Align to current master

This commit is contained in:
Marco Grella 2015-09-04 17:01:04 +02:00
commit 17aafb9daa
217 changed files with 16131 additions and 8628 deletions

View file

@ -90,7 +90,7 @@ request_prefix(void) CC_NON_BANKED
uip_buf[1] = 'P';
uip_len = 2;
slip_send();
uip_len = 0;
uip_clear_buf();
}
/*---------------------------------------------------------------------------*/
/* Set our prefix when we receive one over SLIP */

View file

@ -59,7 +59,7 @@ slip_input_callback(void)
PRINTF("SIN: %u\n", uip_len);
if((char)uip_buf[0] == '!') {
PRINTF("Got configuration message of type %c\n", uip_buf[1]);
uip_len = 0;
uip_clear_buf();
if((char)uip_buf[1] == 'P') {
uip_ipaddr_t prefix;
/* Here we set a prefix !!! */

View file

@ -35,7 +35,7 @@
* USB (CDC_ACM) functionality.
*
* It will print out periodically. Anything you type in the dongle's
* serial console will be echoed back
* serial console will be echoed back after a newline.
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>

View file

@ -6,8 +6,9 @@ boards. More specifically, the example demonstrates:
* How to take sensor readings
* How to use buttons and the reed relay (triggered by holding a magnet near S3
on the SensorTag).
* How to send out BLE advertisements. The device will periodically send out BLE
beacons with the platform name as payload. Those beacons/BLE ADV packets can
be captured with any BLE capable device. Two such applications for iOS are the
TI Multitool and the TI Sensortag app. They can be found in the Apple App
Store. If you have a BLE-capable Mac, you can also use LightBlue for OS X.
* How to send out BLE advertisements, if the chip has BLE capability. The
device will periodically send out BLE beacons with the platform name as
payload. Those beacons/BLE ADV packets can be captured with any BLE-capable
device. Two such applications for iOS are the TI Multitool and the TI
Sensortag app. They can be found in the Apple App Store. If you have a
BLE-capable Mac, you can also use LightBlue for OS X.

View file

@ -88,13 +88,12 @@
#include "sys/etimer.h"
#include "sys/ctimer.h"
#include "dev/leds.h"
#include "dev/serial-line.h"
#include "dev/watchdog.h"
#include "random.h"
#include "button-sensor.h"
#include "batmon-sensor.h"
#include "board-peripherals.h"
#include "cc26xx-rf.h"
#include "rf-core/rf-ble.h"
#include "ti-lib.h"
@ -104,7 +103,6 @@
#define CC26XX_DEMO_LOOP_INTERVAL (CLOCK_SECOND * 20)
#define CC26XX_DEMO_LEDS_PERIODIC LEDS_YELLOW
#define CC26XX_DEMO_LEDS_BUTTON LEDS_RED
#define CC26XX_DEMO_LEDS_SERIAL_IN LEDS_ORANGE
#define CC26XX_DEMO_LEDS_REBOOT LEDS_ALL
/*---------------------------------------------------------------------------*/
#define CC26XX_DEMO_SENSOR_NONE (void *)0xFFFFFFFF
@ -370,8 +368,8 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data)
init_sensors();
/* Init the BLE advertisement daemon */
cc26xx_rf_ble_beacond_config(0, BOARD_STRING);
cc26xx_rf_ble_beacond_start();
rf_ble_beacond_config(0, BOARD_STRING);
rf_ble_beacond_start();
etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL);
get_sync_sensor_readings();

View file

@ -5,7 +5,7 @@ all: cc26xx-web-demo
REST_RESOURCES_DIR = ./resources
REST_RESOURCES_FILES += res-leds.c res-toggle-leds.c res-device.c
REST_RESOURCES_FILES += res-sensors.c res-ble-advd.c
REST_RESOURCES_FILES += res-sensors.c res-ble-advd.c res-net.c
PROJECTDIRS += $(REST_RESOURCES_DIR)
PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES)

View file

@ -10,12 +10,11 @@ demonstrate the CC26xx capability. The applications are:
* A web server which can be used to display sensor readings but also to
configure MQTT functionality
The example has been configured to run for both CC26xx-based boards: i) The
SensorTag 2.0 and ii) The Srf06EB with a CC26xx EM mounted on it.
The example has been configured to run for all CC26xx-based boards: i) The
SensorTag 2.0 and ii) The Srf06EB with a CC26xx or CC13xx EM mounted on it.
To build the example for the Srf, simply run `make`. To build for the tag,
run `make BOARD=sensortag`. Do not forget to `make clean` when switching
between the two platforms.
To change between target boards, follow the instructions in the platform's
REDME file. Do not forget to `make clean` when switching between the boards.
You can disable some of those individual components by changing the respective
defines in `project-conf.h`. For instance, to disable the CoAP functionality,

View file

