67045d4012
The current version of the CC26xx web demo publishes over MQTT the default parent's IPv6 address and the last observed RSSI of this link. This is collected by active probing (periodic ping). This commit brings the probing functionality to the example's main code module. The MQTT client keeps publishing as previously, but we now also export the same information through CoAP resources. Configuration is still possible through the example's web server.
972 lines
30 KiB
C
972 lines
30 KiB
C
/*
|
|
* Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the copyright holder nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/**
|
|
* \addtogroup cc26xx-web-demo
|
|
* @{
|
|
*
|
|
* \file
|
|
* Main module for the CC26XX web demo. Activates on-device resources,
|
|
* takes sensor readings periodically and caches them for all other modules
|
|
* to use.
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
|
#include "contiki.h"
|
|
#include "contiki-net.h"
|
|
#include "rest-engine.h"
|
|
#include "board-peripherals.h"
|
|
#include "lib/sensors.h"
|
|
#include "lib/list.h"
|
|
#include "sys/process.h"
|
|
#include "net/ipv6/sicslowpan.h"
|
|
#include "button-sensor.h"
|
|
#include "batmon-sensor.h"
|
|
#include "httpd-simple.h"
|
|
#include "cc26xx-web-demo.h"
|
|
#include "mqtt-client.h"
|
|
#include "coap-server.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS_NAME(cetic_6lbr_client_process);
|
|
PROCESS(cc26xx_web_demo_process, "CC26XX Web Demo");
|
|
/*---------------------------------------------------------------------------*/
|
|
/*
|
|
* Update sensor readings in a staggered fashion every SENSOR_READING_PERIOD
|
|
* ticks + a random interval between 0 and SENSOR_READING_RANDOM ticks
|
|
*/
|
|
#define SENSOR_READING_PERIOD (CLOCK_SECOND * 20)
|
|
#define SENSOR_READING_RANDOM (CLOCK_SECOND << 4)
|
|
|
|
struct ctimer batmon_timer;
|
|
|
|
#if BOARD_SENSORTAG
|
|
struct ctimer bmp_timer, hdc_timer, tmp_timer, opt_timer, mpu_timer;
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Provide visible feedback via LEDS while searching for a network */
|
|
#define NO_NET_LED_DURATION (CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC >> 1)
|
|
|
|
static struct etimer et;
|
|
static struct ctimer ct;
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Parent RSSI functionality */
|
|
#if CC26XX_WEB_DEMO_READ_PARENT_RSSI
|
|
static struct uip_icmp6_echo_reply_notification echo_reply_notification;
|
|
static struct etimer echo_request_timer;
|
|
int def_rt_rssi = 0;
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
process_event_t cc26xx_web_demo_publish_event;
|
|
process_event_t cc26xx_web_demo_config_loaded_event;
|
|
process_event_t cc26xx_web_demo_load_config_defaults;
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Saved settings on flash: store, offset, magic */
|
|
#define CONFIG_FLASH_OFFSET 0
|
|
#define CONFIG_MAGIC 0xCC265002
|
|
|
|
cc26xx_web_demo_config_t cc26xx_web_demo_config;
|
|
/*---------------------------------------------------------------------------*/
|
|
/* A cache of sensor values. Updated periodically or upon key press */
|
|
LIST(sensor_list);
|
|
/*---------------------------------------------------------------------------*/
|
|
/* The objects representing sensors used in this demo */
|
|
#define DEMO_SENSOR(name, type, descr, xml_element, form_field, units) \
|
|
cc26xx_web_demo_sensor_reading_t name##_reading = \
|
|
{ NULL, 0, 0, descr, xml_element, form_field, units, type, 1, 1 }
|
|
|
|
/* CC26xx sensors */
|
|
DEMO_SENSOR(batmon_temp, CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP,
|
|
"Battery Temp", "battery-temp", "batmon_temp",
|
|
CC26XX_WEB_DEMO_UNIT_TEMP);
|
|
DEMO_SENSOR(batmon_volt, CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT,
|
|
"Battery Volt", "battery-volt", "batmon_volt",
|
|
CC26XX_WEB_DEMO_UNIT_VOLT);
|
|
|
|
/* Sensortag sensors */
|
|
#if BOARD_SENSORTAG
|
|
DEMO_SENSOR(bmp_pres, CC26XX_WEB_DEMO_SENSOR_BMP_PRES,
|
|
"Air Pressure", "air-pressure", "bmp_pres",
|
|
CC26XX_WEB_DEMO_UNIT_PRES);
|
|
DEMO_SENSOR(bmp_temp, CC26XX_WEB_DEMO_SENSOR_BMP_TEMP,
|
|
"Air Temp", "air-temp", "bmp_temp",
|
|
CC26XX_WEB_DEMO_UNIT_TEMP);
|
|
DEMO_SENSOR(hdc_temp, CC26XX_WEB_DEMO_SENSOR_HDC_TEMP,
|
|
"HDC Temp", "hdc-temp", "hdc_temp",
|
|
CC26XX_WEB_DEMO_UNIT_TEMP);
|
|
DEMO_SENSOR(hdc_hum, CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY,
|
|
"HDC Humidity", "hdc-humidity", "hdc_hum",
|
|
CC26XX_WEB_DEMO_UNIT_HUMIDITY);
|
|
DEMO_SENSOR(tmp_amb, CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT,
|
|
"Ambient Temp", "ambient-temp", "tmp_amb",
|
|
CC26XX_WEB_DEMO_UNIT_TEMP);
|
|
DEMO_SENSOR(tmp_obj, CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT,
|
|
"Object Temp", "object-temp", "tmp_obj",
|
|
CC26XX_WEB_DEMO_UNIT_TEMP);
|
|
DEMO_SENSOR(opt, CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT,
|
|
"Light", "light", "light",
|
|
CC26XX_WEB_DEMO_UNIT_LIGHT);
|
|
|
|
/* MPU Readings */
|
|
DEMO_SENSOR(mpu_acc_x, CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X,
|
|
"Acc X", "acc-x", "acc_x",
|
|
CC26XX_WEB_DEMO_UNIT_ACC);
|
|
DEMO_SENSOR(mpu_acc_y, CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y,
|
|
"Acc Y", "acc-y", "acc_y",
|
|
CC26XX_WEB_DEMO_UNIT_ACC);
|
|
DEMO_SENSOR(mpu_acc_z, CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z,
|
|
"Acc Z", "acc-z", "acc_z",
|
|
CC26XX_WEB_DEMO_UNIT_ACC);
|
|
|
|
DEMO_SENSOR(mpu_gyro_x, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X,
|
|
"Gyro X", "gyro-x", "gyro_x",
|
|
CC26XX_WEB_DEMO_UNIT_GYRO);
|
|
DEMO_SENSOR(mpu_gyro_y, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y,
|
|
"Gyro Y", "gyro-y", "gyro_y",
|
|
CC26XX_WEB_DEMO_UNIT_GYRO);
|
|
DEMO_SENSOR(mpu_gyro_z, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z,
|
|
"Gyro Z", "gyro-z", "gyro_Z",
|
|
CC26XX_WEB_DEMO_UNIT_GYRO);
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
#if BOARD_SENSORTAG
|
|
static void init_bmp_reading(void *data);
|
|
static void init_light_reading(void *data);
|
|
static void init_hdc_reading(void *data);
|
|
static void init_tmp_reading(void *data);
|
|
static void init_mpu_reading(void *data);
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
publish_led_off(void *d)
|
|
{
|
|
leds_off(CC26XX_WEB_DEMO_STATUS_LED);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
save_config()
|
|
{
|
|
/* Dump current running config to flash */
|
|
#if BOARD_SENSORTAG
|
|
int rv;
|
|
cc26xx_web_demo_sensor_reading_t *reading = NULL;
|
|
|
|
rv = ext_flash_open();
|
|
|
|
if(!rv) {
|
|
printf("Could not open flash to save config\n");
|
|
ext_flash_close();
|
|
return;
|
|
}
|
|
|
|
rv = ext_flash_erase(CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t));
|
|
|
|
if(!rv) {
|
|
printf("Error erasing flash\n");
|
|
} else {
|
|
cc26xx_web_demo_config.magic = CONFIG_MAGIC;
|
|
cc26xx_web_demo_config.len = sizeof(cc26xx_web_demo_config_t);
|
|
cc26xx_web_demo_config.sensors_bitmap = 0;
|
|
|
|
for(reading = list_head(sensor_list);
|
|
reading != NULL;
|
|
reading = list_item_next(reading)) {
|
|
if(reading->publish) {
|
|
cc26xx_web_demo_config.sensors_bitmap |= (1 << reading->type);
|
|
}
|
|
}
|
|
|
|
rv = ext_flash_write(CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t),
|
|
(uint8_t *)&cc26xx_web_demo_config);
|
|
if(!rv) {
|
|
printf("Error saving config\n");
|
|
}
|
|
}
|
|
|
|
ext_flash_close();
|
|
#endif
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
load_config()
|
|
{
|
|
#if BOARD_SENSORTAG
|
|
/* Read from flash into a temp buffer */
|
|
cc26xx_web_demo_config_t tmp_cfg;
|
|
cc26xx_web_demo_sensor_reading_t *reading = NULL;
|
|
|
|
int rv = ext_flash_open();
|
|
|
|
if(!rv) {
|
|
printf("Could not open flash to load config\n");
|
|
ext_flash_close();
|
|
return;
|
|
}
|
|
|
|
rv = ext_flash_read(CONFIG_FLASH_OFFSET, sizeof(tmp_cfg),
|
|
(uint8_t *)&tmp_cfg);
|
|
|
|
ext_flash_close();
|
|
|
|
if(!rv) {
|
|
printf("Error loading config\n");
|
|
return;
|
|
}
|
|
|
|
if(tmp_cfg.magic == CONFIG_MAGIC && tmp_cfg.len == sizeof(tmp_cfg)) {
|
|
memcpy(&cc26xx_web_demo_config, &tmp_cfg, sizeof(cc26xx_web_demo_config));
|
|
}
|
|
|
|
for(reading = list_head(sensor_list);
|
|
reading != NULL;
|
|
reading = list_item_next(reading)) {
|
|
if(cc26xx_web_demo_config.sensors_bitmap & (1 << reading->type)) {
|
|
reading->publish = 1;
|
|
} else {
|
|
reading->publish = 0;
|
|
snprintf(reading->converted, CC26XX_WEB_DEMO_CONVERTED_LEN, "\"N/A\"");
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Don't start everything here, we need to dictate order of initialisation */
|
|
AUTOSTART_PROCESSES(&cc26xx_web_demo_process);
|
|
/*---------------------------------------------------------------------------*/
|
|
int
|
|
cc26xx_web_demo_ipaddr_sprintf(char *buf, uint8_t buf_len,
|
|
const uip_ipaddr_t *addr)
|
|
{
|
|
uint16_t a;
|
|
uint8_t len = 0;
|
|
int i, f;
|
|
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
|
|
a = (addr->u8[i] << 8) + addr->u8[i + 1];
|
|
if(a == 0 && f >= 0) {
|
|
if(f++ == 0) {
|
|
len += snprintf(&buf[len], buf_len - len, "::");
|
|
}
|
|
} else {
|
|
if(f > 0) {
|
|
f = -1;
|
|
} else if(i > 0) {
|
|
len += snprintf(&buf[len], buf_len - len, ":");
|
|
}
|
|
len += snprintf(&buf[len], buf_len - len, "%x", a);
|
|
}
|
|
}
|
|
|
|
return len;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
const cc26xx_web_demo_sensor_reading_t *
|
|
cc26xx_web_demo_sensor_lookup(int sens_type)
|
|
{
|
|
cc26xx_web_demo_sensor_reading_t *reading = NULL;
|
|
|
|
for(reading = list_head(sensor_list);
|
|
reading != NULL;
|
|
reading = list_item_next(reading)) {
|
|
if(reading->type == sens_type) {
|
|
return reading;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
const cc26xx_web_demo_sensor_reading_t *
|
|
cc26xx_web_demo_sensor_first()
|
|
{
|
|
return list_head(sensor_list);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
void
|
|
cc26xx_web_demo_restore_defaults(void)
|
|
{
|
|
cc26xx_web_demo_sensor_reading_t *reading = NULL;
|
|
|
|
leds_on(LEDS_ALL);
|
|
|
|
for(reading = list_head(sensor_list);
|
|
reading != NULL;
|
|
reading = list_item_next(reading)) {
|
|
reading->publish = 1;
|
|
}
|
|
|
|
#if CC26XX_WEB_DEMO_MQTT_CLIENT
|
|
process_post_synch(&mqtt_client_process,
|
|
cc26xx_web_demo_load_config_defaults, NULL);
|
|
#endif
|
|
|
|
#if CC26XX_WEB_DEMO_NET_UART
|
|
process_post_synch(&net_uart_process, cc26xx_web_demo_load_config_defaults,
|
|
NULL);
|
|
#endif
|
|
|
|
save_config();
|
|
|
|
leds_off(LEDS_ALL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int
|
|
defaults_post_handler(char *key, int key_len, char *val, int val_len)
|
|
{
|
|
if(key_len != strlen("defaults") ||
|
|
strncasecmp(key, "defaults", strlen("defaults")) != 0) {
|
|
/* Not ours */
|
|
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
|
}
|
|
|
|
cc26xx_web_demo_restore_defaults();
|
|
|
|
return HTTPD_SIMPLE_POST_HANDLER_OK;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int
|
|
sensor_readings_handler(char *key, int key_len, char *val, int val_len)
|
|
{
|
|
cc26xx_web_demo_sensor_reading_t *reading = NULL;
|
|
int rv;
|
|
|
|
for(reading = list_head(sensor_list);
|
|
reading != NULL;
|
|
reading = list_item_next(reading)) {
|
|
if(key_len == strlen(reading->form_field) &&
|
|
strncmp(reading->form_field, key, strlen(key)) == 0) {
|
|
|
|
rv = atoi(val);
|
|
|
|
/* Be pedantic: only accept 0 and 1, not just any non-zero value */
|
|
if(rv == 0) {
|
|
reading->publish = 0;
|
|
snprintf(reading->converted, CC26XX_WEB_DEMO_CONVERTED_LEN, "\"N/A\"");
|
|
} else if(rv == 1) {
|
|
reading->publish = 1;
|
|
} else {
|
|
return HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
|
}
|
|
|
|
return HTTPD_SIMPLE_POST_HANDLER_OK;
|
|
}
|
|
}
|
|
|
|
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
#if CC26XX_WEB_DEMO_READ_PARENT_RSSI
|
|
static int
|
|
ping_interval_post_handler(char *key, int key_len, char *val, int val_len)
|
|
{
|
|
int rv = 0;
|
|
|
|
if(key_len != strlen("ping_interval") ||
|
|
strncasecmp(key, "ping_interval", strlen("ping_interval")) != 0) {
|
|
/* Not ours */
|
|
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
|
}
|
|
|
|
rv = atoi(val);
|
|
|
|
if(rv < CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MIN ||
|
|
rv > CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MAX) {
|
|
return HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
|
}
|
|
|
|
cc26xx_web_demo_config.def_rt_ping_interval = rv * CLOCK_SECOND;
|
|
|
|
return HTTPD_SIMPLE_POST_HANDLER_OK;
|
|
}
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
HTTPD_SIMPLE_POST_HANDLER(sensor, sensor_readings_handler);
|
|
HTTPD_SIMPLE_POST_HANDLER(defaults, defaults_post_handler);
|
|
|
|
#if CC26XX_WEB_DEMO_READ_PARENT_RSSI
|
|
HTTPD_SIMPLE_POST_HANDLER(ping_interval, ping_interval_post_handler);
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data,
|
|
uint16_t datalen)
|
|
{
|
|
if(uip_ip6addr_cmp(source, uip_ds6_defrt_choose())) {
|
|
def_rt_rssi = sicslowpan_get_last_rssi();
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
ping_parent(void)
|
|
{
|
|
if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) {
|
|
return;
|
|
}
|
|
|
|
uip_icmp6_send(uip_ds6_defrt_choose(), ICMP6_ECHO_REQUEST, 0,
|
|
CC26XX_WEB_DEMO_ECHO_REQ_PAYLOAD_LEN);
|
|
}
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
get_batmon_reading(void *data)
|
|
{
|
|
int value;
|
|
char *buf;
|
|
clock_time_t next = SENSOR_READING_PERIOD +
|
|
(random_rand() % SENSOR_READING_RANDOM);
|
|
|
|
if(batmon_temp_reading.publish) {
|
|
value = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP);
|
|
if(value != CC26XX_SENSOR_READING_ERROR) {
|
|
batmon_temp_reading.raw = value;
|
|
|
|
buf = batmon_temp_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d", value);
|
|
}
|
|
}
|
|
|
|
if(batmon_volt_reading.publish) {
|
|
value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
|
|
if(value != CC26XX_SENSOR_READING_ERROR) {
|
|
batmon_volt_reading.raw = value;
|
|
|
|
buf = batmon_volt_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d", (value * 125) >> 5);
|
|
}
|
|
}
|
|
|
|
ctimer_set(&batmon_timer, next, get_batmon_reading, NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
#if BOARD_SENSORTAG
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
compare_and_update(cc26xx_web_demo_sensor_reading_t *reading)
|
|
{
|
|
if(reading->last == reading->raw) {
|
|
reading->changed = 0;
|
|
} else {
|
|
reading->last = reading->raw;
|
|
reading->changed = 1;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
print_mpu_reading(int reading, char *buf)
|
|
{
|
|
char *loc_buf = buf;
|
|
|
|
if(reading < 0) {
|
|
sprintf(loc_buf, "-");
|
|
reading = -reading;
|
|
loc_buf++;
|
|
}
|
|
|
|
sprintf(loc_buf, "%d.%02d", reading / 100, reading % 100);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
get_bmp_reading()
|
|
{
|
|
int value;
|
|
char *buf;
|
|
clock_time_t next = SENSOR_READING_PERIOD +
|
|
(random_rand() % SENSOR_READING_RANDOM);
|
|
|
|
if(bmp_pres_reading.publish) {
|
|
value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS);
|
|
if(value != CC26XX_SENSOR_READING_ERROR) {
|
|
bmp_pres_reading.raw = value;
|
|
|
|
compare_and_update(&bmp_pres_reading);
|
|
|
|
buf = bmp_pres_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100,
|
|
value % 100);
|
|
}
|
|
}
|
|
|
|
if(bmp_temp_reading.publish) {
|
|
value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_TEMP);
|
|
if(value != CC26XX_SENSOR_READING_ERROR) {
|
|
bmp_temp_reading.raw = value;
|
|
|
|
compare_and_update(&bmp_temp_reading);
|
|
|
|
buf = bmp_temp_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100,
|
|
value % 100);
|
|
}
|
|
}
|
|
|
|
SENSORS_DEACTIVATE(bmp_280_sensor);
|
|
|
|
ctimer_set(&bmp_timer, next, init_bmp_reading, NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
get_tmp_reading()
|
|
{
|
|
int value;
|
|
char *buf;
|
|
clock_time_t next = SENSOR_READING_PERIOD +
|
|
(random_rand() % SENSOR_READING_RANDOM);
|
|
|
|
if(tmp_amb_reading.publish || tmp_obj_reading.publish) {
|
|
if(tmp_007_sensor.value(TMP_007_SENSOR_TYPE_ALL) ==
|
|
CC26XX_SENSOR_READING_ERROR) {
|
|
|
|
SENSORS_DEACTIVATE(tmp_007_sensor);
|
|
ctimer_set(&tmp_timer, next, init_tmp_reading, NULL);
|
|
}
|
|
}
|
|
|
|
if(tmp_amb_reading.publish) {
|
|
value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_AMBIENT);
|
|
tmp_amb_reading.raw = value;
|
|
|
|
compare_and_update(&tmp_amb_reading);
|
|
|
|
buf = tmp_amb_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%03d", value / 1000,
|
|
value % 1000);
|
|
}
|
|
|
|
if(tmp_obj_reading.publish) {
|
|
value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_OBJECT);
|
|
tmp_obj_reading.raw = value;
|
|
|
|
compare_and_update(&tmp_obj_reading);
|
|
|
|
buf = tmp_obj_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%03d", value / 1000,
|
|
value % 1000);
|
|
}
|
|
|
|
SENSORS_DEACTIVATE(tmp_007_sensor);
|
|
|
|
ctimer_set(&tmp_timer, next, init_tmp_reading, NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
get_hdc_reading()
|
|
{
|
|
int value;
|
|
char *buf;
|
|
clock_time_t next = SENSOR_READING_PERIOD +
|
|
(random_rand() % SENSOR_READING_RANDOM);
|
|
|
|
if(hdc_temp_reading.publish) {
|
|
value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP);
|
|
if(value != CC26XX_SENSOR_READING_ERROR) {
|
|
hdc_temp_reading.raw = value;
|
|
|
|
compare_and_update(&hdc_temp_reading);
|
|
|
|
buf = hdc_temp_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100,
|
|
value % 100);
|
|
}
|
|
}
|
|
|
|
if(hdc_hum_reading.publish) {
|
|
value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY);
|
|
if(value != CC26XX_SENSOR_READING_ERROR) {
|
|
hdc_hum_reading.raw = value;
|
|
|
|
compare_and_update(&hdc_hum_reading);
|
|
|
|
buf = hdc_hum_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100,
|
|
value % 100);
|
|
}
|
|
}
|
|
|
|
ctimer_set(&hdc_timer, next, init_hdc_reading, NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
get_light_reading()
|
|
{
|
|
int value;
|
|
char *buf;
|
|
clock_time_t next = SENSOR_READING_PERIOD +
|
|
(random_rand() % SENSOR_READING_RANDOM);
|
|
|
|
value = opt_3001_sensor.value(0);
|
|
|
|
if(value != CC26XX_SENSOR_READING_ERROR) {
|
|
opt_reading.raw = value;
|
|
|
|
compare_and_update(&opt_reading);
|
|
|
|
buf = opt_reading.converted;
|
|
memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100,
|
|
value % 100);
|
|
}
|
|
|
|
/* The OPT will turn itself off, so we don't need to call its DEACTIVATE */
|
|
ctimer_set(&opt_timer, next, init_light_reading, NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
get_mpu_reading()
|
|
{
|
|
clock_time_t next = SENSOR_READING_PERIOD +
|
|
(random_rand() % SENSOR_READING_RANDOM);
|
|
int raw;
|
|
|
|
if(mpu_gyro_x_reading.publish) {
|
|
raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_X);
|
|
if(raw != CC26XX_SENSOR_READING_ERROR) {
|
|
mpu_gyro_x_reading.raw = raw;
|
|
}
|
|
}
|
|
|
|
if(mpu_gyro_y_reading.publish) {
|
|
raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Y);
|
|
if(raw != CC26XX_SENSOR_READING_ERROR) {
|
|
mpu_gyro_y_reading.raw = raw;
|
|
}
|
|
}
|
|
|
|
if(mpu_gyro_z_reading.publish) {
|
|
raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Z);
|
|
if(raw != CC26XX_SENSOR_READING_ERROR) {
|
|
mpu_gyro_z_reading.raw = raw;
|
|
}
|
|
}
|
|
|
|
if(mpu_acc_x_reading.publish) {
|
|
raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_X);
|
|
if(raw != CC26XX_SENSOR_READING_ERROR) {
|
|
mpu_acc_x_reading.raw = raw;
|
|
}
|
|
}
|
|
|
|
if(mpu_acc_y_reading.publish) {
|
|
raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Y);
|
|
if(raw != CC26XX_SENSOR_READING_ERROR) {
|
|
mpu_acc_y_reading.raw = raw;
|
|
}
|
|
}
|
|
|
|
if(mpu_acc_z_reading.publish) {
|
|
raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Z);
|
|
if(raw != CC26XX_SENSOR_READING_ERROR) {
|
|
mpu_acc_z_reading.raw = raw;
|
|
}
|
|
}
|
|
|
|
SENSORS_DEACTIVATE(mpu_9250_sensor);
|
|
|
|
if(mpu_gyro_x_reading.publish) {
|
|
compare_and_update(&mpu_gyro_x_reading);
|
|
memset(mpu_gyro_x_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
print_mpu_reading(mpu_gyro_x_reading.raw, mpu_gyro_x_reading.converted);
|
|
}
|
|
|
|
if(mpu_gyro_y_reading.publish) {
|
|
compare_and_update(&mpu_gyro_y_reading);
|
|
memset(mpu_gyro_y_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
print_mpu_reading(mpu_gyro_y_reading.raw, mpu_gyro_y_reading.converted);
|
|
}
|
|
|
|
if(mpu_gyro_z_reading.publish) {
|
|
compare_and_update(&mpu_gyro_z_reading);
|
|
memset(mpu_gyro_z_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
print_mpu_reading(mpu_gyro_z_reading.raw, mpu_gyro_z_reading.converted);
|
|
}
|
|
|
|
if(mpu_acc_x_reading.publish) {
|
|
compare_and_update(&mpu_acc_x_reading);
|
|
memset(mpu_acc_x_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
print_mpu_reading(mpu_acc_x_reading.raw, mpu_acc_x_reading.converted);
|
|
}
|
|
|
|
if(mpu_acc_y_reading.publish) {
|
|
compare_and_update(&mpu_acc_y_reading);
|
|
memset(mpu_acc_y_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
print_mpu_reading(mpu_acc_y_reading.raw, mpu_acc_y_reading.converted);
|
|
}
|
|
|
|
if(mpu_acc_z_reading.publish) {
|
|
compare_and_update(&mpu_acc_z_reading);
|
|
memset(mpu_acc_z_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN);
|
|
print_mpu_reading(mpu_acc_z_reading.raw, mpu_acc_z_reading.converted);
|
|
}
|
|
|
|
/* We only use the single timer */
|
|
ctimer_set(&mpu_timer, next, init_mpu_reading, NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
init_tmp_reading(void *data)
|
|
{
|
|
if(tmp_amb_reading.publish || tmp_obj_reading.publish) {
|
|
SENSORS_ACTIVATE(tmp_007_sensor);
|
|
} else {
|
|
ctimer_set(&tmp_timer, CLOCK_SECOND, init_tmp_reading, NULL);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
init_bmp_reading(void *data)
|
|
{
|
|
if(bmp_pres_reading.publish || bmp_temp_reading.publish) {
|
|
SENSORS_ACTIVATE(bmp_280_sensor);
|
|
} else {
|
|
ctimer_set(&bmp_timer, CLOCK_SECOND, init_bmp_reading, NULL);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
init_hdc_reading(void *data)
|
|
{
|
|
if(hdc_hum_reading.publish || hdc_temp_reading.publish) {
|
|
SENSORS_ACTIVATE(hdc_1000_sensor);
|
|
} else {
|
|
ctimer_set(&hdc_timer, CLOCK_SECOND, init_hdc_reading, NULL);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
init_light_reading(void *data)
|
|
{
|
|
if(opt_reading.publish) {
|
|
SENSORS_ACTIVATE(opt_3001_sensor);
|
|
} else {
|
|
ctimer_set(&opt_timer, CLOCK_SECOND, init_light_reading, NULL);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
init_mpu_reading(void *data)
|
|
{
|
|
int readings_bitmap = 0;
|
|
|
|
if(mpu_acc_x_reading.publish || mpu_acc_y_reading.publish ||
|
|
mpu_acc_z_reading.publish) {
|
|
readings_bitmap |= MPU_9250_SENSOR_TYPE_ACC;
|
|
}
|
|
|
|
if(mpu_gyro_x_reading.publish || mpu_gyro_y_reading.publish ||
|
|
mpu_gyro_z_reading.publish) {
|
|
readings_bitmap |= MPU_9250_SENSOR_TYPE_GYRO;
|
|
}
|
|
|
|
if(readings_bitmap) {
|
|
mpu_9250_sensor.configure(SENSORS_ACTIVE, readings_bitmap);
|
|
} else {
|
|
ctimer_set(&mpu_timer, CLOCK_SECOND, init_mpu_reading, NULL);
|
|
}
|
|
}
|
|
#endif
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
init_sensor_readings(void)
|
|
{
|
|
/*
|
|
* Make a first pass and get all initial sensor readings. This will also
|
|
* trigger periodic value updates
|
|
*/
|
|
get_batmon_reading(NULL);
|
|
|
|
#if BOARD_SENSORTAG
|
|
init_bmp_reading(NULL);
|
|
init_light_reading(NULL);
|
|
init_hdc_reading(NULL);
|
|
init_tmp_reading(NULL);
|
|
init_mpu_reading(NULL);
|
|
#endif /* BOARD_SENSORTAG */
|
|
|
|
return;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
init_sensors(void)
|
|
{
|
|
|
|
list_add(sensor_list, &batmon_temp_reading);
|
|
list_add(sensor_list, &batmon_volt_reading);
|
|
SENSORS_ACTIVATE(batmon_sensor);
|
|
|
|
#if BOARD_SENSORTAG
|
|
list_add(sensor_list, &bmp_pres_reading);
|
|
list_add(sensor_list, &bmp_temp_reading);
|
|
|
|
list_add(sensor_list, &tmp_obj_reading);
|
|
list_add(sensor_list, &tmp_amb_reading);
|
|
|
|
list_add(sensor_list, &opt_reading);
|
|
|
|
list_add(sensor_list, &hdc_hum_reading);
|
|
list_add(sensor_list, &hdc_temp_reading);
|
|
|
|
list_add(sensor_list, &mpu_acc_x_reading);
|
|
list_add(sensor_list, &mpu_acc_y_reading);
|
|
list_add(sensor_list, &mpu_acc_z_reading);
|
|
list_add(sensor_list, &mpu_gyro_x_reading);
|
|
list_add(sensor_list, &mpu_gyro_y_reading);
|
|
list_add(sensor_list, &mpu_gyro_z_reading);
|
|
|
|
SENSORS_ACTIVATE(reed_relay_sensor);
|
|
#endif
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
PROCESS_THREAD(cc26xx_web_demo_process, ev, data)
|
|
{
|
|
PROCESS_BEGIN();
|
|
|
|
printf("CC26XX Web Demo Process\n");
|
|
|
|
init_sensors();
|
|
|
|
cc26xx_web_demo_publish_event = process_alloc_event();
|
|
cc26xx_web_demo_config_loaded_event = process_alloc_event();
|
|
cc26xx_web_demo_load_config_defaults = process_alloc_event();
|
|
|
|
/* Start all other (enabled) processes first */
|
|
process_start(&httpd_simple_process, NULL);
|
|
#if CC26XX_WEB_DEMO_COAP_SERVER
|
|
process_start(&coap_server_process, NULL);
|
|
#endif
|
|
|
|
#if CC26XX_WEB_DEMO_6LBR_CLIENT
|
|
process_start(&cetic_6lbr_client_process, NULL);
|
|
#endif
|
|
|
|
#if CC26XX_WEB_DEMO_MQTT_CLIENT
|
|
process_start(&mqtt_client_process, NULL);
|
|
#endif
|
|
|
|
#if CC26XX_WEB_DEMO_NET_UART
|
|
process_start(&net_uart_process, NULL);
|
|
#endif
|
|
|
|
/*
|
|
* Now that processes have set their own config default values, set our
|
|
* own defaults and restore saved config from flash...
|
|
*/
|
|
cc26xx_web_demo_config.sensors_bitmap = 0xFFFFFFFF; /* all on by default */
|
|
cc26xx_web_demo_config.def_rt_ping_interval =
|
|
CC26XX_WEB_DEMO_DEFAULT_RSSI_MEAS_INTERVAL;
|
|
load_config();
|
|
|
|
/*
|
|
* Notify all other processes (basically the ones in this demo) that the
|
|
* configuration has been loaded from flash, in case they care
|
|
*/
|
|
process_post(PROCESS_BROADCAST, cc26xx_web_demo_config_loaded_event, NULL);
|
|
|
|
init_sensor_readings();
|
|
|
|
httpd_simple_register_post_handler(&sensor_handler);
|
|
httpd_simple_register_post_handler(&defaults_handler);
|
|
|
|
#if CC26XX_WEB_DEMO_READ_PARENT_RSSI
|
|
httpd_simple_register_post_handler(&ping_interval_handler);
|
|
|
|
def_rt_rssi = 0x8000000;
|
|
uip_icmp6_echo_reply_callback_add(&echo_reply_notification,
|
|
echo_reply_handler);
|
|
etimer_set(&echo_request_timer, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC);
|
|
#endif
|
|
|
|
etimer_set(&et, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC);
|
|
|
|
/*
|
|
* Update all sensor readings on a configurable sensors_event
|
|
* (e.g a button press / or reed trigger)
|
|
*/
|
|
while(1) {
|
|
if(ev == PROCESS_EVENT_TIMER && etimer_expired(&et)) {
|
|
if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) {
|
|
leds_on(CC26XX_WEB_DEMO_STATUS_LED);
|
|
ctimer_set(&ct, NO_NET_LED_DURATION, publish_led_off, NULL);
|
|
etimer_set(&et, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC);
|
|
}
|
|
}
|
|
|
|
#if CC26XX_WEB_DEMO_READ_PARENT_RSSI
|
|
if(ev == PROCESS_EVENT_TIMER && etimer_expired(&echo_request_timer)) {
|
|
if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) {
|
|
etimer_set(&echo_request_timer, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC);
|
|
} else {
|
|
ping_parent();
|
|
etimer_set(&echo_request_timer, cc26xx_web_demo_config.def_rt_ping_interval);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(ev == sensors_event && data == CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER) {
|
|
if((CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER)->value(
|
|
BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND * 5) {
|
|
printf("Restoring defaults!\n");
|
|
cc26xx_web_demo_restore_defaults();
|
|
} else {
|
|
init_sensor_readings();
|
|
|
|
process_post(PROCESS_BROADCAST, cc26xx_web_demo_publish_event, NULL);
|
|
}
|
|
} else if(ev == httpd_simple_event_new_config) {
|
|
save_config();
|
|
#if BOARD_SENSORTAG
|
|
} else if(ev == sensors_event && data == &bmp_280_sensor) {
|
|
get_bmp_reading();
|
|
} else if(ev == sensors_event && data == &opt_3001_sensor) {
|
|
get_light_reading();
|
|
} else if(ev == sensors_event && data == &hdc_1000_sensor) {
|
|
get_hdc_reading();
|
|
} else if(ev == sensors_event && data == &tmp_007_sensor) {
|
|
get_tmp_reading();
|
|
} else if(ev == sensors_event && data == &mpu_9250_sensor) {
|
|
get_mpu_reading();
|
|
#endif
|
|
}
|
|
|
|
PROCESS_YIELD();
|
|
}
|
|
|
|
PROCESS_END();
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
/**
|
|
* @}
|
|
*/
|