Weather Application Example - Full Source Code
The source code below is the completed
main.c
from the tutorial
Native C Application Development Tutorial
. To compile the source code successfully, several steps in the tutorial must be completed.
/*
* EVALUATION AND USE OF THIS SOFTWARE IS SUBJECT TO THE TERMS AND
* CONDITIONS OF THE CONTROLLING LICENSE AGREEMENT FOUND AT LICENSE.md
* IN THIS SDK. IF YOU DO NOT AGREE TO THE LICENSE TERMS AND CONDITIONS,
* PLEASE RETURN ALL SOURCE FILES TO SILICON LABORATORIES.
* (c) Copyright 2018, Silicon Laboratories Inc. All rights reserved.
*/
#include "gos.h"
#include "si7013.h"
#define WEATHER_REPORT_PERIOD_MS 10000
#define SI7021_MEASUREMENT_TIME_MS 50 // the si7021 takes max 50ms to perform measurement
static gos_i2c_device_t si7021_device =
{
.port = PLATFORM_STD_I2C,
.address = SI7021_ADDR >> 1,
.speed = GOS_I2C_CLOCK_HIGH_SPEED,
.read_timeout = 50, //si7021 can take up to 25ms to finish a conversion
.retries = 0,
.flags = 0
};
// ------------------------------------------------------------------------------------------------
void gos_app_init(void)
{ uint8_t part_id = 0;
uint8_t part_rev = 0;
// Print to the serial terminal
GOS_LOG("Weather Demo");
gos_load_app_settings_once("settings.ini", 1);
gos_network_register_event_handler(GOS_INTERFACE_WLAN, wlan_network_event_handler);
gos_setup_register_finished_event_handler(setup_finished_handler);
start_network_interface();
// Detect the Si7021 and read the firmware version
Si7013_Detect(&si7021_device, 0, &part_id);
Si7013_GetFirmwareRevision(&si7021_device, 0, &part_rev);
if(part_id == SI7021_DEVICE_ID)
GOS_LOG("Detected Si7021 Version %d.%d", ((part_rev >> 4) & 0xF), (part_rev & 0xF));
else
GOS_LOG("Si7021 Not Detected");
gos_event_register_periodic(start_measurement_event_handler, 0, WEATHER_REPORT_PERIOD_MS, 0);
}
// ------------------------------------------------------------------------------------------------
// Try to start WLAN interface
// If fail to start, then start web setup
// NOTE: Web setup will idle timeout after setup.web.idle_timeout seconds
// Upon timeout, the system is rebooted.
// ------------------------------------------------------------------------------------------------
static void start_network_interface(void)
{
gos_result_t result;
GOS_LOG("\r\n\r\nChecking if device is able to connect to local network ...");
if (GOS_FAILED(result, gos_network_up(GOS_INTERFACE_WLAN, true)))
{
GOS_LOG("Failed to join local network, starting Web Setup");
if (GOS_FAILED(result, gos_setup_start()))
{
GOS_LOG("Failed to start Web Setup, rebooting");
gos_system_reboot();
}
else
{
char buffer_url[128];
char buffer_username[64];
char buffer_passkey[64];
uint32_t idle_timeout;
gos_settings_get_uint32("setup.web.idle_timeout", &idle_timeout);
get_setup_url("setup.web.url", buffer_url, sizeof(buffer_url));
get_device_name("setup.web.ssid", buffer_username, sizeof(buffer_username));
gos_settings_get_print_str("setup.web.passkey", buffer_passkey, sizeof(buffer_passkey));
GOS_LOG("Device Web Setup started");
GOS_LOG("1. Connect to Wi-Fi network: %s with passkey: %s", buffer_username, buffer_passkey);
GOS_LOG("2. Open browser to http://%s", buffer_url);
GOS_LOG("3. Setup the device\r\n");
if(idle_timeout != 0)
GOS_LOG("NOTE: Web setup will idle timeout after %d seconds\r\n", idle_timeout);
}
}
else
{
GOS_LOG("Device WLAN started");
}
}
// ------------------------------------------------------------------------------------------------
// Event handler for WLAN interface events
// ------------------------------------------------------------------------------------------------
static void wlan_network_event_handler(bool is_up)
{
// If the WLAN interface has gone down AND softAP interface is NOT up try to restart the WLAN interface
if ((is_up == false) && (gos_network_is_up(GOS_INTERFACE_SOFTAP) == false))
{
// If the network goes down try to restart it, else start web setup
start_network_interface();
}
}
// ------------------------------------------------------------------------------------------------
// Just reboot the system when web setup finishes
// ------------------------------------------------------------------------------------------------
static void setup_finished_handler(void *unsed)
{
GOS_LOG("Web setup finished, rebooting system");
gos_system_reboot();
}
// ------------------------------------------------------------------------------------------------
// Convert '#' to last three chars of device's MAC address
// ------------------------------------------------------------------------------------------------
static const char* get_device_name(const char *setting, char *buffer, size_t buffer_length)
{
int setting_len;
char *setting_ptr;
gos_settings_get_print_str(setting, buffer, buffer_length);
setting_len = strlen(buffer);
setting_ptr = &buffer[setting_len-1];
if (*setting_ptr == '#')
{
char mac_str[20];
// Example output:
// 4C:55:CC:10:78:9B
gos_settings_get_print_str("softap.mac", mac_str, sizeof(mac_str));
*setting_ptr++ = mac_str[13];
*setting_ptr++ = mac_str[15];
*setting_ptr++ = mac_str[16];
*setting_ptr = 0;
}
return buffer;
}
// ------------------------------------------------------------------------------------------------
// When the first entry in the setup.web.url domain list
// ------------------------------------------------------------------------------------------------
static const char* get_setup_url(const char *setting, char *buffer, size_t buffer_length)
{
gos_settings_get_print_str("setup.web.url", buffer, buffer_length);
char *comma_ptr = strchr(buffer, ',');
*comma_ptr = 0;
return buffer;
}
// ------------------------------------------------------------------------------------------------
// Start the measurement then schedule a timed event to read the measurment
// ------------------------------------------------------------------------------------------------
static void start_measurement_event_handler(void *arg)
{
//Initiate the measurment
Si7013_StartNoHoldMeasureRHAndTemp(&si7021_device, 0);
// The Si7013 takes a maximum of 50ms to complete a measurement
// therefore we register an event to read the results 50ms later
gos_event_register_timed(read_and_report_event_handler, arg, SI7021_MEASUREMENT_TIME_MS, 0);
}
// ------------------------------------------------------------------------------------------------
// Read the measurement then report the results
// ------------------------------------------------------------------------------------------------
static void read_and_report_event_handler(void *arg)
{ gos_result_t result = GOS_SUCCESS;
uint32_t rh_data;
int32_t temp_data;
char temp_float_str[10];
char rh_float_str[10];
//Read the measurement results
Si7013_ReadNoHoldRHAndTemp(&si7021_device, 0, &rh_data, &temp_data);
//Format the results to a floating point number and output to the console
GOS_LOG("Temp: %s C | RH: %s %%",
float_to_str((float)(temp_data/1000.0), temp_float_str, 1),
float_to_str((float)(rh_data/1000.0), rh_float_str, 1));
}
// ------------------------------------------------------------------------------------------------
void gos_app_deinit(void)
{
// This API is called just before the application finishes.
// Anything initialized or allocated by the app should be cleaned here.
// This API is optional.
}
// ------------------------------------------------------------------------------------------------
void gos_app_idle(void)
{
// This is called when the event thread has no more pending events.
// This API is optional.
}