@ -44,6 +44,7 @@
#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"
@ -77,13 +78,20 @@ struct ctimer bmp_timer, hdc_timer, tmp_timer, opt_timer, mpu_timer;
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 0xCC265001
#define CONFIG_MAGIC 0xCC265002
cc26xx_web_demo_config_t cc26xx_web_demo_config;
/*---------------------------------------------------------------------------*/
@ -374,8 +382,57 @@ sensor_readings_handler(char *key, int key_len, char *val, int val_len)
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)
@ -828,6 +885,8 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data)
* 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();
/*
@ -841,6 +900,15 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data)
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);
/*
@ -848,6 +916,25 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data)
* (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) {
@ -858,12 +945,6 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data)
process_post(PROCESS_BROADCAST, cc26xx_web_demo_publish_event, NULL);
}
} else 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);
}
} else if(ev == httpd_simple_event_new_config) {
save_config();
#if BOARD_SENSORTAG

View file

@ -80,6 +80,16 @@
#define CC26XX_WEB_DEMO_NET_UART 1
#endif
/*---------------------------------------------------------------------------*/
/* Active probing of RSSI from our preferred parent */
#if (CC26XX_WEB_DEMO_COAP_SERVER || CC26XX_WEB_DEMO_MQTT_CLIENT)
#define CC26XX_WEB_DEMO_READ_PARENT_RSSI 1
#else
#define CC26XX_WEB_DEMO_READ_PARENT_RSSI 0
#endif
#define CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MAX 86400 /* secs: 1 day */
#define CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MIN 5 /* secs */
/*---------------------------------------------------------------------------*/
/* User configuration */
/* Take a sensor reading on button press */
#define CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER &button_left_sensor
@ -91,7 +101,7 @@
/* Force an MQTT publish on sensor event */
#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &reed_relay_sensor
#else
#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &button_right_sensor
#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &button_down_sensor
#endif
#define CC26XX_WEB_DEMO_STATUS_LED LEDS_GREEN
@ -101,7 +111,11 @@
/*---------------------------------------------------------------------------*/
/* Default configuration values */
#define CC26XX_WEB_DEMO_DEFAULT_ORG_ID "quickstart"
#if CPU_FAMILY_CC13XX
#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc13xx"
#else
#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc26xx"
#endif
#define CC26XX_WEB_DEMO_DEFAULT_EVENT_TYPE_ID "status"
#define CC26XX_WEB_DEMO_DEFAULT_SUBSCRIBE_CMD_TYPE "+"
#define CC26XX_WEB_DEMO_DEFAULT_BROKER_PORT 1883
@ -165,6 +179,7 @@ typedef struct cc26xx_web_demo_config_s {
uint32_t magic;
int len;
uint32_t sensors_bitmap;
int def_rt_ping_interval;
mqtt_client_config_t mqtt_config;
net_uart_config_t net_uart;
} cc26xx_web_demo_config_t;

View file

@ -39,7 +39,7 @@
#include "contiki-net.h"
#include "rest-engine.h"
#include "board-peripherals.h"
#include "dev/cc26xx-rf.h"
#include "rf-core/rf-ble.h"
#include <stdio.h>
#include <stdlib.h>
@ -56,7 +56,10 @@ extern resource_t res_device_hw;
extern resource_t res_device_uptime;
extern resource_t res_device_cfg_reset;
#if CC26XX_RF_BLE_SUPPORT
extern resource_t res_parent_rssi;
extern resource_t res_parent_ip;
#if RF_BLE_ENABLED
extern resource_t res_ble_advd;
#endif
@ -138,7 +141,10 @@ PROCESS_THREAD(coap_server_process, ev, data)
rest_activate_resource(&res_device_uptime, "dev/uptime");
rest_activate_resource(&res_device_cfg_reset, "dev/cfg_reset");
#if CC26XX_RF_BLE_SUPPORT
rest_activate_resource(&res_parent_rssi, "net/parent/RSSI");
rest_activate_resource(&res_parent_ip, "net/parent/IPv6");
#if RF_BLE_ENABLED
rest_activate_resource(&res_ble_advd, "dev/ble_advd");
#endif

View file

@ -93,8 +93,8 @@ static int state;
#define STRINGIFY(x) XSTR(x)
#define XSTR(x) #x
#define RSSI_INT_MAX STRINGIFY(MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MAX)
#define RSSI_INT_MIN STRINGIFY(MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MIN)
#define RSSI_INT_MAX STRINGIFY(CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MAX)
#define RSSI_INT_MIN STRINGIFY(CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MIN)
#define PUB_INT_MAX STRINGIFY(MQTT_CLIENT_PUBLISH_INTERVAL_MAX)
#define PUB_INT_MIN STRINGIFY(MQTT_CLIENT_PUBLISH_INTERVAL_MIN)
/*---------------------------------------------------------------------------*/
@ -568,12 +568,54 @@ PT_THREAD(generate_config(struct httpd_state *s))
s->reading->publish ? "" : " Checked",
config_div_close));
}
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0,
"<input type=\"submit\" value=\"Submit\">"));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "</form>"));
/* RSSI measurements */
#if CC26XX_WEB_DEMO_READ_PARENT_RSSI
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "<h1>RSSI Probing</h1>"));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0,
"<form name=\"input\" action=\"%s\" ",
http_dev_cfg_page.filename));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "method=\"post\" enctype=\""));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "application/x-www-form-urlencoded\" "));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "accept-charset=\"UTF-8\">"));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "%sPeriod (secs):%s",
config_div_left, config_div_close));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "%s<input type=\"number\" ",
config_div_right));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "value=\"%lu\" ",
(clock_time_t)
(cc26xx_web_demo_config.def_rt_ping_interval
/ CLOCK_SECOND)));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0,
"min=\"" RSSI_INT_MIN "\" "
"max=\"" RSSI_INT_MAX "\" "
"name=\"ping_interval\">%s",
config_div_close));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0,
"<input type=\"submit\" value=\"Submit\">"));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "</form>"));
#endif
/* Actions */
PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "<h1>Actions</h1>"));
PT_WAIT_THREAD(&s->generate_pt,
@ -732,24 +774,6 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s))
"name=\"broker_port\">%s",
config_div_close));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "%sRSSI Interval (secs):%s",
config_div_left, config_div_close));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "%s<input type=\"number\" ",
config_div_right));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0, "value=\"%lu\" ",
(clock_time_t)
(cc26xx_web_demo_config.mqtt_config.def_rt_ping_interval
/ CLOCK_SECOND)));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0,
"min=\"" RSSI_INT_MIN "\" "
"max=\"" RSSI_INT_MAX "\" "
"name=\"ping_interval\">%s",
config_div_close));
PT_WAIT_THREAD(&s->generate_pt,
enqueue_chunk(s, 0,
"<input type=\"submit\" value=\"Submit\">"));

