sensors/skink/main.c

See examples/sensors/skink

/*
* ZentriOS SDK LICENSE AGREEMENT | Zentri.com, 2016.
*
* Use of source code and/or libraries contained in the ZentriOS SDK is
* subject to the Zentri Operating System SDK license agreement and
* applicable open source license agreements.
*
*/
/* Documentation for this app is available online.
* See https://docs.zentri.com/wifi/sdk/latest/examples/sensors/skink
*/
#include "zos.h"
#include "sensor.h"
#include "hygrometer.h"
#include "thermometer.h"
#include "light.h"
#include "airquality.h"
#define AIR_READ_PERIOD 2000 // ms
#define LIGHT_READ_PERIOD 2000 // ms
#define HYGROMETER_READ_PERIOD 1000 // ms
#define THERMOMETER_READ_PERIOD 1000 // ms
#define ALL_SENSORS_LOW_RATE_PERIOD 5000 // ms
#define AIR_STREAM_NAME "airstream"
#define LIGHT_STREAM_NAME "lightstream"
#define HYGROMETER_STREAM_NAME "hygrometer"
#define THERMOMETER_STREAM_NAME "thermometer"
static zos_bool_t is_initialized;
static zos_result_t initialise_sensors(void);
static zos_result_t air_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg);
static zos_result_t light_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg);
static zos_result_t hygrometer_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg);
static zos_result_t thermometer_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg);
static void air_read_event_handler(void *arg);
static void light_read_event_handler(void *arg);
static void hygrometer_read_event_handler(void *arg);
static void thermometer_read_event_handler(void *arg);
static void all_sensors_read_event_handler(void *arg);
static zos_result_t send_air_sensor_data(const zos_hs_handle_t handle, uint16_t co2_equ, uint16_t tvoc);
static zos_result_t send_light_sensor_data(const zos_hs_handle_t handle, uint32_t lux);
static zos_result_t send_hygrometer_data(const zos_hs_handle_t handle, uint32_t rh);
static zos_result_t send_thermometer_data(const zos_hs_handle_t handle, uint32_t temp);
static zos_result_t get_sensor_data(sensor_id_t sensor, void* data);
static zos_result_t send_data(const zos_hs_handle_t handle, const char *stream, const char *data);
/*************************************************************************************************/
void zn_app_init(void)
{
zos_result_t result;
ZOS_LOG("Starting Skink Environmental Sensor Demo");
if(ZOS_FAILED(result, zn_load_app_settings("skink.ini")))
{
ZOS_LOG("Failed to load app settings: %d", result);
return;
}
// power up the air quality sensor via the SENSOR_EN GPIO
if (ZOS_FAILED(result, initialise_sensors()))
{
ZOS_LOG("Failed to initialize sensors");
return;
}
{
ZOS_LOG("Failed to restart network: %d", result);
}
else
{
{
ZOS_LOG("Failed to start the HTTP server!");
}
else
{
ZOS_LOG("Connect with a Wi-Fi client to: Skink / password");
ZOS_LOG("Using a browser, go to http://skink.com");
is_initialized = ZOS_TRUE;
}
}
zn_hs_stream_register_callback(AIR_STREAM_NAME, air_stream_callback, NULL);
zn_hs_stream_register_callback(LIGHT_STREAM_NAME, light_stream_callback, NULL);
zn_hs_stream_register_callback(HYGROMETER_STREAM_NAME, hygrometer_stream_callback, NULL);
zn_hs_stream_register_callback(THERMOMETER_STREAM_NAME, thermometer_stream_callback, NULL);
// initially, register a periodic function to read all sensor data at low rate (for testing)
zn_event_register_periodic(all_sensors_read_event_handler, NULL, ALL_SENSORS_LOW_RATE_PERIOD, EVENT_FLAGS1(RUN_NOW));
}
/*************************************************************************************************/
void zn_app_deinit(void)
{
zn_event_unregister(all_sensors_read_event_handler, NULL);
}
/*************************************************************************************************/
zos_bool_t zn_app_idle(void)
{
// return TRUE so the event loop idles
return is_initialized;
}
/*************************************************************************************************/
static zos_result_t initialise_sensors(void)
{
zos_result_t result;
if (ZOS_FAILED(result, sensor_init(SENSOR_HYGROMETER, NULL)))
{
ZOS_LOG("ERROR - Failed to initialize hygrometer!");
retval = result;
}
if (ZOS_FAILED(result, sensor_init(SENSOR_THERMOMETER, NULL)))
{
ZOS_LOG("ERROR - Failed to initialize thermometer!");
retval = result;
}
if (ZOS_FAILED(result, sensor_init(SENSOR_AIRQUALITY, NULL)))
{
ZOS_LOG("ERROR - Failed to initialize air quality sensor!");
retval = result;
}
if (ZOS_FAILED(result, sensor_init(SENSOR_LIGHT, NULL)))
{
ZOS_LOG("ERROR - Failed to initialize light sensor!");
retval = result;
}
return retval;
}
/*************************************************************************************************/
static zos_result_t air_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg)
{
if(method == HS_STREAM_LISTEN)
{
ZOS_LOG("Air stream listener registered, streaming data");
zn_event_register_periodic(air_read_event_handler, handle, AIR_READ_PERIOD, EVENT_FLAGS1(RUN_NOW));
// client connected.. stop the background periodic reader
zn_event_unregister(all_sensors_read_event_handler, NULL);
}
else if(method == HS_STREAM_UNLISTEN)
{
ZOS_LOG("Air stream listener unregistered");
zn_event_unregister(air_read_event_handler, handle);
}
else if(method == HS_STREAM_READ)
{
char *update_interval_str;
if(zn_hs_stream_read(handle, &update_interval_str, NULL) == ZOS_SUCCESS)
{
uint32_t update_interval = str_to_uint32(update_interval_str);
zn_event_update_periodic(air_read_event_handler, handle, update_interval, EVENT_FLAGS1(RUN_NOW));
ZOS_LOG("Air quality sensor update interval: %d", update_interval);
}
}
return ZOS_SUCCESS;
}
/*************************************************************************************************/
static zos_result_t light_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg)
{
if(method == HS_STREAM_LISTEN)
{
ZOS_LOG("Light stream listener registered, streaming data");
zn_event_register_periodic(light_read_event_handler, handle, LIGHT_READ_PERIOD, EVENT_FLAGS1(RUN_NOW));
// client connected.. stop the background periodic reader
zn_event_unregister(all_sensors_read_event_handler, NULL);
}
else if(method == HS_STREAM_UNLISTEN)
{
ZOS_LOG("Light stream listener unregistered");
zn_event_unregister(light_read_event_handler, handle);
}
else if(method == HS_STREAM_READ)
{
char *update_interval_str;
if(zn_hs_stream_read(handle, &update_interval_str, NULL) == ZOS_SUCCESS)
{
uint32_t update_interval = str_to_uint32(update_interval_str);
zn_event_update_periodic(light_read_event_handler, handle, update_interval, EVENT_FLAGS1(RUN_NOW));
ZOS_LOG("Light sensor update interval: %d", update_interval);
}
}
return ZOS_SUCCESS;
}
/*************************************************************************************************/
static zos_result_t hygrometer_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg)
{
if(method == HS_STREAM_LISTEN)
{
ZOS_LOG("Hygrometer stream listener registered, streaming data");
zn_event_register_periodic(hygrometer_read_event_handler, handle, HYGROMETER_READ_PERIOD, EVENT_FLAGS1(RUN_NOW));
// client connected.. stop the background periodic reader
zn_event_unregister(all_sensors_read_event_handler, NULL);
}
else if(method == HS_STREAM_UNLISTEN)
{
ZOS_LOG("Hygrometer stream listener unregistered");
zn_event_unregister(hygrometer_read_event_handler, handle);
}
else if(method == HS_STREAM_READ)
{
char *update_interval_str;
if(zn_hs_stream_read(handle, &update_interval_str, NULL) == ZOS_SUCCESS)
{
uint32_t update_interval = str_to_uint32(update_interval_str);
zn_event_update_periodic(hygrometer_read_event_handler, handle, update_interval, EVENT_FLAGS1(RUN_NOW));
ZOS_LOG("Hygrometer update interval: %d", update_interval);
}
}
return ZOS_SUCCESS;
}
/*************************************************************************************************/
static zos_result_t thermometer_stream_callback(zos_hs_handle_t handle, const char *stream, zos_hs_stream_method_t method, void *arg)
{
if(method == HS_STREAM_LISTEN)
{
ZOS_LOG("Thermometer stream listener registered, streaming data");
zn_event_register_periodic(thermometer_read_event_handler, handle, THERMOMETER_READ_PERIOD, EVENT_FLAGS1(RUN_NOW));
// client connected.. stop the background periodic reader
zn_event_unregister(all_sensors_read_event_handler, NULL);
}
else if(method == HS_STREAM_UNLISTEN)
{
ZOS_LOG("Thermometer stream listener unregistered");
zn_event_unregister(thermometer_read_event_handler, handle);
}
else if(method == HS_STREAM_READ)
{
char *update_interval_str;
if(zn_hs_stream_read(handle, &update_interval_str, NULL) == ZOS_SUCCESS)
{
uint32_t update_interval = str_to_uint32(update_interval_str);
zn_event_update_periodic(thermometer_read_event_handler, handle, update_interval, EVENT_FLAGS1(RUN_NOW));
ZOS_LOG("Thermometer update interval: %d", update_interval);
}
}
return ZOS_SUCCESS;
}
/*************************************************************************************************/
static void air_read_event_handler(void *arg)
{
airquality_data_t air_data;
zos_result_t result;
if (ZOS_FAILED(result, get_sensor_data(SENSOR_AIRQUALITY, &air_data)))
{
ZOS_LOG("Failed to get air quality sensor data!");
}
else
{
send_air_sensor_data(handle, air_data.co2_equ, air_data.tvoc);
}
}
/*************************************************************************************************/
static void light_read_event_handler(void *arg)
{
light_data_t light_data;
zos_result_t result;
if (ZOS_FAILED(result, get_sensor_data(SENSOR_LIGHT, &light_data)))
{
ZOS_LOG("Failed to get light sensor data!");
}
else
{
// ZOS_LOG("Raw (0x%04X), Exponent(%u), Mantissa (%u)", raw, exponent, mantissa);
send_light_sensor_data(handle, light_data.lux);
}
}
/*************************************************************************************************/
static void hygrometer_read_event_handler(void *arg)
{
hygrometer_data_t hygrometer_data;
zos_result_t result;
if (ZOS_FAILED(result, get_sensor_data(SENSOR_HYGROMETER, &hygrometer_data)))
{
ZOS_LOG("Failed to get hygrometer data!");
}
else
{
send_hygrometer_data(handle, hygrometer_data.raw);
}
}
/*************************************************************************************************/
static void thermometer_read_event_handler(void *arg)
{
thermometer_data_t thermometer_data;
zos_result_t result;
if (ZOS_FAILED(result, get_sensor_data(SENSOR_THERMOMETER, &thermometer_data)))
{
ZOS_LOG("Failed to get thermometer data!");
}
else
{
send_thermometer_data(handle, thermometer_data.raw);
}
}
/*************************************************************************************************/
static void all_sensors_read_event_handler(void *arg)
{
zos_result_t result;
static airquality_data_t air_data;
static light_data_t light_data;
static hygrometer_data_t hygrometer_data;
static thermometer_data_t thermometer_data;
if (ZOS_FAILED(result, get_sensor_data(SENSOR_AIRQUALITY, &air_data)))
{
ZOS_LOG("CO2 = FAILED");
ZOS_LOG("tVOC = FAILED");
}
else
{
ZOS_LOG("CO2 = %d", air_data.co2_equ);
ZOS_LOG("tVOC = %d", air_data.tvoc);
}
if (ZOS_FAILED(result, get_sensor_data(SENSOR_LIGHT, &light_data)))
{
ZOS_LOG("LUX = FAILED");
}
else
{
ZOS_LOG("LUX = %u", light_data.lux);
}
if (ZOS_FAILED(result, get_sensor_data(SENSOR_HYGROMETER, &hygrometer_data)))
{
ZOS_LOG("RH = FAILED");
}
else
{
ZOS_LOG("RH = %u", hygrometer_data.raw);
}
if (ZOS_FAILED(result, get_sensor_data(SENSOR_THERMOMETER, &thermometer_data)))
{
ZOS_LOG("Temp = FAILED");
}
else
{
ZOS_LOG("Temp = %d", (int)thermometer_data.raw);
}
}
/*************************************************************************************************/
static zos_result_t send_air_sensor_data(const zos_hs_handle_t handle, uint16_t co2_equ, uint16_t tvoc)
{
char buffer[20];
ZOS_LOG("CO2 = %d [ppm]", co2_equ);
ZOS_LOG("tVOC = %d [ppb]\n\r", tvoc);
sprintf(buffer, "{\"tvoc\":%d}", (int)tvoc);
return send_data(handle, AIR_STREAM_NAME, buffer);
}
/*************************************************************************************************/
static zos_result_t send_light_sensor_data(const zos_hs_handle_t handle, uint32_t lux)
{
char buffer[20];
ZOS_LOG("LUX = %u\n\r", lux);
sprintf(buffer, "{\"lux\":%u}", (unsigned int)lux);
return send_data(handle, LIGHT_STREAM_NAME, buffer);
}
/*************************************************************************************************/
static zos_result_t send_hygrometer_data(const zos_hs_handle_t handle, uint32_t rh)
{
char buffer[20];
ZOS_LOG("RH = %u\n\r", rh);
sprintf(buffer, "{\"RH\":%u}", (unsigned int)rh);
return send_data(handle, HYGROMETER_STREAM_NAME, buffer);
}
/*************************************************************************************************/
static zos_result_t send_thermometer_data(const zos_hs_handle_t handle, uint32_t temp)
{
char buffer[20];
ZOS_LOG("Temp = %d\n\r", (int)temp);
sprintf(buffer, "{\"temp_c\":%d}", (int)temp);
return send_data(handle, THERMOMETER_STREAM_NAME, buffer);
}
/*************************************************************************************************/
static zos_result_t send_data(const zos_hs_handle_t handle, const char *stream, const char *data)
{
zos_buffer_t json_buffer =
{
.data = (uint8_t*)data,
.size = strlen(data)
};
// json encode the string in-place
json_encode_buffer(&json_buffer);
return zn_hs_stream_write_listener(handle, stream, data, ZOS_TRUE);
}
/*************************************************************************************************/
static zos_result_t get_sensor_data(sensor_id_t sensor, void* data)
{
zos_bool_t has_data = ZOS_FALSE;
if (sensor_has_new_data(sensor, &has_data) == ZOS_SUCCESS)
{
if (has_data == ZOS_TRUE)
{
if (sensor_get_data(sensor, data) != ZOS_SUCCESS)
{
ZOS_LOG("Failed to get data!");
}
else
{
result = ZOS_SUCCESS;
}
}
else
{
ZOS_LOG("No new data!");
result = ZOS_SUCCESS;
}
}
else
{
ZOS_LOG("Failed to check for new data!");
}
return result;
}