View file

@ -48,7 +48,7 @@
/*---------------------------------------------------------------------------*/
/* Ideally a multiple of TCP_MSS */
#ifdef HTTPD_SIMPLE_CONF_MAIN_BUF_SIZE
#define HTTPD_SIMPLE_MAIN_BUF_SIZE HTTPD_SIMPLE_CONF_BUF_SIZE
#define HTTPD_SIMPLE_MAIN_BUF_SIZE HTTPD_SIMPLE_CONF_MAIN_BUF_SIZE
#else
#define HTTPD_SIMPLE_MAIN_BUF_SIZE UIP_TCP_MSS
#endif

View file

@ -41,7 +41,6 @@
#include "net/rpl/rpl.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-icmp6.h"
#include "net/ipv6/sicslowpan.h"
#include "sys/etimer.h"
#include "sys/ctimer.h"
#include "lib/sensors.h"
@ -86,7 +85,7 @@ static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd";
* Number of times to try reconnecting to the broker.
* Can be a limited number (e.g. 3, 10 etc) or can be set to RETRY_FOREVER
*/
#define RECONNECT_ATTEMPTS RETRY_FOREVER
#define RECONNECT_ATTEMPTS 5
#define CONNECTION_STABLE_TIME (CLOCK_SECOND * 5)
#define NEW_CONFIG_WAIT_INTERVAL (CLOCK_SECOND * 20)
static struct timer connection_life;
@ -139,9 +138,7 @@ static uint16_t seq_nr_value = 0;
static uip_ip6addr_t def_route;
/*---------------------------------------------------------------------------*/
/* Parent RSSI functionality */
static struct uip_icmp6_echo_reply_notification echo_reply_notification;
static struct etimer echo_request_timer;
int def_rt_rssi = 0;
extern int def_rt_rssi;
/*---------------------------------------------------------------------------*/
const static cc26xx_web_demo_sensor_reading_t *reading;
/*---------------------------------------------------------------------------*/
@ -388,29 +385,6 @@ reconnect_post_handler(char *key, int key_len, char *val, int val_len)
return HTTPD_SIMPLE_POST_HANDLER_OK;
}
/*---------------------------------------------------------------------------*/
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 < MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MIN ||
rv > MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MAX) {
return HTTPD_SIMPLE_POST_HANDLER_ERROR;
}
conf->def_rt_ping_interval = rv * CLOCK_SECOND;
return HTTPD_SIMPLE_POST_HANDLER_OK;
}
/*---------------------------------------------------------------------------*/
HTTPD_SIMPLE_POST_HANDLER(org_id, org_id_post_handler);
HTTPD_SIMPLE_POST_HANDLER(type_id, type_id_post_handler);
HTTPD_SIMPLE_POST_HANDLER(event_type_id, event_type_id_post_handler);
@ -420,16 +394,6 @@ HTTPD_SIMPLE_POST_HANDLER(ip_addr, ip_addr_post_handler);
HTTPD_SIMPLE_POST_HANDLER(port, port_post_handler);
HTTPD_SIMPLE_POST_HANDLER(interval, interval_post_handler);
HTTPD_SIMPLE_POST_HANDLER(reconnect, reconnect_post_handler);
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
pub_handler(const char *topic, uint16_t topic_len, const uint8_t *chunk,
@ -624,7 +588,6 @@ init_config()
conf->broker_port = CC26XX_WEB_DEMO_DEFAULT_BROKER_PORT;
conf->pub_interval = CC26XX_WEB_DEMO_DEFAULT_PUBLISH_INTERVAL;
conf->def_rt_ping_interval = CC26XX_WEB_DEMO_DEFAULT_RSSI_MEAS_INTERVAL;
return 1;
}
@ -641,7 +604,6 @@ register_http_post_handlers(void)
httpd_simple_register_post_handler(&port_handler);
httpd_simple_register_post_handler(&ip_addr_handler);
httpd_simple_register_post_handler(&reconnect_handler);
httpd_simple_register_post_handler(&ping_interval_handler);
}
/*---------------------------------------------------------------------------*/
static void
@ -664,6 +626,7 @@ publish(void)
/* Publish MQTT topic in IBM quickstart format */
int len;
int remaining = APP_BUFFER_SIZE;
char def_rt_str[64];
seq_nr_value++;
@ -686,7 +649,6 @@ publish(void)
buf_ptr += len;
/* Put our Default route's string representation in a buffer */
char def_rt_str[64];
memset(def_rt_str, 0, sizeof(def_rt_str));
cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str),
uip_ds6_defrt_choose());
@ -743,17 +705,6 @@ connect_to_broker(void)
}
/*---------------------------------------------------------------------------*/
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);
}
/*---------------------------------------------------------------------------*/
static void
state_machine(void)
{
switch(state) {
@ -794,7 +745,6 @@ state_machine(void)
if(uip_ds6_get_global(ADDR_PREFERRED) != NULL) {
/* Registered and with a public IP. Connect */
DBG("Registered. Connect attempt %u\n", connect_attempt);
ping_parent();
connect_to_broker();
}
etimer_set(&publish_periodic_timer, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC);
@ -923,11 +873,6 @@ PROCESS_THREAD(mqtt_client_process, ev, data)
update_config();
def_rt_rssi = 0x8000000;
uip_icmp6_echo_reply_callback_add(&echo_reply_notification,
echo_reply_handler);
etimer_set(&echo_request_timer, conf->def_rt_ping_interval);
/* Main loop */
while(1) {
@ -956,11 +901,6 @@ PROCESS_THREAD(mqtt_client_process, ev, data)
state_machine();
}
if(ev == PROCESS_EVENT_TIMER && data == &echo_request_timer) {
ping_parent();
etimer_set(&echo_request_timer, conf->def_rt_ping_interval);
}
if(ev == cc26xx_web_demo_load_config_defaults) {
init_config();
etimer_set(&publish_periodic_timer, NEW_CONFIG_WAIT_INTERVAL);

View file

@ -45,8 +45,6 @@
#define MQTT_CLIENT_CONFIG_CMD_TYPE_LEN 8
#define MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN 64
/*---------------------------------------------------------------------------*/
#define MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MAX 86400 /* secs: 1 day */
#define MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MIN 5 /* secs */
#define MQTT_CLIENT_PUBLISH_INTERVAL_MAX 86400 /* secs: 1 day */
#define MQTT_CLIENT_PUBLISH_INTERVAL_MIN 5 /* secs */
/*---------------------------------------------------------------------------*/
@ -63,7 +61,6 @@ typedef struct mqtt_client_config {
char broker_ip[MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN];
char cmd_type[MQTT_CLIENT_CONFIG_CMD_TYPE_LEN];
clock_time_t pub_interval;
int def_rt_ping_interval;
uint16_t broker_port;
} mqtt_client_config_t;
/*---------------------------------------------------------------------------*/

View file

@ -32,11 +32,9 @@
#define PROJECT_CONF_H_
/*---------------------------------------------------------------------------*/
/* Change to match your configuration */
#define NETSTACK_CONF_RDC contikimac_driver
#define IEEE802154_CONF_PANID 0xABCD
#define CC26XX_RF_CONF_CHANNEL 25
#define CC26XX_MODEL_CONF_CPU_VARIANT 2650 /* CC2650 */
#define CC26XX_RF_CONF_BLE_SUPPORT 1 /* Only available with CC2650 */
#define RF_CORE_CONF_CHANNEL 25
#define RF_BLE_CONF_ENABLED 1
/*---------------------------------------------------------------------------*/
/* Enable/Disable Components of this Demo */
#define CC26XX_WEB_DEMO_CONF_MQTT_CLIENT 1

View file

@ -38,7 +38,7 @@
#include "contiki.h"
#include "rest-engine.h"
#include "er-coap.h"
#include "dev/cc26xx-rf.h"
#include "rf-core/rf-ble.h"
#include <string.h>
#include <stdlib.h>
@ -64,7 +64,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
if(len > 0 && len < BLE_NAME_BUF_LEN) {
memcpy(name, text, len);
cc26xx_rf_ble_beacond_config(0, name);
rf_ble_beacond_config(0, name);
success = 1;
}
@ -73,7 +73,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
rv = atoi(text);
if(rv > 0) {
cc26xx_rf_ble_beacond_config((clock_time_t)(rv * CLOCK_SECOND), NULL);
rf_ble_beacond_config((clock_time_t)(rv * CLOCK_SECOND), NULL);
success = 1;
}
@ -81,7 +81,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
if(len) {
if(strncmp(text, "on", len) == 0) {
if(cc26xx_rf_ble_beacond_start()) {
if(rf_ble_beacond_start()) {
success = 1;
} else {
REST.set_response_status(response, REST.status.FORBIDDEN);
@ -90,7 +90,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
return;
}
} else if(strncmp(text, "off", len) == 0) {
cc26xx_rf_ble_beacond_stop();
rf_ble_beacond_stop();
success = 1;
} else {
success = 0;

View file

@ -40,37 +40,65 @@
#include "rest-engine.h"
#include "er-coap.h"
#include "sys/clock.h"
#include "cc26xx-model.h"
#include "coap-server.h"
#include "cc26xx-web-demo.h"
#include "ti-lib.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
static uint16_t
detect_chip(void)
{
if(ti_lib_chipinfo_chip_family_is_cc26xx()) {
if(ti_lib_chipinfo_supports_ieee_802_15_4() == true) {
if(ti_lib_chipinfo_supports_ble() == true) {
return 2650;
} else {
return 2630;
}
} else {
return 2640;
}
} else if(ti_lib_chipinfo_chip_family_is_cc13xx()) {
if(ti_lib_chipinfo_supports_ble() == false &&
ti_lib_chipinfo_supports_ieee_802_15_4() == false) {
return 1310;
} else if(ti_lib_chipinfo_supports_ble() == true &&
ti_lib_chipinfo_supports_ieee_802_15_4() == true) {
return 1350;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_hw(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
uint16_t chip = detect_chip();
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s on CC%u", BOARD_STRING,
CC26XX_MODEL_CPU_VARIANT);
chip);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"HW Ver\":\"%s on CC%u\"}",
BOARD_STRING, CC26XX_MODEL_CPU_VARIANT);
BOARD_STRING, chip);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<hw-ver val=\"%s on CC%u\"/>", BOARD_STRING,
CC26XX_MODEL_CPU_VARIANT);
chip);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else {

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 2015, 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
* CoAP resource handler for network-related resources
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rest-engine.h"
#include "er-coap.h"
#include "coap-server.h"
#include "cc26xx-web-demo.h"
#include "ti-lib.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
extern int def_rt_rssi;
/*---------------------------------------------------------------------------*/
static void
res_get_handler_parent_rssi(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
REST.get_header_accept(request, &accept);
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", def_rt_rssi);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}",
def_rt_rssi);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<parent-rssi val=\"%d\"/>", def_rt_rssi);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_pref_parent(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
char def_rt_str[64];
REST.get_header_accept(request, &accept);
memset(def_rt_str, 0, sizeof(def_rt_str));
cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str),
uip_ds6_defrt_choose());
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", def_rt_str);
REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}",
def_rt_str);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.APPLICATION_XML) {
REST.set_header_content_type(response, REST.type.APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<parent=\"%s\"/>", def_rt_str);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
RESOURCE(res_parent_rssi, "title=\"Parent RSSI\";rt=\"dBm\"",
res_get_handler_parent_rssi, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
RESOURCE(res_parent_ip, "title=\"Preferred Parent\";rt=\"IPv6 address\"",
res_get_handler_pref_parent, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -35,11 +35,9 @@
#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 0
/*---------------------------------------------------------------------------*/
/* Change to match your configuration */
#define NETSTACK_CONF_RDC contikimac_driver
#define IEEE802154_CONF_PANID 0xABCD
#define CC26XX_RF_CONF_CHANNEL 25
#define CC26XX_MODEL_CONF_CPU_VARIANT 2650 /* CC2650 */
#define CC26XX_RF_CONF_BLE_SUPPORT 1 /* Only available with CC2650 */
#define RF_CORE_CONF_CHANNEL 25
#define RF_BLE_CONF_ENABLED 1
/*---------------------------------------------------------------------------*/
#endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,12 @@
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
CONTIKI_PROJECT = very-sleepy-demo
all: $(CONTIKI_PROJECT)
CONTIKI_WITH_IPV6 = 1
APPS += er-coap
APPS += rest-engine
CONTIKI = ../../..
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1 @@
TARGET = srf06-cc26xx

View file

@ -0,0 +1,91 @@
# CC13xx/CC26xx Very Sleepy Demo
This example demonstrates a way of deploying a very low-consuming, very sleepy
node. The node has two modes of operation:
* Normal: ContikiMAC duty-cycles the radio as usual. The node is reachable.
* Very Sleepy: Radio cycling mostly off, except when we need to perform network
maintenance tasks. In this mode, the node is unreachable for most of the time.
The node will operate in RPL leaf mode. This means that it will be reachable
downwards, but it will not advertise the DODAG and it will not participate in
routing.
After booting, the node will enter "normal" mode.
The node exposes an OBSERVEable CoAP resource. It will notify subscribers with
a new value for this resource every `interval` seconds. It will then stay in
normal mode for `duration` seconds. During this time window, it will be
reachable over the network in order to e.g. receive a new configuration.
When this time window expires, the node will switch back to very sleepy mode.
This will only happen if very sleepy mode has been enabled by setting `mode=1`
as per the instructions below.
When the node is duty-cycling the radio, either because it is in normal mode or
because network maintenance is taking place, it will keep its green LED on thus
providing an indication that it is reachable.
A normal mode stint can be manually triggered by pressing the left button.
## Requirements
To run this example you will need:
* A border router operating with the same RDC, same channel, same radio mode
(e.g. IEEE or sub-ghz), same PAN ID. Alternatively, you can
use [6lbr](https://github.com/cetic/6lbr) with a suitable slip-radio.
* The [Copper (Cu)](https://addons.mozilla.org/en-US/firefox/addon/copper-270430/)
addon for Firefox
## Configuration
To configure the node, send a CoAP POST message to the `very_sleepy_config`
resource. The POST message's payload must specify _at least one_ of:
* `mode=0|1`: Send `mode=1` to enable very sleepy mode, `mode=0` to disable it.
* `interval=n` where `n` is the number of seconds between two consecutive normal
mode periods. This interval also dictates the OBSERVEr notification period.
* `duration=n` where `n` is the number of seconds that the node will stay in
normal mode before dropping to very sleepy mode. This value is only relevant
if `mode==1`.
A POST request must contain at least one of the above, but they are otherwise
all optional. So, for example, a POST may simply specify `interval=n`. To send
multiple values, delimit them with `&`. So you can send something like
`mode=1&interval=60&duration=20`
The current running configuration can be retrieved by sending a GET request to
the same CoAP resource.
## Running the example
* Deploy your border router or 6lbr
* Turn on the very sleepy node.
* Fire up the Copper addon
* Select `.well-known/core` and hit `GET`
* Configure very sleepy operation:
* Select the `very_sleepy_config` resource
* In the `Outgoing` pane, type your POST payload as per the instructions
above. For example, you can type: `mode=1&interval=30&duration=10`
* Hit `POST`
* Select the `sen/readings` resource and hit `OBSERVE`
## Caveats
If you click on a resource in the Copper resources tree while you are observing
a different resource, the OBSERVEr for the latter will be stopped without
notifying the CoAP server. This will result in the server sending out OBSERVE
notifications that will be responded to with port unreachable ICMPv6 messages.
This will continue for quite a while, until the server detects that the
OBSERVEr has been lost (a test currently performed once every 20 notifications).
In order to prevent this from happening, hit the "Cancel" button for the
OBSERVE before switching views to a different resource. This will unregister
the observer.
In very sleepy mode, the radio is not truly always off. The contiki core needs
to perform other periodic tasks in order to maintain network connectivity. For
that reason, this example will allow the radio to turn on periodically even
while in very sleepy mode. Thus, you may see that the node becomes briefly
reachable every now and then. However, do not count on those periods of
reachability to perform any tasks, as they will be brief and will be disrupted
without warning.

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2015, 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.
*/
/*---------------------------------------------------------------------------*/
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
/*---------------------------------------------------------------------------*/
/* Change to match your configuration */
#define IEEE802154_CONF_PANID 0xABCD
#define RF_CORE_CONF_CHANNEL 25
/*---------------------------------------------------------------------------*/
/* For very sleepy operation */
#define RF_BLE_CONF_ENABLED 0
#define UIP_DS6_CONF_PERIOD CLOCK_SECOND
#define UIP_CONF_TCP 0
#define RPL_CONF_LEAF_ONLY 1
/*
* We'll fail without RPL probing, so turn it on explicitly even though it's
* on by default
*/
#define RPL_CONF_WITH_PROBING 1
/*---------------------------------------------------------------------------*/
#endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,423 @@
/*
* 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.
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "sys/etimer.h"
#include "sys/stimer.h"
#include "sys/process.h"
#include "dev/leds.h"
#include "dev/watchdog.h"
#include "button-sensor.h"
#include "batmon-sensor.h"
#include "board-peripherals.h"
#include "net/netstack.h"
#include "net/ipv6/uip-ds6-nbr.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/rpl/rpl.h"
#include "net/rpl/rpl-private.h"
#include "rest-engine.h"
#include "er-coap.h"
#include "ti-lib.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
/*---------------------------------------------------------------------------*/
/* Normal mode duration params in seconds */
#define NORMAL_OP_DURATION_DEFAULT 10
#define NORMAL_OP_DURATION_MIN 10
#define NORMAL_OP_DURATION_MAX 60
/*---------------------------------------------------------------------------*/
/* Observer notification period params in seconds */
#define PERIODIC_INTERVAL_DEFAULT 30
#define PERIODIC_INTERVAL_MIN 30
#define PERIODIC_INTERVAL_MAX 86400 /* 1 day */
/*---------------------------------------------------------------------------*/
#define VERY_SLEEPY_MODE_OFF 0
#define VERY_SLEEPY_MODE_ON 1
/*---------------------------------------------------------------------------*/
#define MAC_CAN_BE_TURNED_OFF 0
#define MAC_MUST_STAY_ON 1
#define KEEP_MAC_ON_MIN_PERIOD 10 /* secs */
/*---------------------------------------------------------------------------*/
#define PERIODIC_INTERVAL CLOCK_SECOND
/*---------------------------------------------------------------------------*/
#define POST_STATUS_BAD 0x80
#define POST_STATUS_HAS_MODE 0x40
#define POST_STATUS_HAS_DURATION 0x20
#define POST_STATUS_HAS_INTERVAL 0x10
#define POST_STATUS_NONE 0x00
/*---------------------------------------------------------------------------*/
typedef struct sleepy_config_s {
unsigned long interval;
unsigned long duration;
uint8_t mode;
} sleepy_config_t;
sleepy_config_t config;
/*---------------------------------------------------------------------------*/
#define STATE_NORMAL 0
#define STATE_NOTIFY_OBSERVERS 1
#define STATE_VERY_SLEEPY 2
/*---------------------------------------------------------------------------*/
static struct stimer st_duration;
static struct stimer st_interval;
static struct stimer st_min_mac_on_duration;
static struct etimer et_periodic;
static process_event_t event_new_config;
static uint8_t state;
/*---------------------------------------------------------------------------*/
const char *not_supported_msg = "Supported:text/plain,application/json";
/*---------------------------------------------------------------------------*/
PROCESS(very_sleepy_demo_process, "CC13xx/CC26xx very sleepy process");
AUTOSTART_PROCESSES(&very_sleepy_demo_process);
/*---------------------------------------------------------------------------*/
static void
readings_get_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
int temp;
int voltage;
if(request != NULL) {
REST.get_header_accept(request, &accept);
}
temp = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP);
voltage = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
if(accept == -1 || accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"{\"temp\":{\"v\":%d,\"u\":\"C\"},"
"\"voltage\":{\"v\":%d,\"u\":\"mV\"}}",
temp, (voltage * 125) >> 5);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV",
temp, (voltage * 125) >> 5);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, not_supported_msg,
strlen(not_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
RESOURCE(readings_resource, "title=\"Sensor Readings\";obs",
readings_get_handler, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
static void
conf_get_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
if(request != NULL) {
REST.get_header_accept(request, &accept);
}
if(accept == -1 || accept == REST.type.APPLICATION_JSON) {
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"{\"config\":{\"mode\":%u,\"duration\":%lu,\"interval\":%lu}}",
config.mode, config.duration, config.interval);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else if(accept == REST.type.TEXT_PLAIN) {
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"Mode=%u, Duration=%lusecs, Interval=%lusecs",
config.mode, config.duration, config.interval);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
} else {
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
REST.set_response_payload(response, not_supported_msg,
strlen(not_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
conf_post_handler(void *request, void *response, uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
const char *ptr = NULL;
char tmp_buf[16];
unsigned long interval = 0;
unsigned long duration = 0;
uint8_t mode = VERY_SLEEPY_MODE_OFF;
uint8_t post_status = POST_STATUS_NONE;
int rv;
rv = REST.get_post_variable(request, "mode", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
rv = atoi(tmp_buf);
if(rv == 1) {
mode = VERY_SLEEPY_MODE_ON;
post_status |= POST_STATUS_HAS_MODE;
} else if(rv == 0) {
mode = VERY_SLEEPY_MODE_OFF;
post_status |= POST_STATUS_HAS_MODE;
} else {
post_status = POST_STATUS_BAD;
}
}
rv = REST.get_post_variable(request, "duration", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
rv = atoi(tmp_buf);
duration = (unsigned long)rv;
if(duration < NORMAL_OP_DURATION_MIN || duration > NORMAL_OP_DURATION_MAX) {
post_status = POST_STATUS_BAD;
} else {
post_status |= POST_STATUS_HAS_DURATION;
}
}
rv = REST.get_post_variable(request, "interval", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
rv = atoi(tmp_buf);
interval = (unsigned long)rv;
if(interval < PERIODIC_INTERVAL_MIN || interval > PERIODIC_INTERVAL_MAX) {
post_status = POST_STATUS_BAD;
} else {
post_status |= POST_STATUS_HAS_INTERVAL;
}
}
if((post_status & POST_STATUS_BAD) == POST_STATUS_BAD ||
post_status == POST_STATUS_NONE) {
REST.set_response_status(response, REST.status.BAD_REQUEST);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"mode=0|1&duration=[%u,%u]&interval=[%u,%u]",
NORMAL_OP_DURATION_MIN, NORMAL_OP_DURATION_MAX,
PERIODIC_INTERVAL_MIN, PERIODIC_INTERVAL_MAX);
REST.set_response_payload(response, buffer, strlen((char *)buffer));
return;
}
/* Values are sane. Update the config and notify the process */
if(post_status & POST_STATUS_HAS_MODE) {
config.mode = mode;
}
if(post_status & POST_STATUS_HAS_INTERVAL) {
config.interval = interval;
}
if(post_status & POST_STATUS_HAS_DURATION) {
config.duration = duration;
}
process_post(&very_sleepy_demo_process, event_new_config, NULL);
}
/*---------------------------------------------------------------------------*/
RESOURCE(very_sleepy_conf,
"title=\"Very sleepy conf: "
"GET|POST mode=0|1&interval=<secs>&duration=<secs>\";rt=\"Control\"",
conf_get_handler, conf_post_handler, NULL, NULL);
/*---------------------------------------------------------------------------*/
/*
* If our preferred parent is not NBR_REACHABLE in the ND cache, NUD will send
* a unicast NS and wait for NA. If NA fails then the neighbour will be removed
* from the ND cache and the default route will be deleted. To prevent this,
* keep the MAC on until the parent becomes NBR_REACHABLE. We also keep the MAC
* on if we are about to do RPL probing.
*
* In all cases, the radio will be locked on for KEEP_MAC_ON_MIN_PERIOD secs
*/
static uint8_t
keep_mac_on(void)
{
uip_ds6_nbr_t *nbr;
uint8_t rv = MAC_CAN_BE_TURNED_OFF;
if(!stimer_expired(&st_min_mac_on_duration)) {
return MAC_MUST_STAY_ON;
}
#if RPL_WITH_PROBING
/* Determine if we are about to send a RPL probe */
if(CLOCK_LT(etimer_expiration_time(
&rpl_get_default_instance()->probing_timer.etimer),
(clock_time() + PERIODIC_INTERVAL))) {
rv = MAC_MUST_STAY_ON;
}
#endif
/* It's OK to pass a NULL pointer, the callee checks and returns NULL */
nbr = uip_ds6_nbr_lookup(uip_ds6_defrt_choose());
if(nbr == NULL) {
/* We don't have a default route, or it's not reachable (NUD likely). */
rv = MAC_MUST_STAY_ON;
} else {
if(nbr->state != NBR_REACHABLE) {
rv = MAC_MUST_STAY_ON;
}
}
if(rv == MAC_MUST_STAY_ON && stimer_expired(&st_min_mac_on_duration)) {
stimer_set(&st_min_mac_on_duration, KEEP_MAC_ON_MIN_PERIOD);
}
return rv;
}
/*---------------------------------------------------------------------------*/
static void
switch_to_normal(void)
{
state = STATE_NOTIFY_OBSERVERS;
/*
* Stay in normal mode for 'duration' secs.
* Transition back to normal in 'interval' secs, _including_ 'duration'
*/
stimer_set(&st_duration, config.duration);
stimer_set(&st_interval, config.interval);
}
/*---------------------------------------------------------------------------*/
static void
switch_to_very_sleepy(void)
{
state = STATE_VERY_SLEEPY;
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(very_sleepy_demo_process, ev, data)
{
uint8_t mac_keep_on;
PROCESS_BEGIN();
SENSORS_ACTIVATE(batmon_sensor);
config.mode = VERY_SLEEPY_MODE_OFF;
config.interval = PERIODIC_INTERVAL_DEFAULT;
config.duration = NORMAL_OP_DURATION_DEFAULT;
state = STATE_NORMAL;
event_new_config = process_alloc_event();
rest_init_engine();
readings_resource.flags += IS_OBSERVABLE;
rest_activate_resource(&readings_resource, "sen/readings");
rest_activate_resource(&very_sleepy_conf, "very_sleepy_config");
printf("Very Sleepy Demo Process\n");
switch_to_normal();
etimer_set(&et_periodic, PERIODIC_INTERVAL);
while(1) {
PROCESS_YIELD();
if(ev == sensors_event && data == &button_left_sensor) {
switch_to_normal();
}
if(ev == event_new_config) {
stimer_set(&st_interval, config.interval);
stimer_set(&st_duration, config.duration);
}
if((ev == PROCESS_EVENT_TIMER && data == &et_periodic) ||
(ev == sensors_event && data == &button_left_sensor) ||
(ev == event_new_config)) {
/*
* Determine if the stack is about to do essential network maintenance
* and, if so, keep the MAC layer on
*/
mac_keep_on = keep_mac_on();
if(mac_keep_on == MAC_MUST_STAY_ON || state != STATE_VERY_SLEEPY) {
leds_on(LEDS_GREEN);
NETSTACK_MAC.on();
}
/*
* Next, switch between normal and very sleepy mode depending on config,
* send notifications to observers as required.
*/
if(state == STATE_NOTIFY_OBSERVERS) {
REST.notify_subscribers(&readings_resource);
state = STATE_NORMAL;
}
if(state == STATE_NORMAL) {
if(stimer_expired(&st_duration)) {
stimer_set(&st_duration, config.duration);
if(config.mode == VERY_SLEEPY_MODE_ON) {
switch_to_very_sleepy();
}
}
} else if(state == STATE_VERY_SLEEPY) {
if(stimer_expired(&st_interval)) {
switch_to_normal();
}
}
if(mac_keep_on == MAC_CAN_BE_TURNED_OFF && state == STATE_VERY_SLEEPY) {
leds_off(LEDS_GREEN);
NETSTACK_MAC.off(0);
} else {
leds_on(LEDS_GREEN);
NETSTACK_MAC.on();
}
/* Schedule next pass */
etimer_set(&et_periodic, PERIODIC_INTERVAL);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View file

@ -311,7 +311,7 @@ request_prefix(void)
uip_buf[1] = 'P';
uip_len = 2;
slip_send();
uip_len = 0;
uip_clear_buf();
}
/*---------------------------------------------------------------------------*/
void

View file

@ -59,7 +59,7 @@ slip_input_callback(void)
// PRINTF("SIN: %u\n", uip_len);
if(uip_buf[0] == '!') {
PRINTF("Got configuration message of type %c\n", uip_buf[1]);
uip_len = 0;
uip_clear_buf();
if(uip_buf[1] == 'P') {
uip_ipaddr_t prefix;
/* Here we set a prefix !!! */
@ -85,7 +85,7 @@ slip_input_callback(void)
slip_send();
}
uip_len = 0;
uip_clear_buf();
}
/* Save the last sender received over SLIP to avoid bouncing the
packet back if no route is found */

View file

@ -162,7 +162,7 @@ slip_input_callback(void)
{
PRINTF("SR-SIN: %u '%c%c'\n", uip_len, uip_buf[0], uip_buf[1]);
cmd_input(uip_buf, uip_len);
uip_len = 0;
uip_clear_buf();
}
/*---------------------------------------------------------------------------*/
static void

View file

@ -1 +1 @@
DEFINES = WITH_CLIENT,WITH_DNS,WITH_GUI,WITH_PFS
DEFINES = WITH_CLIENT,WITH_DNS,WITH_GUI,WITH_PFS,MTU_SIZE=1000

View file

@ -13,6 +13,8 @@ uip_buf_t uip_aligned_buf;
uint16_t uip_len;
uint8_t uip_ext_len;
struct uip_stats uip_stat;
uip_lladdr_t uip_lladdr;

View file

@ -90,7 +90,7 @@ request_prefix(void) CC_NON_BANKED
uip_buf[1] = 'P';
uip_len = 2;
slip_send();
uip_len = 0;
uip_clear_buf();
}
/*---------------------------------------------------------------------------*/
/* Set our prefix when we receive one over SLIP */

View file

@ -60,7 +60,7 @@ slip_input_callback(void)
PRINTF("SIN: %u\n", uip_len);
if((char)uip_buf[0] == '!') {
PRINTF("Got configuration message of type %c\n", uip_buf[1]);
uip_len = 0;
uip_clear_buf();
if((char)uip_buf[1] == 'P') {
uip_ipaddr_t prefix;
/* Here we set a prefix !!! */

View file

@ -34,20 +34,6 @@
#include "shell.h"
#include "serial-shell.h"
#include "dev/watchdog.h"
#include "net/rime/rime.h"
#include "cc2420.h"
#include "dev/leds.h"
#include "dev/light.h"
#include "dev/sht11/sht11.h"
#include "dev/battery-sensor.h"
#include "net/rime/timesynch.h"
#include <stdio.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
PROCESS(sky_shell_process, "Sky Contiki shell");
AUTOSTART_PROCESSES(&sky_shell_process);

View file

@ -1 +1 @@
DEFINES = WITH_LOGGING,WITH_CLIENT,WITH_DNS,WITH_ARGS
DEFINES = WITH_LOGGING,WITH_CLIENT,WITH_DNS,WITH_PFS,WITH_ARGS