Add CC26xx examples
This commit is contained in:
parent
c9071b6952
commit
0f567e499f
30 changed files with 5928 additions and 0 deletions
9
examples/cc26xx/Makefile
Normal file
9
examples/cc26xx/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
|
||||
CONTIKI_PROJECT = cc26xx-demo
|
||||
|
||||
all: $(CONTIKI_PROJECT)
|
||||
|
||||
CONTIKI_WITH_IPV6 = 1
|
||||
|
||||
CONTIKI = ../..
|
||||
include $(CONTIKI)/Makefile.include
|
1
examples/cc26xx/Makefile.target
Normal file
1
examples/cc26xx/Makefile.target
Normal file
|
@ -0,0 +1 @@
|
|||
TARGET = srf06-cc26xx
|
15
examples/cc26xx/README.md
Normal file
15
examples/cc26xx/README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
CC26xx Demo
|
||||
===========
|
||||
This example demonstrates basic functionality for the two supported CC26xx
|
||||
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 keep a power domain powered and a peripheral clocked under low power
|
||||
operation
|
||||
* 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.
|
477
examples/cc26xx/cc26xx-demo.c
Normal file
477
examples/cc26xx/cc26xx-demo.c
Normal file
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
* 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-platforms
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc26xx-examples CC26xx Example Projects
|
||||
*
|
||||
* Example projects for CC26xx-based platforms.
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc26xx-demo CC26xx Demo Project
|
||||
*
|
||||
* Example project demonstrating the CC26xx platforms
|
||||
*
|
||||
* This example will work for the following boards:
|
||||
* - srf06-cc26xx: SmartRF06EB + CC26XX EM
|
||||
* - sensortag-cc26xx: CC26XX sensortag
|
||||
*
|
||||
* By default, the example will build for the srf06-cc26xx board. To switch
|
||||
* between platforms:
|
||||
* - make clean
|
||||
* - make BOARD=sensortag-cc26xx savetarget
|
||||
*
|
||||
* or
|
||||
*
|
||||
* make BOARD=srf06-cc26xx savetarget
|
||||
*
|
||||
* This is an IPv6/RPL-enabled example. Thus, if you have a border router in
|
||||
* your installation (same RDC layer, same PAN ID and RF channel), you should
|
||||
* be able to ping6 this demo node.
|
||||
*
|
||||
* This example also demonstrates CC26xx BLE operation. The process starts
|
||||
* the BLE beacon daemon (implemented in the RF driver). The daemon will
|
||||
* send out a BLE beacon periodically. Use any BLE-enabled application (e.g.
|
||||
* LightBlue on OS X or the TI BLE Multitool smartphone app) and after a few
|
||||
* seconds the cc26xx device will be discovered.
|
||||
*
|
||||
* - etimer/clock : Every CC26XX_DEMO_LOOP_INTERVAL clock ticks the LED defined
|
||||
* as CC26XX_DEMO_LEDS_PERIODIC will toggle and the device
|
||||
* will print out readings from some supported sensors
|
||||
* - sensors : Some sensortag sensors are read asynchronously (see sensor
|
||||
* documentation). For those, this example will print out
|
||||
* readings in a staggered fashion at a random interval
|
||||
* - Buttons : CC26XX_DEMO_SENSOR_1 button will toggle CC26XX_DEMO_LEDS_BUTTON
|
||||
* - CC26XX_DEMO_SENSOR_2 turns on LEDS_REBOOT and causes a
|
||||
* watchdog reboot
|
||||
* - The remaining buttons will just print something
|
||||
* - The example also shows how to retrieve the duration of a
|
||||
* button press (in ticks). The driver will generate a
|
||||
* sensors_changed event upon button release
|
||||
* - UART : Receiving an entire line of text over UART (ending
|
||||
* in \\r) will cause CC26XX_DEMO_LEDS_SERIAL_IN to toggle
|
||||
* This also demonstrates how a code module can influence
|
||||
* low-power operation: In this example we keep the UART on
|
||||
* and capable to RX even with the chip in deep sleep.
|
||||
* see keep_uart_on() and the UART driver
|
||||
* - Reed Relay : Will toggle the sensortag buzzer on/off
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
* Example demonstrating the cc26xx platforms
|
||||
*/
|
||||
#include "contiki.h"
|
||||
#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 "lpm.h"
|
||||
#include "cc26xx-rf.h"
|
||||
|
||||
#include "ti-lib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#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
|
||||
|
||||
#define CC26XX_DEMO_SENSOR_1 &button_left_sensor
|
||||
#define CC26XX_DEMO_SENSOR_2 &button_right_sensor
|
||||
|
||||
#if BOARD_SENSORTAG
|
||||
#define CC26XX_DEMO_SENSOR_3 CC26XX_DEMO_SENSOR_NONE
|
||||
#define CC26XX_DEMO_SENSOR_4 CC26XX_DEMO_SENSOR_NONE
|
||||
#define CC26XX_DEMO_SENSOR_5 &reed_relay_sensor
|
||||
#else
|
||||
#define CC26XX_DEMO_SENSOR_3 &button_up_sensor
|
||||
#define CC26XX_DEMO_SENSOR_4 &button_down_sensor
|
||||
#define CC26XX_DEMO_SENSOR_5 &button_select_sensor
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct etimer et;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(cc26xx_demo_process, "cc26xx demo process");
|
||||
AUTOSTART_PROCESSES(&cc26xx_demo_process);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if BOARD_SENSORTAG
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* 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)
|
||||
|
||||
static struct ctimer bmp_timer, opt_timer, sht_timer, tmp_timer, mpu_timer;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void init_bmp_reading(void *not_used);
|
||||
static void init_opt_reading(void *not_used);
|
||||
static void init_sht_reading(void *not_used);
|
||||
static void init_tmp_reading(void *not_used);
|
||||
static void init_mpu_reading(void *not_used);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
print_mpu_reading(int reading)
|
||||
{
|
||||
if(reading < 0) {
|
||||
printf("-");
|
||||
reading = -reading;
|
||||
}
|
||||
|
||||
printf("%d.%02d", reading / 100, reading % 100);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
get_bmp_reading()
|
||||
{
|
||||
int value;
|
||||
clock_time_t next = SENSOR_READING_PERIOD +
|
||||
(random_rand() % SENSOR_READING_RANDOM);
|
||||
|
||||
value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS);
|
||||
if(value != CC26XX_SENSOR_READING_ERROR) {
|
||||
printf("BAR: Pressure=%d.%02d hPa\n", value / 100, value % 100);
|
||||
} else {
|
||||
printf("BAR: Pressure Read Error\n");
|
||||
}
|
||||
|
||||
value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_TEMP);
|
||||
if(value != CC26XX_SENSOR_READING_ERROR) {
|
||||
printf("BAR: Temp=%d.%02d C\n", value / 100, value % 100);
|
||||
} else {
|
||||
printf("BAR: Temperature Read Error\n");
|
||||
}
|
||||
|
||||
SENSORS_DEACTIVATE(bmp_280_sensor);
|
||||
|
||||
ctimer_set(&bmp_timer, next, init_bmp_reading, NULL);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
get_tmp_reading()
|
||||
{
|
||||
int value;
|
||||
clock_time_t next = SENSOR_READING_PERIOD +
|
||||
(random_rand() % SENSOR_READING_RANDOM);
|
||||
|
||||
value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_ALL);
|
||||
|
||||
if(value == CC26XX_SENSOR_READING_ERROR) {
|
||||
printf("TMP: Ambient Read Error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_AMBIENT);
|
||||
printf("TMP: Ambient=%d.%03d C\n", value / 1000, value % 1000);
|
||||
|
||||
value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_OBJECT);
|
||||
printf("TMP: Object=%d.%03d C\n", value / 1000, value % 1000);
|
||||
|
||||
SENSORS_DEACTIVATE(tmp_007_sensor);
|
||||
|
||||
ctimer_set(&tmp_timer, next, init_tmp_reading, NULL);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
get_sht_reading()
|
||||
{
|
||||
int value;
|
||||
clock_time_t next = SENSOR_READING_PERIOD +
|
||||
(random_rand() % SENSOR_READING_RANDOM);
|
||||
|
||||
value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP);
|
||||
if(value != CC26XX_SENSOR_READING_ERROR) {
|
||||
printf("SHT: Temp=%d.%02d C\n", value / 100, value % 100);
|
||||
} else {
|
||||
printf("SHT: Temp Read Error\n");
|
||||
}
|
||||
|
||||
value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY);
|
||||
if(value != CC26XX_SENSOR_READING_ERROR) {
|
||||
printf("SHT: Humidity=%d.%02d %%RH\n", value / 100, value % 100);
|
||||
} else {
|
||||
printf("SHT: Humidity Read Error\n");
|
||||
}
|
||||
|
||||
ctimer_set(&sht_timer, next, init_sht_reading, NULL);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
get_light_reading()
|
||||
{
|
||||
int value;
|
||||
clock_time_t next = SENSOR_READING_PERIOD +
|
||||
(random_rand() % SENSOR_READING_RANDOM);
|
||||
|
||||
value = opt_3001_sensor.value(0);
|
||||
if(value != CC26XX_SENSOR_READING_ERROR) {
|
||||
printf("OPT: Light=%d.%02d lux\n", value / 100, value % 100);
|
||||
} else {
|
||||
printf("OPT: Light Read Error\n");
|
||||
}
|
||||
|
||||
SENSORS_DEACTIVATE(opt_3001_sensor);
|
||||
|
||||
ctimer_set(&opt_timer, next, init_opt_reading, NULL);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
get_mpu_reading()
|
||||
{
|
||||
int value;
|
||||
clock_time_t next = SENSOR_READING_PERIOD +
|
||||
(random_rand() % SENSOR_READING_RANDOM);
|
||||
|
||||
printf("MPU Gyro: X=");
|
||||
value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_X);
|
||||
print_mpu_reading(value);
|
||||
printf(" deg/sec\n");
|
||||
|
||||
printf("MPU Gyro: Y=");
|
||||
value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Y);
|
||||
print_mpu_reading(value);
|
||||
printf(" deg/sec\n");
|
||||
|
||||
printf("MPU Gyro: Z=");
|
||||
value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Z);
|
||||
print_mpu_reading(value);
|
||||
printf(" deg/sec\n");
|
||||
|
||||
printf("MPU Acc: X=");
|
||||
value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_X);
|
||||
print_mpu_reading(value);
|
||||
printf(" G\n");
|
||||
|
||||
printf("MPU Acc: Y=");
|
||||
value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Y);
|
||||
print_mpu_reading(value);
|
||||
printf(" G\n");
|
||||
|
||||
printf("MPU Acc: Z=");
|
||||
value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Z);
|
||||
print_mpu_reading(value);
|
||||
printf(" G\n");
|
||||
|
||||
SENSORS_DEACTIVATE(mpu_9250_sensor);
|
||||
|
||||
ctimer_set(&mpu_timer, next, init_mpu_reading, NULL);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init_bmp_reading(void *not_used)
|
||||
{
|
||||
SENSORS_ACTIVATE(bmp_280_sensor);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init_opt_reading(void *not_used)
|
||||
{
|
||||
SENSORS_ACTIVATE(opt_3001_sensor);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init_sht_reading(void *not_used)
|
||||
{
|
||||
SENSORS_ACTIVATE(sht_21_sensor);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init_tmp_reading(void *not_used)
|
||||
{
|
||||
SENSORS_ACTIVATE(tmp_007_sensor);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init_mpu_reading(void *not_used)
|
||||
{
|
||||
mpu_9250_sensor.configure(SENSORS_ACTIVE, MPU_9250_SENSOR_TYPE_ALL);
|
||||
}
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
get_sync_sensor_readings(void)
|
||||
{
|
||||
int value;
|
||||
|
||||
printf("-----------------------------------------\n");
|
||||
|
||||
value = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP);
|
||||
printf("Bat: Temp=%d.%02d C (%08x)\n", value >> 2,
|
||||
(value & 0x00000003) * 25, value);
|
||||
|
||||
value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
|
||||
printf("Bat: Volt=%d mV\n", (value * 125) >> 5);
|
||||
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init_sensors(void)
|
||||
{
|
||||
#if BOARD_SENSORTAG
|
||||
SENSORS_ACTIVATE(reed_relay_sensor);
|
||||
#endif
|
||||
|
||||
SENSORS_ACTIVATE(batmon_sensor);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init_sensor_readings(void)
|
||||
{
|
||||
#if BOARD_SENSORTAG
|
||||
SENSORS_ACTIVATE(sht_21_sensor);
|
||||
SENSORS_ACTIVATE(tmp_007_sensor);
|
||||
SENSORS_ACTIVATE(opt_3001_sensor);
|
||||
SENSORS_ACTIVATE(bmp_280_sensor);
|
||||
|
||||
init_mpu_reading(NULL);
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static lpm_power_domain_lock_t lock;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* In order to maintain UART input operation:
|
||||
* - Keep the uart clocked in sleep and deep sleep
|
||||
* - Keep the serial PD on in deep sleep
|
||||
*/
|
||||
static void
|
||||
keep_uart_on(void)
|
||||
{
|
||||
/* Keep the serial PD on */
|
||||
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL);
|
||||
|
||||
/* Keep the UART clock on during Sleep and Deep Sleep */
|
||||
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0);
|
||||
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0);
|
||||
ti_lib_prcm_load_set();
|
||||
while(!ti_lib_prcm_load_get());
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(cc26xx_demo_process, ev, data)
|
||||
{
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
printf("CC26XX demo\n");
|
||||
|
||||
init_sensors();
|
||||
|
||||
/* Init the BLE advertisement daemon */
|
||||
cc26xx_rf_ble_beacond_config(0, BOARD_STRING);
|
||||
cc26xx_rf_ble_beacond_start();
|
||||
|
||||
etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL);
|
||||
get_sync_sensor_readings();
|
||||
init_sensor_readings();
|
||||
|
||||
keep_uart_on();
|
||||
|
||||
while(1) {
|
||||
|
||||
PROCESS_YIELD();
|
||||
|
||||
if(ev == PROCESS_EVENT_TIMER) {
|
||||
if(data == &et) {
|
||||
leds_toggle(CC26XX_DEMO_LEDS_PERIODIC);
|
||||
|
||||
get_sync_sensor_readings();
|
||||
|
||||
etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL);
|
||||
}
|
||||
} else if(ev == sensors_event) {
|
||||
if(data == CC26XX_DEMO_SENSOR_1) {
|
||||
printf("Left: Pin %d, press duration %d clock ticks\n",
|
||||
(CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_STATE),
|
||||
(CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_DURATION));
|
||||
|
||||
if((CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_DURATION) >
|
||||
CLOCK_SECOND) {
|
||||
printf("Long button press!\n");
|
||||
}
|
||||
|
||||
leds_toggle(CC26XX_DEMO_LEDS_BUTTON);
|
||||
} else if(data == CC26XX_DEMO_SENSOR_2) {
|
||||
leds_on(CC26XX_DEMO_LEDS_REBOOT);
|
||||
watchdog_reboot();
|
||||
} else if(data == CC26XX_DEMO_SENSOR_3) {
|
||||
printf("Up\n");
|
||||
} else if(data == CC26XX_DEMO_SENSOR_4) {
|
||||
printf("Down\n");
|
||||
} else if(data == CC26XX_DEMO_SENSOR_5) {
|
||||
#if BOARD_SENSORTAG
|
||||
if(buzzer_state()) {
|
||||
buzzer_stop();
|
||||
} else {
|
||||
buzzer_start(1000);
|
||||
}
|
||||
} 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 == &sht_21_sensor) {
|
||||
get_sht_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();
|
||||
#else
|
||||
printf("Sel: Pin %d, press duration %d clock ticks\n",
|
||||
button_select_sensor.value(BUTTON_SENSOR_VALUE_STATE),
|
||||
button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION));
|
||||
#endif
|
||||
}
|
||||
} else if(ev == serial_line_event_message) {
|
||||
leds_toggle(CC26XX_DEMO_LEDS_SERIAL_IN);
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
24
examples/cc26xx/cc26xx-web-demo/Makefile
Normal file
24
examples/cc26xx/cc26xx-web-demo/Makefile
Normal file
|
@ -0,0 +1,24 @@
|
|||
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
|
||||
|
||||
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
|
||||
|
||||
PROJECTDIRS += $(REST_RESOURCES_DIR)
|
||||
PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES)
|
||||
|
||||
PROJECT_SOURCEFILES += cetic-6lbr-client.c coap-server.c net-uart.c mqtt-client.c
|
||||
PROJECT_SOURCEFILES += httpd-simple.c
|
||||
|
||||
CONTIKI_WITH_IPV6 = 1
|
||||
|
||||
# REST Engine shall use Erbium CoAP implementation
|
||||
APPS += er-coap
|
||||
APPS += rest-engine
|
||||
APPS += mqtt
|
||||
|
||||
CONTIKI=../../..
|
||||
include $(CONTIKI)/Makefile.include
|
1
examples/cc26xx/cc26xx-web-demo/Makefile.target
Normal file
1
examples/cc26xx/cc26xx-web-demo/Makefile.target
Normal file
|
@ -0,0 +1 @@
|
|||
TARGET = srf06-cc26xx
|
169
examples/cc26xx/cc26xx-web-demo/README.md
Normal file
169
examples/cc26xx/cc26xx-web-demo/README.md
Normal file
|
@ -0,0 +1,169 @@
|
|||
CC26xx Web Demo Readme
|
||||
======================
|
||||
This demo project combines a number of web-based applications aiming to
|
||||
demonstrate the CC26xx capability. The applications are:
|
||||
|
||||
* A network-based UART
|
||||
* A client for [6lbr](http://cetic.github.io/6lbr/)
|
||||
* A CoAP server
|
||||
* An MQTT client
|
||||
* 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.
|
||||
|
||||
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.
|
||||
|
||||
You can disable some of those individual components by changing the respective
|
||||
defines in `project-conf.h`. For instance, to disable the CoAP functionality,
|
||||
set `#define CC26XX_WEB_DEMO_CONF_COAP_SERVER 0`. The web server cannot be
|
||||
disabled, all other aforementioned applications can.
|
||||
|
||||
Network UART (net-uart)
|
||||
-----------------------
|
||||
This example only makes sense if you are using the Srf or if you have taken
|
||||
the sensortag out of its case and you have it connected over JTAG to the Srf.
|
||||
|
||||
The net-uart does two things:
|
||||
|
||||
* When you type a string to the UART console, the string will be sent verbatim
|
||||
to a remote UDP port 7777 listener. This can be for example a netcat listener
|
||||
on a linux or OS X PC:
|
||||
`nc -6ulkw 1 7777`
|
||||
* The net-uart also listens to UDP port 7777 and when it receives a string over
|
||||
UDP, it will print it verbatim over UART.
|
||||
|
||||
The example will initially send packets to a hard-coded IPv6 address. This can
|
||||
be changed very easily by entering a different IPv6 address to the console.
|
||||
Thus, when the serial input string is an IPv6 address, it will not be sent as
|
||||
any other string would, but instead it will configure the example to send to a
|
||||
different remote address. This new IPv6 address is not persistent across
|
||||
device reboots.
|
||||
|
||||
6lbr Client
|
||||
-----------
|
||||
This will periodically send a UDP packet to your 6lbr, containing network
|
||||
information, which will be used by 6lbr to construct a network graph. To see
|
||||
this in action, fire up a browser and navigate to the 6lbr web page. The
|
||||
default address is http://[bbbb::100]. Once the page loads, click the 'sensors'
|
||||
tab, as per the image below.
|
||||
|
||||
![6lbr](img/6lbr-web.png)
|
||||
|
||||
CoAP Server
|
||||
-----------
|
||||
For this functionality to work, you will need to install the
|
||||
[Copper (Cu)](https://addons.mozilla.org/en-US/firefox/addon/copper-270430/)
|
||||
addon to your browser.
|
||||
|
||||
From the sensors tab in the 6lbr web page, click the 'coap' link in the line
|
||||
corresponding to your CC26xx device. Once the addon fires up, select
|
||||
".well-known/core" in the left pane and then hit the 'Get' button at the top.
|
||||
|
||||
![CoAP Resources](img/coap-resources.png)
|
||||
|
||||
The Device will respond with a list of all available CoAP resources. This list
|
||||
will be different between the Srf and the SensorTag. The screenshot below shows
|
||||
a (partial) list of resources exported by the SensorTag CoAP server. Select
|
||||
a resource on the left pane and hit 'Get' to retrieve its value. Select
|
||||
`lt/g` and hit 'Post' to toggle the green LED, `lt/r` for the red one.
|
||||
|
||||
You can also use CoAP to enable/disable BLE advertisements! Select
|
||||
`dev/ble_advd` and then hit the "Outgoing" button in the payload panel. Type in
|
||||
the desired payload, which can be:
|
||||
|
||||
* `mode=on|off`
|
||||
* `name=<name>`
|
||||
* `interval=<secs>`
|
||||
|
||||
or a combination of both delimited with an amp. For example, you can set as
|
||||
payload `mode=on&name=My CC26xx Device 4&interval=5`. Once you have set the
|
||||
payload, hit either the POST or PUT button.
|
||||
|
||||
Bear in mind that you must set `name` at least once before enabling BLE
|
||||
advertisements. If you fail to do so, the RF will refuse to enter BLE mode and
|
||||
the CoAP engine will return 4.03 forbidden. The values of `name` and `interval`
|
||||
persist across BLE on/off cycles, so you only have to set them once. The values
|
||||
do _not_ persist through device powercycles.
|
||||
|
||||
HTTPD
|
||||
-----
|
||||
Back on the 6lbr page, hit the 'web' link corresponding to your device. This
|
||||
will take you to a web page served by the CC26xx. The HTTPD serves two pages:
|
||||
|
||||
* index.html: Provides sensor readings and network information
|
||||
* config.html: Can be used to configure the MQTT client (more below)
|
||||
|
||||
In the navigation bar at the top there is also a third link, which will take
|
||||
you directly to your device's page on IBM's quickstart service.
|
||||
|
||||
IBM Quickstart / MQTT Client
|
||||
----------------------------
|
||||
The MQTT client can be used to:
|
||||
|
||||
* Publish sensor readings to an MQTT broker.
|
||||
* Subscribe to a topic and as a result receive commands from an MQTT broker
|
||||
|
||||
The device will try to connect to IBM's quickstart over NAT64, so you will
|
||||
need a NAT64 gateway in your network to make this work. A guide on how to
|
||||
setup NAT64 is out of scope here. If this is not an option for you, you can
|
||||
configure the device to publish to a local MQTT broker over end-to-end IPv6.
|
||||
See below on how to change the destination broker's address.
|
||||
|
||||
By default the device will publish readings to IBM's quickstart service. The
|
||||
publish messages include sensor readings but also some other information such
|
||||
as device uptime in seconds and a message sequence number. Click the "IBM
|
||||
Quickstart" link in the web page to go directly to your device's page
|
||||
on Quickstart. After a few seconds, you will see something like this:
|
||||
|
||||
![A SensorTag on IBM Quickstart](img/quickstart-sensortag.png)
|
||||
|
||||
Sensor readings are only published if they have changed since the previous
|
||||
reading (BatMon is an exception and always gets published). Additionally, you
|
||||
can turn on/off individual readings from the config.html web page, as per the
|
||||
figure below.
|
||||
|
||||
![Sensor Readings Configuration](img/sensor-readings-config.png)
|
||||
|
||||
Some of the MQTT client functionality can be configured even further:
|
||||
|
||||
* You can change the broker IP and port. This is useful if you want to use your
|
||||
own MQTT broker instead of IBM's quickstart. The example has been tested
|
||||
successfully with [mosquitto](http://mosquitto.org/)
|
||||
* You can change the publish interval. Recommended values are 10secs or higher.
|
||||
You will not be allowed to set this to anything less than 5 seconds.
|
||||
* If you want to use IBM's cloud service with a registered device, change
|
||||
'Org ID' and provide an 'Auth Token', which acts as a 'password', but bear in
|
||||
mind that it gets transported in clear text, both over the web configuration
|
||||
page as well as inside MQTT messages.
|
||||
* The remaining configuration options are related to the content of MQTT
|
||||
messages and in general you won't have to modify them.
|
||||
|
||||
For the SensorTag, changes to the MQTT configuration get saved in external
|
||||
flash and persist across device restarts. The same does not hold true for
|
||||
Srf+EM builds.
|
||||
|
||||
You can also subscribe to topics and receive commands, but this will only
|
||||
work if you use "Org ID" != 'quickstart'. Thus, if you provide a different
|
||||
Org ID (do not forget the auth token!), the device will subscribe to:
|
||||
|
||||
`iot-2/cmd/+/fmt/json`
|
||||
|
||||
You can then use this to toggle LEDs or to turn the buzzer on and off.
|
||||
The buzzer is only available on the SensorTag. To do this, you can for example
|
||||
use mosquitto client to publish to `iot-2/cmd/leds/fmt/json`. So, to turn
|
||||
the buzzer on, you would do this:
|
||||
|
||||
`mosquitto_pub -h <broker IP> -m "1" -t iot-2/cmd/buzz/fmt/json`
|
||||
|
||||
Where `broker IP` should be replaced with the IP address of your mosquitto
|
||||
broker (the one where you device has subscribed). Replace `-m "1'` with `-m "0"`
|
||||
to turn the buzzer back off. Replace `buzz` with `leds` in the topic to change
|
||||
the state of the LED.
|
||||
|
||||
Bear in mind that, even though the topic suggests that messages are of json
|
||||
format, they are in fact not. This was done in order to avoid linking a json
|
||||
parser into the firmware.
|
893
examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c
Normal file
893
examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c
Normal file
|
@ -0,0 +1,893 @@
|
|||
/*
|
||||
* 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 "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, sht_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;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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
|
||||
|
||||
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(sht_temp, CC26XX_WEB_DEMO_SENSOR_SHT_TEMP,
|
||||
"SHT Temp", "sht-temp", "sht_temp",
|
||||
CC26XX_WEB_DEMO_UNIT_TEMP);
|
||||
DEMO_SENSOR(sht_hum, CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY,
|
||||
"SHT Humidity", "sht-humidity", "sht_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_sht_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;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
HTTPD_SIMPLE_POST_HANDLER(sensor, sensor_readings_handler);
|
||||
HTTPD_SIMPLE_POST_HANDLER(defaults, defaults_post_handler);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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.%02d", value >> 2,
|
||||
(value & 0x00000003) * 25);
|
||||
}
|
||||
}
|
||||
|
||||
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_sht_reading()
|
||||
{
|
||||
int value;
|
||||
char *buf;
|
||||
clock_time_t next = SENSOR_READING_PERIOD +
|
||||
(random_rand() % SENSOR_READING_RANDOM);
|
||||
|
||||
if(sht_temp_reading.publish) {
|
||||
value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP);
|
||||
if(value != CC26XX_SENSOR_READING_ERROR) {
|
||||
sht_temp_reading.raw = value;
|
||||
|
||||
compare_and_update(&sht_temp_reading);
|
||||
|
||||
buf = sht_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(sht_hum_reading.publish) {
|
||||
value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY);
|
||||
if(value != CC26XX_SENSOR_READING_ERROR) {
|
||||
sht_hum_reading.raw = value;
|
||||
|
||||
compare_and_update(&sht_hum_reading);
|
||||
|
||||
buf = sht_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(&sht_timer, next, init_sht_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);
|
||||
|
||||
SENSORS_DEACTIVATE(opt_3001_sensor);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_sht_reading(void *data)
|
||||
{
|
||||
if(sht_hum_reading.publish || sht_temp_reading.publish) {
|
||||
SENSORS_ACTIVATE(sht_21_sensor);
|
||||
} else {
|
||||
ctimer_set(&sht_timer, CLOCK_SECOND, init_sht_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_sht_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, &sht_hum_reading);
|
||||
list_add(sensor_list, &sht_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 */
|
||||
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);
|
||||
|
||||
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 == 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 == 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
|
||||
} 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 == &sht_21_sensor) {
|
||||
get_sht_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();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
210
examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h
Normal file
210
examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* 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-examples
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc26xx-web-demo CC26xx Web Demo
|
||||
* @{
|
||||
*
|
||||
* An example demonstrating:
|
||||
* * how to use a CC26XX-powered node in a deployment driven by a 6LBR
|
||||
* * how to expose on-device sensors as CoAP resources
|
||||
* * how to build a small web page which reports networking and sensory data
|
||||
* * how to configure functionality through the aforementioned web page using
|
||||
* HTTP POST requests
|
||||
* * a network-based UART
|
||||
*
|
||||
* \file
|
||||
* Main header file for the CC26XX web demo.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef CC26XX_WEB_DEMO_H_
|
||||
#define CC26XX_WEB_DEMO_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "dev/leds.h"
|
||||
#include "sys/process.h"
|
||||
#include "mqtt-client.h"
|
||||
#include "net-uart.h"
|
||||
|
||||
#include <stdint.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef CC26XX_WEB_DEMO_CONF_MQTT_CLIENT
|
||||
#define CC26XX_WEB_DEMO_MQTT_CLIENT CC26XX_WEB_DEMO_CONF_MQTT_CLIENT
|
||||
#else
|
||||
#define CC26XX_WEB_DEMO_MQTT_CLIENT 1
|
||||
#endif
|
||||
|
||||
#ifdef CC26XX_WEB_DEMO_CONF_6LBR_CLIENT
|
||||
#define CC26XX_WEB_DEMO_6LBR_CLIENT CC26XX_WEB_DEMO_CONF_6LBR_CLIENT
|
||||
#else
|
||||
#define CC26XX_WEB_DEMO_6LBR_CLIENT 1
|
||||
#endif
|
||||
|
||||
#ifdef CC26XX_WEB_DEMO_CONF_COAP_SERVER
|
||||
#define CC26XX_WEB_DEMO_COAP_SERVER CC26XX_WEB_DEMO_CONF_COAP_SERVER
|
||||
#else
|
||||
#define CC26XX_WEB_DEMO_COAP_SERVER 1
|
||||
#endif
|
||||
|
||||
#ifdef CC26XX_WEB_DEMO_CONF_NET_UART
|
||||
#define CC26XX_WEB_DEMO_NET_UART CC26XX_WEB_DEMO_CONF_NET_UART
|
||||
#else
|
||||
#define CC26XX_WEB_DEMO_NET_UART 1
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* User configuration */
|
||||
/* Take a sensor reading on button press */
|
||||
#define CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER &button_left_sensor
|
||||
|
||||
/* Payload length of ICMPv6 echo requests used to measure RSSI with def rt */
|
||||
#define CC26XX_WEB_DEMO_ECHO_REQ_PAYLOAD_LEN 20
|
||||
|
||||
#if BOARD_SENSORTAG
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
#define CC26XX_WEB_DEMO_STATUS_LED LEDS_GREEN
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* A timeout used when waiting to connect to a network */
|
||||
#define CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC (CLOCK_SECOND >> 3)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Default configuration values */
|
||||
#define CC26XX_WEB_DEMO_DEFAULT_ORG_ID "quickstart"
|
||||
#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc26xx"
|
||||
#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
|
||||
#define CC26XX_WEB_DEMO_DEFAULT_PUBLISH_INTERVAL (30 * CLOCK_SECOND)
|
||||
#define CC26XX_WEB_DEMO_DEFAULT_KEEP_ALIVE_TIMER 60
|
||||
#define CC26XX_WEB_DEMO_DEFAULT_RSSI_MEAS_INTERVAL (CLOCK_SECOND * 30)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* You normally won't have to change anything from here onwards unless you are
|
||||
* extending the example
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Sensor types */
|
||||
#define CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP 0
|
||||
#define CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT 1
|
||||
#define CC26XX_WEB_DEMO_SENSOR_BMP_PRES 2
|
||||
#define CC26XX_WEB_DEMO_SENSOR_BMP_TEMP 3
|
||||
#define CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT 4
|
||||
#define CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT 5
|
||||
#define CC26XX_WEB_DEMO_SENSOR_SHT_TEMP 6
|
||||
#define CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY 7
|
||||
#define CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT 8
|
||||
#define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X 9
|
||||
#define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y 10
|
||||
#define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z 11
|
||||
#define CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X 12
|
||||
#define CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y 13
|
||||
#define CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z 14
|
||||
/*---------------------------------------------------------------------------*/
|
||||
extern process_event_t cc26xx_web_demo_publish_event;
|
||||
extern process_event_t cc26xx_web_demo_config_loaded_event;
|
||||
extern process_event_t cc26xx_web_demo_load_config_defaults;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define CC26XX_WEB_DEMO_UNIT_TEMP "C"
|
||||
#define CC26XX_WEB_DEMO_UNIT_VOLT "mV"
|
||||
#define CC26XX_WEB_DEMO_UNIT_PRES "hPa"
|
||||
#define CC26XX_WEB_DEMO_UNIT_HUMIDITY "%RH"
|
||||
#define CC26XX_WEB_DEMO_UNIT_LIGHT "lux"
|
||||
#define CC26XX_WEB_DEMO_UNIT_ACC "G"
|
||||
#define CC26XX_WEB_DEMO_UNIT_GYRO "deg per sec"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* A data type for sensor readings, internally stored in a linked list */
|
||||
#define CC26XX_WEB_DEMO_CONVERTED_LEN 12
|
||||
|
||||
typedef struct cc26xx_web_demo_sensor_reading {
|
||||
struct cc26xx_web_demo_sensor_reading *next;
|
||||
int raw;
|
||||
int last;
|
||||
const char *descr;
|
||||
const char *xml_element;
|
||||
const char *form_field;
|
||||
char *units;
|
||||
uint8_t type;
|
||||
uint8_t publish;
|
||||
uint8_t changed;
|
||||
char converted[CC26XX_WEB_DEMO_CONVERTED_LEN];
|
||||
} cc26xx_web_demo_sensor_reading_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Global configuration */
|
||||
typedef struct cc26xx_web_demo_config_s {
|
||||
uint32_t magic;
|
||||
int len;
|
||||
uint32_t sensors_bitmap;
|
||||
mqtt_client_config_t mqtt_config;
|
||||
net_uart_config_t net_uart;
|
||||
} cc26xx_web_demo_config_t;
|
||||
|
||||
extern cc26xx_web_demo_config_t cc26xx_web_demo_config;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Performs a lookup for a reading of a specific type of sensor
|
||||
* \param sens_type CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP...
|
||||
* \return A pointer to the reading data structure or NULL
|
||||
*/
|
||||
const cc26xx_web_demo_sensor_reading_t *cc26xx_web_demo_sensor_lookup(int sens_type);
|
||||
|
||||
/**
|
||||
* \brief Returns the first available sensor reading
|
||||
* \return A pointer to the reading data structure or NULL
|
||||
*/
|
||||
const cc26xx_web_demo_sensor_reading_t *cc26xx_web_demo_sensor_first(void);
|
||||
|
||||
/**
|
||||
* \brief Print an IPv6 address into a buffer
|
||||
* \param buf A pointer to the buffer where this function will print the IPv6
|
||||
* address
|
||||
* \param buf_len the length of the buffer
|
||||
* \param addr A pointer to the IPv6 address
|
||||
* \return The number of bytes written to the buffer
|
||||
*
|
||||
* It is the caller's responsibility to allocate enough space for buf
|
||||
*/
|
||||
int cc26xx_web_demo_ipaddr_sprintf(char *buf, uint8_t buf_len,
|
||||
const uip_ipaddr_t *addr);
|
||||
|
||||
/**
|
||||
* \brief Resets the example to a default configuration
|
||||
*/
|
||||
void cc26xx_web_demo_restore_defaults(void);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* CC26XX_WEB_DEMO_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
197
examples/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c
Normal file
197
examples/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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
|
||||
* An implementation of a 6LBR UDP client. Is used to populate the 6LBR
|
||||
* web server's 'sensors' tab
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "contiki-lib.h"
|
||||
#include "contiki-net.h"
|
||||
#include "net/rpl/rpl.h"
|
||||
#include "net/ip/uip.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define DEBUG 0
|
||||
#include "net/ip/uip-debug.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef CETIC_6LBR_NODE_INFO_PORT
|
||||
#define CETIC_6LBR_NODE_INFO_PORT 3000
|
||||
#endif
|
||||
|
||||
#define MAX_PAYLOAD_LEN 40
|
||||
#define MSG_INTERVAL (60 * CLOCK_SECOND)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct uip_udp_conn *client_conn = NULL;
|
||||
static struct etimer et;
|
||||
static uip_ip6addr_t dest_addr;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(cetic_6lbr_client_process, "6LBR Client Process");
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
tcpip_handler(void)
|
||||
{
|
||||
char *str;
|
||||
|
||||
if(uip_newdata()) {
|
||||
str = uip_appdata;
|
||||
str[uip_datalen()] = '\0';
|
||||
PRINTF("Response from the server: '%s'\n", str);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char *
|
||||
add_ipaddr(char *buf, const uip_ipaddr_t *addr)
|
||||
{
|
||||
uint16_t a;
|
||||
unsigned int i;
|
||||
int f;
|
||||
char *p = buf;
|
||||
|
||||
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) {
|
||||
p += sprintf(p, "::");
|
||||
}
|
||||
} else {
|
||||
if(f > 0) {
|
||||
f = -1;
|
||||
} else if(i > 0) {
|
||||
p += sprintf(p, ":");
|
||||
}
|
||||
p += sprintf(p, "%04x", a);
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
timeout_handler(void)
|
||||
{
|
||||
static int seq_id;
|
||||
char buf[MAX_PAYLOAD_LEN];
|
||||
int i;
|
||||
uip_ip6addr_t *globaladdr = NULL;
|
||||
uint16_t dest_port = CETIC_6LBR_NODE_INFO_PORT;
|
||||
int has_dest = 0;
|
||||
rpl_dag_t *dag;
|
||||
|
||||
uip_ds6_addr_t *addr_desc = uip_ds6_get_global(ADDR_PREFERRED);
|
||||
if(addr_desc != NULL) {
|
||||
globaladdr = &addr_desc->ipaddr;
|
||||
dag = rpl_get_any_dag();
|
||||
if(dag) {
|
||||
uip_ipaddr_copy(&dest_addr, globaladdr);
|
||||
memcpy(&dest_addr.u8[8], &dag->dag_id.u8[8], sizeof(uip_ipaddr_t) / 2);
|
||||
has_dest = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_dest) {
|
||||
if(client_conn == NULL) {
|
||||
PRINTF("UDP-CLIENT: address destination: ");
|
||||
PRINT6ADDR(&dest_addr);
|
||||
PRINTF("\n");
|
||||
client_conn = udp_new(&dest_addr, UIP_HTONS(dest_port), NULL);
|
||||
|
||||
if(client_conn != NULL) {
|
||||
PRINTF("Created a connection with the server ");
|
||||
PRINT6ADDR(&client_conn->ripaddr);
|
||||
PRINTF(" local/remote port %u/%u\n",
|
||||
UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport));
|
||||
} else {
|
||||
PRINTF("Could not open connection\n");
|
||||
}
|
||||
} else {
|
||||
if(memcmp(&client_conn->ripaddr, &dest_addr, sizeof(uip_ipaddr_t)) != 0) {
|
||||
PRINTF("UDP-CLIENT: new address destination: ");
|
||||
PRINT6ADDR(&dest_addr);
|
||||
PRINTF("\n");
|
||||
uip_udp_remove(client_conn);
|
||||
client_conn = udp_new(&dest_addr, UIP_HTONS(dest_port), NULL);
|
||||
if(client_conn != NULL) {
|
||||
PRINTF("Created a connection with the server ");
|
||||
PRINT6ADDR(&client_conn->ripaddr);
|
||||
PRINTF(" local/remote port %u/%u\n",
|
||||
UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport));
|
||||
} else {
|
||||
PRINTF("Could not open connection\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(client_conn != NULL) {
|
||||
PRINTF("Client sending to: ");
|
||||
PRINT6ADDR(&client_conn->ripaddr);
|
||||
i = sprintf(buf, "%d | ", ++seq_id);
|
||||
dag = rpl_get_any_dag();
|
||||
if(dag && dag->instance->def_route) {
|
||||
add_ipaddr(buf + i, &dag->instance->def_route->ipaddr);
|
||||
} else {
|
||||
sprintf(buf + i, "(null)");
|
||||
}
|
||||
PRINTF(" (msg: %s)\n", buf);
|
||||
uip_udp_packet_send(client_conn, buf, strlen(buf));
|
||||
} else {
|
||||
PRINTF("No connection created\n");
|
||||
}
|
||||
} else {
|
||||
PRINTF("No address configured\n");
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(cetic_6lbr_client_process, ev, data)
|
||||
{
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
printf("6LBR Client Process\n");
|
||||
|
||||
memset(&dest_addr, 0, sizeof(uip_ipaddr_t));
|
||||
|
||||
etimer_set(&et, MSG_INTERVAL);
|
||||
while(1) {
|
||||
PROCESS_YIELD();
|
||||
if(etimer_expired(&et)) {
|
||||
timeout_handler();
|
||||
etimer_set(&et, MSG_INTERVAL);
|
||||
} else if(ev == tcpip_event) {
|
||||
tcpip_handler();
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
157
examples/cc26xx/cc26xx-web-demo/coap-server.c
Normal file
157
examples/cc26xx/cc26xx-web-demo/coap-server.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* 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
|
||||
* A CC26XX-specific CoAP server
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
#include "rest-engine.h"
|
||||
#include "board-peripherals.h"
|
||||
#include "dev/cc26xx-rf.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Common resources */
|
||||
extern resource_t res_leds;
|
||||
|
||||
extern resource_t res_batmon_temp;
|
||||
extern resource_t res_batmon_volt;
|
||||
|
||||
extern resource_t res_device_sw;
|
||||
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_ble_advd;
|
||||
#endif
|
||||
|
||||
/* Board-specific resources */
|
||||
#if BOARD_SENSORTAG
|
||||
extern resource_t res_bmp280_temp;
|
||||
extern resource_t res_bmp280_press;
|
||||
extern resource_t res_tmp007_amb;
|
||||
extern resource_t res_tmp007_obj;
|
||||
extern resource_t res_sht21_temp;
|
||||
extern resource_t res_sht21_hum;
|
||||
extern resource_t res_opt3001_light;
|
||||
extern resource_t res_mpu_acc_x;
|
||||
extern resource_t res_mpu_acc_y;
|
||||
extern resource_t res_mpu_acc_z;
|
||||
extern resource_t res_mpu_gyro_x;
|
||||
extern resource_t res_mpu_gyro_y;
|
||||
extern resource_t res_mpu_gyro_z;
|
||||
extern resource_t res_toggle_red;
|
||||
extern resource_t res_toggle_green;
|
||||
#else
|
||||
extern resource_t res_toggle_red;
|
||||
extern resource_t res_toggle_green;
|
||||
extern resource_t res_toggle_orange;
|
||||
extern resource_t res_toggle_yellow;
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const char *coap_server_not_found_msg = "Resource not found";
|
||||
const char *coap_server_supported_msg = "Supported:"
|
||||
"text/plain,"
|
||||
"application/json,"
|
||||
"application/xml";
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
start_board_resources(void)
|
||||
{
|
||||
#if BOARD_SENSORTAG
|
||||
rest_activate_resource(&res_bmp280_temp, "sen/bar/temp");
|
||||
rest_activate_resource(&res_bmp280_press, "sen/bar/pres");
|
||||
rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb");
|
||||
rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj");
|
||||
rest_activate_resource(&res_sht21_temp, "sen/sht/t");
|
||||
rest_activate_resource(&res_sht21_hum, "sen/sht/h");
|
||||
rest_activate_resource(&res_opt3001_light, "sen/opt/light");
|
||||
rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x");
|
||||
rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y");
|
||||
rest_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z");
|
||||
rest_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x");
|
||||
rest_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y");
|
||||
rest_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z");
|
||||
rest_activate_resource(&res_leds, "lt");
|
||||
rest_activate_resource(&res_toggle_green, "lt/g");
|
||||
rest_activate_resource(&res_toggle_red, "lt/r");
|
||||
#elif BOARD_SMARTRF06EB
|
||||
rest_activate_resource(&res_leds, "lt");
|
||||
rest_activate_resource(&res_toggle_red, "lt/r");
|
||||
rest_activate_resource(&res_toggle_yellow, "lt/y");
|
||||
rest_activate_resource(&res_toggle_green, "lt/g");
|
||||
rest_activate_resource(&res_toggle_orange, "lt/o");
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(coap_server_process, "CC26XX CoAP Server");
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(coap_server_process, ev, data)
|
||||
{
|
||||
PROCESS_BEGIN();
|
||||
|
||||
printf("CC26XX CoAP Server\n");
|
||||
|
||||
/* Initialize the REST engine. */
|
||||
rest_init_engine();
|
||||
|
||||
rest_activate_resource(&res_batmon_temp, "sen/batmon/temp");
|
||||
rest_activate_resource(&res_batmon_volt, "sen/batmon/voltage");
|
||||
|
||||
rest_activate_resource(&res_device_hw, "dev/mdl/hw");
|
||||
rest_activate_resource(&res_device_sw, "dev/mdl/sw");
|
||||
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_ble_advd, "dev/ble_advd");
|
||||
#endif
|
||||
|
||||
start_board_resources();
|
||||
|
||||
/* Define application-specific events here. */
|
||||
while(1) {
|
||||
PROCESS_WAIT_EVENT();
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
52
examples/cc26xx/cc26xx-web-demo/coap-server.h
Normal file
52
examples/cc26xx/cc26xx-web-demo/coap-server.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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
|
||||
* Header file for the CC26xx web demo CoAP functionality
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "sys/process.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef COAP_SERVER_H_
|
||||
#define COAP_SERVER_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
extern const char *coap_server_not_found_msg;
|
||||
extern const char *coap_server_supported_msg;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_NAME(coap_server_process);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* COAP_SERVER_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
1298
examples/cc26xx/cc26xx-web-demo/httpd-simple.c
Normal file
1298
examples/cc26xx/cc26xx-web-demo/httpd-simple.c
Normal file
File diff suppressed because it is too large
Load diff
101
examples/cc26xx/cc26xx-web-demo/httpd-simple.h
Normal file
101
examples/cc26xx/cc26xx-web-demo/httpd-simple.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Swedish Institute of Computer Science.
|
||||
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
|
||||
*
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \file
|
||||
* Header file for the HTTPD of the cc26xx web demo example.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
* Niclas Finne <nfi@sics.se>
|
||||
* Joakim Eriksson <joakime@sics.se>
|
||||
* Texas Instruments Incorporated - http://www.ti.com/
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef HTTPD_SIMPLE_H_
|
||||
#define HTTPD_SIMPLE_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki-net.h"
|
||||
#include "sys/process.h"
|
||||
#include "cc26xx-web-demo.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Ideally a multiple of TCP_MSS */
|
||||
#ifdef HTTPD_SIMPLE_CONF_MAIN_BUF_SIZE
|
||||
#define HTTPD_SIMPLE_MAIN_BUF_SIZE HTTPD_SIMPLE_CONF_BUF_SIZE
|
||||
#else
|
||||
#define HTTPD_SIMPLE_MAIN_BUF_SIZE UIP_TCP_MSS
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define HTTPD_PATHLEN 16
|
||||
#define HTTPD_INBUF_LEN (HTTPD_PATHLEN + 10)
|
||||
|
||||
#define TMP_BUF_SIZE (UIP_TCP_MSS + 1)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* POST request handlers */
|
||||
#define HTTPD_SIMPLE_POST_HANDLER_OK 1
|
||||
#define HTTPD_SIMPLE_POST_HANDLER_UNKNOWN 0
|
||||
#define HTTPD_SIMPLE_POST_HANDLER_ERROR 0xFFFFFFFF
|
||||
|
||||
/**
|
||||
* \brief Datatype for a handler which can process incoming POST requests
|
||||
* \param key The configuration key to be updated
|
||||
* \param key_len The length of the key argument
|
||||
* \param val The new configuration value for key
|
||||
* \param val_len The length of the value argument
|
||||
*
|
||||
* \return 1: HTTPD_SIMPLE_POST_HANDLER_OK if the function can handle the
|
||||
* request, HTTPD_SIMPLE_POST_HANDLER_UNKNOWN if it does not know how to handle
|
||||
* it. HTTPD_SIMPLE_POST_HANDLER_ERROR if it does know how to handle it but
|
||||
* the request was malformed.
|
||||
*/
|
||||
typedef struct httpd_simple_post_handler {
|
||||
struct httpd_simple_post_handler *next;
|
||||
int (*handler)(char *key, int key_len, char *val, int val_len);
|
||||
} httpd_simple_post_handler_t;
|
||||
|
||||
/* Declare a handler */
|
||||
#define HTTPD_SIMPLE_POST_HANDLER(name, fp) \
|
||||
httpd_simple_post_handler_t name##_handler = { NULL, fp }
|
||||
|
||||
/**
|
||||
* \brief Register a handler for POST requests
|
||||
* \param h A pointer to the handler structure
|
||||
*/
|
||||
void httpd_simple_register_post_handler(httpd_simple_post_handler_t *h);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* An event generated by the HTTPD when a new configuration request has been
|
||||
* received
|
||||
*/
|
||||
extern process_event_t httpd_simple_event_new_config;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_NAME(httpd_simple_process);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* HTTPD_SIMPLE_H_ */
|
BIN
examples/cc26xx/cc26xx-web-demo/img/6lbr-web.png
Normal file
BIN
examples/cc26xx/cc26xx-web-demo/img/6lbr-web.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 80 KiB |
BIN
examples/cc26xx/cc26xx-web-demo/img/coap-resources.png
Normal file
BIN
examples/cc26xx/cc26xx-web-demo/img/coap-resources.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 274 KiB |
BIN
examples/cc26xx/cc26xx-web-demo/img/quickstart-sensortag.png
Normal file
BIN
examples/cc26xx/cc26xx-web-demo/img/quickstart-sensortag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 155 KiB |
BIN
examples/cc26xx/cc26xx-web-demo/img/sensor-readings-config.png
Normal file
BIN
examples/cc26xx/cc26xx-web-demo/img/sensor-readings-config.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
examples/cc26xx/cc26xx-web-demo/img/well-known-core.png
Normal file
BIN
examples/cc26xx/cc26xx-web-demo/img/well-known-core.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
975
examples/cc26xx/cc26xx-web-demo/mqtt-client.c
Normal file
975
examples/cc26xx/cc26xx-web-demo/mqtt-client.c
Normal file
|
@ -0,0 +1,975 @@
|
|||
/*
|
||||
* 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
|
||||
* MQTT/IBM cloud service client for the CC26XX web demo.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki-conf.h"
|
||||
#include "rpl/rpl-private.h"
|
||||
#include "mqtt.h"
|
||||
#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"
|
||||
#include "button-sensor.h"
|
||||
#include "board-peripherals.h"
|
||||
#include "cc26xx-web-demo.h"
|
||||
#include "dev/leds.h"
|
||||
#include "mqtt-client.h"
|
||||
#include "httpd-simple.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* IBM server: messaging.quickstart.internetofthings.ibmcloud.com
|
||||
* (184.172.124.189) mapped in an NAT64 (prefix 64:ff9b::/96) IPv6 address
|
||||
* Note: If not able to connect; lookup the IP address again as it may change.
|
||||
*
|
||||
* If the node has a broker IP setting saved on flash, this value here will
|
||||
* get ignored
|
||||
*/
|
||||
static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd";
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* A timeout used when waiting for something to happen (e.g. to connect or to
|
||||
* disconnect)
|
||||
*/
|
||||
#define STATE_MACHINE_PERIODIC (CLOCK_SECOND >> 1)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Provide visible feedback via LEDS during various states */
|
||||
/* When connecting to broker */
|
||||
#define CONNECTING_LED_DURATION (CLOCK_SECOND >> 3)
|
||||
|
||||
/* Each time we try to publish */
|
||||
#define PUBLISH_LED_ON_DURATION (CLOCK_SECOND)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Connections and reconnections */
|
||||
#define RETRY_FOREVER 0xFF
|
||||
#define RECONNECT_INTERVAL (CLOCK_SECOND * 2)
|
||||
|
||||
/*
|
||||
* 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 CONNECTION_STABLE_TIME (CLOCK_SECOND * 5)
|
||||
#define NEW_CONFIG_WAIT_INTERVAL (CLOCK_SECOND * 20)
|
||||
static struct timer connection_life;
|
||||
static uint8_t connect_attempt;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Various states */
|
||||
static uint8_t state;
|
||||
#define MQTT_CLIENT_STATE_INIT 0
|
||||
#define MQTT_CLIENT_STATE_REGISTERED 1
|
||||
#define MQTT_CLIENT_STATE_CONNECTING 2
|
||||
#define MQTT_CLIENT_STATE_CONNECTED 3
|
||||
#define MQTT_CLIENT_STATE_PUBLISHING 4
|
||||
#define MQTT_CLIENT_STATE_DISCONNECTED 5
|
||||
#define MQTT_CLIENT_STATE_NEWCONFIG 6
|
||||
#define MQTT_CLIENT_STATE_CONFIG_ERROR 0xFE
|
||||
#define MQTT_CLIENT_STATE_ERROR 0xFF
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Maximum TCP segment size for outgoing segments of our socket */
|
||||
#define MQTT_CLIENT_MAX_SEGMENT_SIZE 32
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Buffers for Client ID and Topic.
|
||||
* Make sure they are large enough to hold the entire respective string
|
||||
*
|
||||
* d:quickstart:status:EUI64 is 32 bytes long
|
||||
* iot-2/evt/status/fmt/json is 25 bytes
|
||||
* We also need space for the null termination
|
||||
*/
|
||||
#define BUFFER_SIZE 64
|
||||
static char client_id[BUFFER_SIZE];
|
||||
static char pub_topic[BUFFER_SIZE];
|
||||
static char sub_topic[BUFFER_SIZE];
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* The main MQTT buffers.
|
||||
* We will need to increase if we start publishing more data.
|
||||
*/
|
||||
#define APP_BUFFER_SIZE 512
|
||||
static struct mqtt_connection conn;
|
||||
static char app_buffer[APP_BUFFER_SIZE];
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define QUICKSTART "quickstart"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct mqtt_message *msg_ptr = 0;
|
||||
static struct etimer publish_periodic_timer;
|
||||
static struct ctimer ct;
|
||||
static char *buf_ptr;
|
||||
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;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const static cc26xx_web_demo_sensor_reading_t *reading;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
mqtt_client_config_t *conf;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(mqtt_client_process, "CC26XX MQTT Client");
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
publish_led_off(void *d)
|
||||
{
|
||||
leds_off(CC26XX_WEB_DEMO_STATUS_LED);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
new_net_config(void)
|
||||
{
|
||||
/*
|
||||
* We got a new configuration over the net.
|
||||
*
|
||||
* Disconnect from the current broker and stop the periodic timer.
|
||||
*
|
||||
* When the source of the new configuration is done, we will get notified
|
||||
* via an event.
|
||||
*/
|
||||
if(state == MQTT_CLIENT_STATE_NEWCONFIG) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = MQTT_CLIENT_STATE_NEWCONFIG;
|
||||
|
||||
etimer_stop(&publish_periodic_timer);
|
||||
mqtt_disconnect(&conn);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
org_id_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
if(key_len != strlen("org_id") ||
|
||||
strncasecmp(key, "org_id", strlen("org_id")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(val_len > MQTT_CLIENT_CONFIG_ORG_ID_LEN) {
|
||||
/* Ours but bad value */
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
} else {
|
||||
memset(conf->org_id, 0, MQTT_CLIENT_CONFIG_ORG_ID_LEN);
|
||||
memcpy(conf->org_id, val, val_len);
|
||||
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
type_id_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
if(key_len != strlen("type_id") ||
|
||||
strncasecmp(key, "type_id", strlen("type_id")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(val_len > MQTT_CLIENT_CONFIG_TYPE_ID_LEN) {
|
||||
/* Ours but bad value */
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
} else {
|
||||
memset(conf->type_id, 0, MQTT_CLIENT_CONFIG_TYPE_ID_LEN);
|
||||
memcpy(conf->type_id, val, val_len);
|
||||
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
event_type_id_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
if(key_len != strlen("event_type_id") ||
|
||||
strncasecmp(key, "event_type_id", strlen("event_type_id")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(val_len > MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN) {
|
||||
/* Ours but bad value */
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
} else {
|
||||
memset(conf->event_type_id, 0, MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN);
|
||||
memcpy(conf->event_type_id, val, val_len);
|
||||
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
cmd_type_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
if(key_len != strlen("cmd_type") ||
|
||||
strncasecmp(key, "cmd_type", strlen("cmd_type")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(val_len > MQTT_CLIENT_CONFIG_CMD_TYPE_LEN) {
|
||||
/* Ours but bad value */
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
} else {
|
||||
memset(conf->cmd_type, 0, MQTT_CLIENT_CONFIG_CMD_TYPE_LEN);
|
||||
memcpy(conf->cmd_type, val, val_len);
|
||||
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
auth_token_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
if(key_len != strlen("auth_token") ||
|
||||
strncasecmp(key, "auth_token", strlen("auth_token")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(val_len > MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN) {
|
||||
/* Ours but bad value */
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
} else {
|
||||
memset(conf->auth_token, 0, MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN);
|
||||
memcpy(conf->auth_token, val, val_len);
|
||||
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
interval_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if(key_len != strlen("interval") ||
|
||||
strncasecmp(key, "interval", strlen("interval")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
rv = atoi(val);
|
||||
|
||||
if(rv < MQTT_CLIENT_PUBLISH_INTERVAL_MIN ||
|
||||
rv > MQTT_CLIENT_PUBLISH_INTERVAL_MAX) {
|
||||
return HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
}
|
||||
|
||||
conf->pub_interval = rv * CLOCK_SECOND;
|
||||
|
||||
return HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
port_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if(key_len != strlen("broker_port") ||
|
||||
strncasecmp(key, "broker_port", strlen("broker_port")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
rv = atoi(val);
|
||||
|
||||
if(rv <= 65535 && rv > 0) {
|
||||
conf->broker_port = rv;
|
||||
} else {
|
||||
return HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
return HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
ip_addr_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
|
||||
if(key_len != strlen("broker_ip") ||
|
||||
strncasecmp(key, "broker_ip", strlen("broker_ip")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(val_len > MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN) {
|
||||
/* Ours but bad value */
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
} else {
|
||||
memset(conf->broker_ip, 0, MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN);
|
||||
memcpy(conf->broker_ip, val, val_len);
|
||||
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
reconnect_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
if(key_len != strlen("reconnect") ||
|
||||
strncasecmp(key, "reconnect", strlen("reconnect")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
new_net_config();
|
||||
|
||||
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);
|
||||
HTTPD_SIMPLE_POST_HANDLER(cmd_type, cmd_type_post_handler);
|
||||
HTTPD_SIMPLE_POST_HANDLER(auth_token, auth_token_post_handler);
|
||||
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,
|
||||
uint16_t chunk_len)
|
||||
{
|
||||
DBG("Pub Handler: topic='%s' (len=%u), chunk_len=%u\n", topic, topic_len,
|
||||
chunk_len);
|
||||
|
||||
/* If we don't like the length, ignore */
|
||||
if(topic_len != 23 || chunk_len != 1) {
|
||||
printf("Incorrect topic or chunk len. Ignored\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the format != json, ignore */
|
||||
if(strncmp(&topic[topic_len - 4], "json", 4) != 0) {
|
||||
printf("Incorrect format\n");
|
||||
}
|
||||
|
||||
if(strncmp(&topic[10], "leds", 4) == 0) {
|
||||
if(chunk[0] == '1') {
|
||||
leds_on(LEDS_RED);
|
||||
} else if(chunk[0] == '0') {
|
||||
leds_off(LEDS_RED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#if BOARD_SENSORTAG
|
||||
if(strncmp(&topic[10], "buzz", 4) == 0) {
|
||||
if(chunk[0] == '1') {
|
||||
buzzer_start(1000);
|
||||
} else if(chunk[0] == '0') {
|
||||
buzzer_stop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
mqtt_event(struct mqtt_connection *m, mqtt_event_t event, void *data)
|
||||
{
|
||||
switch(event) {
|
||||
case MQTT_EVENT_CONNECTED: {
|
||||
DBG("APP - Application has a MQTT connection\n");
|
||||
timer_set(&connection_life, CONNECTION_STABLE_TIME);
|
||||
state = MQTT_CLIENT_STATE_CONNECTED;
|
||||
break;
|
||||
}
|
||||
case MQTT_EVENT_DISCONNECTED: {
|
||||
DBG("APP - MQTT Disconnect. Reason %u\n", *((mqtt_event_t *)data));
|
||||
|
||||
/* Do nothing if the disconnect was the result of an incoming config */
|
||||
if(state != MQTT_CLIENT_STATE_NEWCONFIG) {
|
||||
state = MQTT_CLIENT_STATE_DISCONNECTED;
|
||||
process_poll(&mqtt_client_process);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MQTT_EVENT_PUBLISH: {
|
||||
msg_ptr = data;
|
||||
|
||||
/* Implement first_flag in publish message? */
|
||||
if(msg_ptr->first_chunk) {
|
||||
msg_ptr->first_chunk = 0;
|
||||
DBG("APP - Application received a publish on topic '%s'. Payload "
|
||||
"size is %i bytes. Content:\n\n",
|
||||
msg_ptr->topic, msg_ptr->payload_length);
|
||||
}
|
||||
|
||||
pub_handler(msg_ptr->topic, strlen(msg_ptr->topic), msg_ptr->payload_chunk,
|
||||
msg_ptr->payload_length);
|
||||
break;
|
||||
}
|
||||
case MQTT_EVENT_SUBACK: {
|
||||
DBG("APP - Application is subscribed to topic successfully\n");
|
||||
break;
|
||||
}
|
||||
case MQTT_EVENT_UNSUBACK: {
|
||||
DBG("APP - Application is unsubscribed to topic successfully\n");
|
||||
break;
|
||||
}
|
||||
case MQTT_EVENT_PUBACK: {
|
||||
DBG("APP - Publishing complete.\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DBG("APP - Application got a unhandled MQTT event: %i\n", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
construct_pub_topic(void)
|
||||
{
|
||||
int len = snprintf(pub_topic, BUFFER_SIZE, "iot-2/evt/%s/fmt/json",
|
||||
conf->event_type_id);
|
||||
|
||||
/* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */
|
||||
if(len < 0 || len >= BUFFER_SIZE) {
|
||||
printf("Pub Topic: %d, Buffer %d\n", len, BUFFER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
construct_sub_topic(void)
|
||||
{
|
||||
int len = snprintf(sub_topic, BUFFER_SIZE, "iot-2/cmd/%s/fmt/json",
|
||||
conf->cmd_type);
|
||||
|
||||
/* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */
|
||||
if(len < 0 || len >= BUFFER_SIZE) {
|
||||
printf("Sub Topic: %d, Buffer %d\n", len, BUFFER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
construct_client_id(void)
|
||||
{
|
||||
int len = snprintf(client_id, BUFFER_SIZE, "d:%s:%s:%02x%02x%02x%02x%02x%02x",
|
||||
conf->org_id, conf->type_id,
|
||||
linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1],
|
||||
linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[5],
|
||||
linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]);
|
||||
|
||||
/* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */
|
||||
if(len < 0 || len >= BUFFER_SIZE) {
|
||||
printf("Client ID: %d, Buffer %d\n", len, BUFFER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
update_config(void)
|
||||
{
|
||||
if(construct_client_id() == 0) {
|
||||
/* Fatal error. Client ID larger than the buffer */
|
||||
state = MQTT_CLIENT_STATE_CONFIG_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if(construct_sub_topic() == 0) {
|
||||
/* Fatal error. Topic larger than the buffer */
|
||||
state = MQTT_CLIENT_STATE_CONFIG_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if(construct_pub_topic() == 0) {
|
||||
/* Fatal error. Topic larger than the buffer */
|
||||
state = MQTT_CLIENT_STATE_CONFIG_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset the counter */
|
||||
seq_nr_value = 0;
|
||||
|
||||
state = MQTT_CLIENT_STATE_INIT;
|
||||
|
||||
/*
|
||||
* Schedule next timer event ASAP
|
||||
*
|
||||
* If we entered an error state then we won't do anything when it fires.
|
||||
*
|
||||
* Since the error at this stage is a config error, we will only exit this
|
||||
* error state if we get a new config.
|
||||
*/
|
||||
etimer_set(&publish_periodic_timer, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
init_config()
|
||||
{
|
||||
/* Populate configuration with default values */
|
||||
memset(conf, 0, sizeof(mqtt_client_config_t));
|
||||
|
||||
memcpy(conf->org_id, CC26XX_WEB_DEMO_DEFAULT_ORG_ID, 11);
|
||||
memcpy(conf->type_id, CC26XX_WEB_DEMO_DEFAULT_TYPE_ID, 7);
|
||||
memcpy(conf->event_type_id, CC26XX_WEB_DEMO_DEFAULT_EVENT_TYPE_ID, 7);
|
||||
memcpy(conf->broker_ip, broker_ip, strlen(broker_ip));
|
||||
memcpy(conf->cmd_type, CC26XX_WEB_DEMO_DEFAULT_SUBSCRIBE_CMD_TYPE, 1);
|
||||
|
||||
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;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
register_http_post_handlers(void)
|
||||
{
|
||||
httpd_simple_register_post_handler(&org_id_handler);
|
||||
httpd_simple_register_post_handler(&type_id_handler);
|
||||
httpd_simple_register_post_handler(&event_type_id_handler);
|
||||
httpd_simple_register_post_handler(&cmd_type_handler);
|
||||
httpd_simple_register_post_handler(&auth_token_handler);
|
||||
httpd_simple_register_post_handler(&interval_handler);
|
||||
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
|
||||
subscribe(void)
|
||||
{
|
||||
/* Publish MQTT topic in IBM quickstart format */
|
||||
mqtt_status_t status;
|
||||
|
||||
status = mqtt_subscribe(&conn, NULL, sub_topic, MQTT_QOS_LEVEL_0);
|
||||
|
||||
DBG("APP - Subscribing!\n");
|
||||
if(status == MQTT_STATUS_OUT_QUEUE_FULL) {
|
||||
DBG("APP - Tried to subscribe but command queue was full!\n");
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
publish(void)
|
||||
{
|
||||
/* Publish MQTT topic in IBM quickstart format */
|
||||
int len;
|
||||
int remaining = APP_BUFFER_SIZE;
|
||||
|
||||
seq_nr_value++;
|
||||
|
||||
buf_ptr = app_buffer;
|
||||
|
||||
len = snprintf(buf_ptr, remaining,
|
||||
"{"
|
||||
"\"d\":{"
|
||||
"\"myName\":\"%s\","
|
||||
"\"Seq #\":%d,"
|
||||
"\"Uptime (sec)\":%lu",
|
||||
BOARD_STRING, seq_nr_value, clock_seconds());
|
||||
|
||||
if(len < 0 || len >= remaining) {
|
||||
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
|
||||
return;
|
||||
}
|
||||
|
||||
remaining -= len;
|
||||
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());
|
||||
|
||||
len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d",
|
||||
def_rt_str, def_rt_rssi);
|
||||
|
||||
if(len < 0 || len >= remaining) {
|
||||
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
|
||||
return;
|
||||
}
|
||||
remaining -= len;
|
||||
buf_ptr += len;
|
||||
|
||||
memcpy(&def_route, uip_ds6_defrt_choose(), sizeof(uip_ip6addr_t));
|
||||
|
||||
for(reading = cc26xx_web_demo_sensor_first();
|
||||
reading != NULL; reading = reading->next) {
|
||||
if(reading->publish && reading->raw != CC26XX_SENSOR_READING_ERROR) {
|
||||
len = snprintf(buf_ptr, remaining,
|
||||
",\"%s (%s)\":%s", reading->descr, reading->units,
|
||||
reading->converted);
|
||||
|
||||
if(len < 0 || len >= remaining) {
|
||||
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
|
||||
return;
|
||||
}
|
||||
remaining -= len;
|
||||
buf_ptr += len;
|
||||
}
|
||||
}
|
||||
|
||||
len = snprintf(buf_ptr, remaining, "}}");
|
||||
|
||||
if(len < 0 || len >= remaining) {
|
||||
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
|
||||
return;
|
||||
}
|
||||
|
||||
mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer,
|
||||
strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF);
|
||||
|
||||
DBG("APP - Publish!\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
connect_to_broker(void)
|
||||
{
|
||||
/* Connect to MQTT server */
|
||||
mqtt_connect(&conn, conf->broker_ip, conf->broker_port,
|
||||
conf->pub_interval * 3);
|
||||
|
||||
state = MQTT_CLIENT_STATE_CONNECTING;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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) {
|
||||
case MQTT_CLIENT_STATE_INIT:
|
||||
/* If we have just been configured register MQTT connection */
|
||||
mqtt_register(&conn, &mqtt_client_process, client_id, mqtt_event,
|
||||
MQTT_CLIENT_MAX_SEGMENT_SIZE);
|
||||
|
||||
/*
|
||||
* If we are not using the quickstart service (thus we are an IBM
|
||||
* registered device), we need to provide user name and password
|
||||
*/
|
||||
if(strncasecmp(conf->org_id, QUICKSTART, strlen(conf->org_id)) != 0) {
|
||||
if(strlen(conf->auth_token) == 0) {
|
||||
printf("User name set, but empty auth token\n");
|
||||
state = MQTT_CLIENT_STATE_ERROR;
|
||||
break;
|
||||
} else {
|
||||
mqtt_set_username_password(&conn, "use-token-auth",
|
||||
conf->auth_token);
|
||||
}
|
||||
}
|
||||
|
||||
/* _register() will set auto_reconnect. We don't want that. */
|
||||
conn.auto_reconnect = 0;
|
||||
connect_attempt = 1;
|
||||
|
||||
/*
|
||||
* Wipe out the default route so we'll republish it every time we switch to
|
||||
* a new broker
|
||||
*/
|
||||
memset(&def_route, 0, sizeof(def_route));
|
||||
|
||||
state = MQTT_CLIENT_STATE_REGISTERED;
|
||||
DBG("Init\n");
|
||||
/* Continue */
|
||||
case MQTT_CLIENT_STATE_REGISTERED:
|
||||
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);
|
||||
return;
|
||||
break;
|
||||
case MQTT_CLIENT_STATE_CONNECTING:
|
||||
leds_on(CC26XX_WEB_DEMO_STATUS_LED);
|
||||
ctimer_set(&ct, CONNECTING_LED_DURATION, publish_led_off, NULL);
|
||||
/* Not connected yet. Wait */
|
||||
DBG("Connecting (%u)\n", connect_attempt);
|
||||
break;
|
||||
case MQTT_CLIENT_STATE_CONNECTED:
|
||||
/* Don't subscribe unless we are a registered device */
|
||||
if(strncasecmp(conf->org_id, QUICKSTART, strlen(conf->org_id)) == 0) {
|
||||
DBG("Using 'quickstart': Skipping subscribe\n");
|
||||
state = MQTT_CLIENT_STATE_PUBLISHING;
|
||||
}
|
||||
/* Continue */
|
||||
case MQTT_CLIENT_STATE_PUBLISHING:
|
||||
/* If the timer expired, the connection is stable. */
|
||||
if(timer_expired(&connection_life)) {
|
||||
/*
|
||||
* Intentionally using 0 here instead of 1: We want RECONNECT_ATTEMPTS
|
||||
* attempts if we disconnect after a successful connect
|
||||
*/
|
||||
connect_attempt = 0;
|
||||
}
|
||||
|
||||
if(mqtt_ready(&conn) && conn.out_buffer_sent) {
|
||||
/* Connected. Publish */
|
||||
if(state == MQTT_CLIENT_STATE_CONNECTED) {
|
||||
subscribe();
|
||||
state = MQTT_CLIENT_STATE_PUBLISHING;
|
||||
} else {
|
||||
leds_on(CC26XX_WEB_DEMO_STATUS_LED);
|
||||
ctimer_set(&ct, PUBLISH_LED_ON_DURATION, publish_led_off, NULL);
|
||||
publish();
|
||||
}
|
||||
etimer_set(&publish_periodic_timer, conf->pub_interval);
|
||||
|
||||
DBG("Publishing\n");
|
||||
/* Return here so we don't end up rescheduling the timer */
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Our publish timer fired, but some MQTT packet is already in flight
|
||||
* (either not sent at all, or sent but not fully ACKd).
|
||||
*
|
||||
* This can mean that we have lost connectivity to our broker or that
|
||||
* simply there is some network delay. In both cases, we refuse to
|
||||
* trigger a new message and we wait for TCP to either ACK the entire
|
||||
* packet after retries, or to timeout and notify us.
|
||||
*/
|
||||
DBG("Publishing... (MQTT state=%d, q=%u)\n", conn.state,
|
||||
conn.out_queue_full);
|
||||
}
|
||||
break;
|
||||
case MQTT_CLIENT_STATE_DISCONNECTED:
|
||||
DBG("Disconnected\n");
|
||||
if(connect_attempt < RECONNECT_ATTEMPTS ||
|
||||
RECONNECT_ATTEMPTS == RETRY_FOREVER) {
|
||||
/* Disconnect and backoff */
|
||||
clock_time_t interval;
|
||||
mqtt_disconnect(&conn);
|
||||
connect_attempt++;
|
||||
|
||||
interval = connect_attempt < 3 ? RECONNECT_INTERVAL << connect_attempt :
|
||||
RECONNECT_INTERVAL << 3;
|
||||
|
||||
DBG("Disconnected. Attempt %u in %lu ticks\n", connect_attempt, interval);
|
||||
|
||||
etimer_set(&publish_periodic_timer, interval);
|
||||
|
||||
state = MQTT_CLIENT_STATE_REGISTERED;
|
||||
return;
|
||||
} else {
|
||||
/* Max reconnect attempts reached. Enter error state */
|
||||
state = MQTT_CLIENT_STATE_ERROR;
|
||||
DBG("Aborting connection after %u attempts\n", connect_attempt - 1);
|
||||
}
|
||||
break;
|
||||
case MQTT_CLIENT_STATE_NEWCONFIG:
|
||||
/* Only update config after we have disconnected */
|
||||
if(conn.state == MQTT_CONN_STATE_NOT_CONNECTED) {
|
||||
update_config();
|
||||
DBG("New config\n");
|
||||
|
||||
/* update_config() scheduled next pass. Return */
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MQTT_CLIENT_STATE_CONFIG_ERROR:
|
||||
/* Idle away. The only way out is a new config */
|
||||
printf("Bad configuration.\n");
|
||||
return;
|
||||
case MQTT_CLIENT_STATE_ERROR:
|
||||
default:
|
||||
leds_on(CC26XX_WEB_DEMO_STATUS_LED);
|
||||
/*
|
||||
* 'default' should never happen.
|
||||
*
|
||||
* If we enter here it's because of some error. Stop timers. The only thing
|
||||
* that can bring us out is a new config event
|
||||
*/
|
||||
printf("Default case: State=0x%02x\n", state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we didn't return so far, reschedule ourselves */
|
||||
etimer_set(&publish_periodic_timer, STATE_MACHINE_PERIODIC);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(mqtt_client_process, ev, data)
|
||||
{
|
||||
|
||||
PROCESS_BEGIN();
|
||||
|
||||
printf("CC26XX MQTT Client Process\n");
|
||||
|
||||
conf = &cc26xx_web_demo_config.mqtt_config;
|
||||
if(init_config() != 1) {
|
||||
PROCESS_EXIT();
|
||||
}
|
||||
|
||||
register_http_post_handlers();
|
||||
|
||||
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) {
|
||||
|
||||
PROCESS_YIELD();
|
||||
|
||||
if(ev == sensors_event && data == CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER) {
|
||||
if(state == MQTT_CLIENT_STATE_ERROR) {
|
||||
connect_attempt = 1;
|
||||
state = MQTT_CLIENT_STATE_REGISTERED;
|
||||
}
|
||||
}
|
||||
|
||||
if(ev == httpd_simple_event_new_config) {
|
||||
/*
|
||||
* Schedule next pass in a while. When HTTPD sends us this event, it is
|
||||
* also in the process of sending the config page. Wait a little before
|
||||
* reconnecting, so as to not cause congestion.
|
||||
*/
|
||||
etimer_set(&publish_periodic_timer, NEW_CONFIG_WAIT_INTERVAL);
|
||||
}
|
||||
|
||||
if((ev == PROCESS_EVENT_TIMER && data == &publish_periodic_timer) ||
|
||||
ev == PROCESS_EVENT_POLL ||
|
||||
ev == cc26xx_web_demo_publish_event ||
|
||||
(ev == sensors_event && data == CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
74
examples/cc26xx/cc26xx-web-demo/mqtt-client.h
Normal file
74
examples/cc26xx/cc26xx-web-demo/mqtt-client.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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
|
||||
* Header file for the CC26xx web demo MQTT client functionality
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef MQTT_CLIENT_H_
|
||||
#define MQTT_CLIENT_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define MQTT_CLIENT_CONFIG_ORG_ID_LEN 32
|
||||
#define MQTT_CLIENT_CONFIG_TYPE_ID_LEN 32
|
||||
#define MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN 32
|
||||
#define MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN 32
|
||||
#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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_NAME(mqtt_client_process);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Data structure declaration for the MQTT client configuration
|
||||
*/
|
||||
typedef struct mqtt_client_config {
|
||||
char org_id[MQTT_CLIENT_CONFIG_ORG_ID_LEN];
|
||||
char type_id[MQTT_CLIENT_CONFIG_TYPE_ID_LEN];
|
||||
char auth_token[MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN];
|
||||
char event_type_id[MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN];
|
||||
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;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* MQTT_CLIENT_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
344
examples/cc26xx/cc26xx-web-demo/net-uart.c
Normal file
344
examples/cc26xx/cc26xx-web-demo/net-uart.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* 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
|
||||
* A process which receives data over UART and transmits them over UDP
|
||||
* to a pre-defined IPv6 address and port. It also listens on the same UDP
|
||||
* port for messages, which it prints out over UART.
|
||||
*
|
||||
* For this example to work, you will have to modify the destination IPv6
|
||||
* address by adjusting the set_dest_addr() macro below.
|
||||
*
|
||||
* To listen on your linux or OS X box:
|
||||
* nc -6ulkw 1 REMOTE_PORT
|
||||
*
|
||||
* (REMOTE_PORT should be the actual value of the define below, e.g. 7777)
|
||||
*
|
||||
* Once netcat is up and listening, type something to the CC26xx's terminal
|
||||
* Bear in mind that the datagram will only be sent after a 0x0a (LF) char
|
||||
* has been received. Therefore, if you are on Win, do NOT use PuTTY for
|
||||
* this purpose, since it does not send 0x0a as part of the line end. On
|
||||
* Win XP use hyperterm. On Win 7 use some other software (e.g. Tera Term,
|
||||
* which can be configured to send CRLF on enter keystrokes).
|
||||
*
|
||||
* To send data in the other direction from your linux or OS X box:
|
||||
*
|
||||
* nc -6u \<node IPv6 address\> REMOTE_PORT
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki-conf.h"
|
||||
#include "sys/process.h"
|
||||
#include "dev/serial-line.h"
|
||||
#include "net/ip/uip.h"
|
||||
#include "net/ip/uip-udp-packet.h"
|
||||
#include "net/ip/uiplib.h"
|
||||
#include "lpm.h"
|
||||
#include "net-uart.h"
|
||||
#include "httpd-simple.h"
|
||||
|
||||
#include "ti-lib.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/ip/uip-debug.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define REMOTE_PORT 7777
|
||||
#define MAX_MSG_SIZE 100
|
||||
|
||||
#define set_dest_addr() uip_ip6addr(&remote_addr, \
|
||||
0xBBBB, 0x0000, 0x0000, 0x0000, \
|
||||
0x3E07, 0x54FF, 0xFE74, 0x4885);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define ADDRESS_CONVERSION_OK 1
|
||||
#define ADDRESS_CONVERSION_ERROR 0
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef MIN
|
||||
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct uip_udp_conn *udp_conn = NULL;
|
||||
|
||||
static uint8_t buffer[MAX_MSG_SIZE];
|
||||
static uint8_t msg_len;
|
||||
static uip_ip6addr_t remote_addr;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define IPV6_ADDR_STR_LEN 64
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(net_uart_process, "Net UART Process");
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* \brief Attempts to convert a string representation of an IPv6 address to a
|
||||
* numeric one.
|
||||
* \param buf The buffer with the string to be converted.
|
||||
* \return ADDRESS_CONVERSION_OK or ADDRESS_CONVERSION_ERROR
|
||||
*
|
||||
* ToDo: Add support for NAT64 conversion in case the incoming address is a v4
|
||||
* This is now supported in the current master, so when we pull it in this will
|
||||
* be very straightforward.
|
||||
*/
|
||||
static int
|
||||
set_new_ip_address(char *buf)
|
||||
{
|
||||
/*
|
||||
* uiplib_ip6addrconv will immediately start writing into the supplied buffer
|
||||
* even if it subsequently fails. Thus, pass an intermediate buffer
|
||||
*/
|
||||
uip_ip6addr_t tmp_addr;
|
||||
|
||||
int rv = uiplib_ip6addrconv(buf, &tmp_addr);
|
||||
|
||||
if(rv == ADDRESS_CONVERSION_OK) {
|
||||
/* Conversion OK, copy to our main buffer */
|
||||
memcpy(&remote_addr, &tmp_addr, sizeof(remote_addr));
|
||||
|
||||
PRINTF("Updated remote address ");
|
||||
PRINT6ADDR(&remote_addr);
|
||||
PRINTF("\n");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
net_input(void)
|
||||
{
|
||||
if(uip_newdata()) {
|
||||
memset(buffer, 0, MAX_MSG_SIZE);
|
||||
msg_len = MIN(uip_datalen(), MAX_MSG_SIZE - 1);
|
||||
|
||||
/* Copy data */
|
||||
memcpy(buffer, uip_appdata, msg_len);
|
||||
printf("%s", (char *)buffer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* In order to maintain UART input operation:
|
||||
* - Keep the uart clocked in sleep and deep sleep
|
||||
* - Keep the serial PD on in deep sleep
|
||||
*/
|
||||
static lpm_power_domain_lock_t lock;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
release_uart(void)
|
||||
{
|
||||
/* Release serial PD lock */
|
||||
lpm_pd_lock_release(&lock);
|
||||
|
||||
/* Let the UART turn off during Sleep and Deep Sleep */
|
||||
ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0);
|
||||
ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0);
|
||||
ti_lib_prcm_load_set();
|
||||
while(!ti_lib_prcm_load_get());
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
keep_uart_on(void)
|
||||
{
|
||||
/* Keep the serial PD on */
|
||||
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL);
|
||||
|
||||
/* Keep the UART clock on during Sleep and Deep Sleep */
|
||||
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0);
|
||||
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0);
|
||||
ti_lib_prcm_load_set();
|
||||
while(!ti_lib_prcm_load_get());
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
remote_port_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if(key_len != strlen("net_uart_port") ||
|
||||
strncasecmp(key, "net_uart_port", strlen("net_uart_port")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
rv = atoi(val);
|
||||
|
||||
if(rv <= 65535 && rv > 0) {
|
||||
cc26xx_web_demo_config.net_uart.remote_port = (uint16_t)rv;
|
||||
} else {
|
||||
return HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
}
|
||||
|
||||
return HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
remote_ipv6_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
|
||||
if(key_len != strlen("net_uart_ip") ||
|
||||
strncasecmp(key, "net_uart_ip", strlen("net_uart_ip")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
if(val_len > IPV6_ADDR_STR_LEN) {
|
||||
/* Ours but bad value */
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
} else {
|
||||
if(set_new_ip_address(val)) {
|
||||
memset(cc26xx_web_demo_config.net_uart.remote_address, 0,
|
||||
NET_UART_IP_ADDR_STRLEN);
|
||||
memcpy(cc26xx_web_demo_config.net_uart.remote_address, val, val_len);
|
||||
rv = HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
on_off_post_handler(char *key, int key_len, char *val, int val_len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if(key_len != strlen("net_uart_on") ||
|
||||
strncasecmp(key, "net_uart_on", strlen("net_uart_on")) != 0) {
|
||||
/* Not ours */
|
||||
return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN;
|
||||
}
|
||||
|
||||
rv = atoi(val);
|
||||
|
||||
/* Be pedantic: only accept 0 and 1, not just any non-zero value */
|
||||
if(rv == 0) {
|
||||
cc26xx_web_demo_config.net_uart.enable = 0;
|
||||
release_uart();
|
||||
} else if(rv == 1) {
|
||||
cc26xx_web_demo_config.net_uart.enable = 1;
|
||||
keep_uart_on();
|
||||
} else {
|
||||
return HTTPD_SIMPLE_POST_HANDLER_ERROR;
|
||||
}
|
||||
|
||||
return HTTPD_SIMPLE_POST_HANDLER_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
HTTPD_SIMPLE_POST_HANDLER(remote_port, remote_port_post_handler);
|
||||
HTTPD_SIMPLE_POST_HANDLER(remote_ipv6, remote_ipv6_post_handler);
|
||||
HTTPD_SIMPLE_POST_HANDLER(on_off, on_off_post_handler);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
set_config_defaults(void)
|
||||
{
|
||||
/* Set a hard-coded destination address to start with */
|
||||
set_dest_addr();
|
||||
|
||||
/* Set config defaults */
|
||||
cc26xx_web_demo_ipaddr_sprintf(cc26xx_web_demo_config.net_uart.remote_address,
|
||||
NET_UART_IP_ADDR_STRLEN, &remote_addr);
|
||||
cc26xx_web_demo_config.net_uart.remote_port = REMOTE_PORT;
|
||||
cc26xx_web_demo_config.net_uart.enable = 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(net_uart_process, ev, data)
|
||||
{
|
||||
PROCESS_BEGIN();
|
||||
|
||||
printf("CC26XX Net UART Process\n");
|
||||
|
||||
set_config_defaults();
|
||||
|
||||
udp_conn = udp_new(NULL, UIP_HTONS(0), NULL);
|
||||
udp_bind(udp_conn, UIP_HTONS(REMOTE_PORT));
|
||||
|
||||
if(udp_conn == NULL) {
|
||||
printf("No UDP connection available, exiting the process!\n");
|
||||
PROCESS_EXIT();
|
||||
}
|
||||
|
||||
httpd_simple_register_post_handler(&remote_port_handler);
|
||||
httpd_simple_register_post_handler(&remote_ipv6_handler);
|
||||
httpd_simple_register_post_handler(&on_off_handler);
|
||||
|
||||
while(1) {
|
||||
|
||||
PROCESS_YIELD();
|
||||
|
||||
if(ev == serial_line_event_message) {
|
||||
/*
|
||||
* If the message contains a new IP address, save it and go back to
|
||||
* waiting.
|
||||
*/
|
||||
if(set_new_ip_address((char *)data) == ADDRESS_CONVERSION_ERROR) {
|
||||
/* Not an IP address in the message. Send to current destination */
|
||||
memset(buffer, 0, MAX_MSG_SIZE);
|
||||
|
||||
/* We need to add a line feed, thus never fill the entire buffer */
|
||||
msg_len = MIN(strlen(data), MAX_MSG_SIZE - 1);
|
||||
memcpy(buffer, data, msg_len);
|
||||
|
||||
/* Add a line feed */
|
||||
buffer[msg_len] = 0x0A;
|
||||
msg_len++;
|
||||
|
||||
uip_udp_packet_sendto(
|
||||
udp_conn, buffer, msg_len, &remote_addr,
|
||||
UIP_HTONS(cc26xx_web_demo_config.net_uart.remote_port));
|
||||
}
|
||||
} else if(ev == tcpip_event) {
|
||||
net_input();
|
||||
} else if(ev == cc26xx_web_demo_config_loaded_event) {
|
||||
/*
|
||||
* New config. Check if it's possible to update the remote address.
|
||||
* The port will have been updated already
|
||||
*/
|
||||
set_new_ip_address(cc26xx_web_demo_config.net_uart.remote_address);
|
||||
|
||||
if(cc26xx_web_demo_config.net_uart.enable == 1) {
|
||||
keep_uart_on();
|
||||
}
|
||||
} else if(ev == cc26xx_web_demo_load_config_defaults) {
|
||||
set_config_defaults();
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
48
examples/cc26xx/cc26xx-web-demo/net-uart.h
Normal file
48
examples/cc26xx/cc26xx-web-demo/net-uart.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef NET_UART_H_
|
||||
#define NET_UART_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "net/ip/uip.h"
|
||||
|
||||
#include <stdint.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define NET_UART_IP_ADDR_STRLEN 64
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_NAME(net_uart_process);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef struct net_uart_config_s {
|
||||
char remote_address[NET_UART_IP_ADDR_STRLEN];
|
||||
uint16_t remote_port;
|
||||
uint8_t enable;
|
||||
} net_uart_config_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* NET_UART_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
53
examples/cc26xx/cc26xx-web-demo/project-conf.h
Normal file
53
examples/cc26xx/cc26xx-web-demo/project-conf.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef PROJECT_CONF_H_
|
||||
#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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Enable/Disable Components of this Demo */
|
||||
#define CC26XX_WEB_DEMO_CONF_MQTT_CLIENT 1
|
||||
#define CC26XX_WEB_DEMO_CONF_6LBR_CLIENT 1
|
||||
#define CC26XX_WEB_DEMO_CONF_COAP_SERVER 1
|
||||
#define CC26XX_WEB_DEMO_CONF_NET_UART 1
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Shrink the size of the uIP buffer, routing table and ND cache */
|
||||
#define UIP_CONF_BUFFER_SIZE 900
|
||||
#define NBR_TABLE_CONF_MAX_NEIGHBORS 8
|
||||
#define UIP_CONF_MAX_ROUTES 8
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* PROJECT_CONF_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
113
examples/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c
Normal file
113
examples/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 to start/stop/configure BLE advertisements
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "rest-engine.h"
|
||||
#include "er-coap.h"
|
||||
#include "dev/cc26xx-rf.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define BLE_NAME_BUF_LEN 32
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const char *forbidden_payload = "Name to advertise unspecified.\n"
|
||||
"Use name=<name> in the request";
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_ble_post_put_handler(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
size_t len = 0;
|
||||
const char *text = NULL;
|
||||
char name[BLE_NAME_BUF_LEN];
|
||||
int success = 0;
|
||||
int rv;
|
||||
|
||||
memset(name, 0, BLE_NAME_BUF_LEN);
|
||||
|
||||
len = REST.get_post_variable(request, "name", &text);
|
||||
|
||||
if(len > 0 && len < BLE_NAME_BUF_LEN) {
|
||||
memcpy(name, text, len);
|
||||
cc26xx_rf_ble_beacond_config(0, name);
|
||||
success = 1;
|
||||
}
|
||||
|
||||
len = REST.get_post_variable(request, "interval", &text);
|
||||
|
||||
rv = atoi(text);
|
||||
|
||||
if(rv > 0) {
|
||||
cc26xx_rf_ble_beacond_config((clock_time_t)(rv * CLOCK_SECOND), NULL);
|
||||
success = 1;
|
||||
}
|
||||
|
||||
len = REST.get_post_variable(request, "mode", &text);
|
||||
|
||||
if(len) {
|
||||
if(strncmp(text, "on", len) == 0) {
|
||||
if(cc26xx_rf_ble_beacond_start()) {
|
||||
success = 1;
|
||||
} else {
|
||||
REST.set_response_status(response, REST.status.FORBIDDEN);
|
||||
REST.set_response_payload(response, forbidden_payload,
|
||||
strlen(forbidden_payload));
|
||||
return;
|
||||
}
|
||||
} else if(strncmp(text, "off", len) == 0) {
|
||||
cc26xx_rf_ble_beacond_stop();
|
||||
success = 1;
|
||||
} else {
|
||||
success = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
REST.set_response_status(response, REST.status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_ble_advd,
|
||||
"title=\"BLE advd config: POST/PUT name=<name>&mode=on|off"
|
||||
"&interval=<secs>\";rt=\"Control\"",
|
||||
NULL,
|
||||
res_ble_post_put_handler,
|
||||
res_ble_post_put_handler,
|
||||
NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
179
examples/cc26xx/cc26xx-web-demo/resources/res-device.c
Normal file
179
examples/cc26xx/cc26xx-web-demo/resources/res-device.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* 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
|
||||
* CoAP resource handler for CC26XX software and hardware version
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#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 <string.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_hw(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, "%s on CC%u", BOARD_STRING,
|
||||
CC26XX_MODEL_CPU_VARIANT);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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_sw(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, "%s", CONTIKI_VERSION_STRING);
|
||||
|
||||
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, "{\"SW Ver\":\"%s\"}",
|
||||
CONTIKI_VERSION_STRING);
|
||||
|
||||
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,
|
||||
"<sw-ver val=\"%s\"/>", CONTIKI_VERSION_STRING);
|
||||
|
||||
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_uptime(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, "%lu", clock_seconds());
|
||||
|
||||
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, "{\"uptime\":%lu}",
|
||||
clock_seconds());
|
||||
|
||||
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,
|
||||
"<uptime val=\"%lu\" unit=\"sec\"/>", clock_seconds());
|
||||
|
||||
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_post_handler_cfg_reset(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
cc26xx_web_demo_restore_defaults();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_device_sw,
|
||||
"title=\"Software version\";rt=\"text\"",
|
||||
res_get_handler_sw,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_device_uptime,
|
||||
"title=\"Uptime\";rt=\"seconds\"",
|
||||
res_get_handler_uptime,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_device_hw,
|
||||
"title=\"Hardware version\";rt=\"text\"",
|
||||
res_get_handler_hw,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_device_cfg_reset,
|
||||
"title=\"Reset Device Config: POST\";rt=\"Control\"",
|
||||
NULL, res_post_handler_cfg_reset, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
110
examples/cc26xx/cc26xx-web-demo/resources/res-leds.c
Normal file
110
examples/cc26xx/cc26xx-web-demo/resources/res-leds.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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 the CC26xx LEDs. Slightly modified copy of
|
||||
* the one found in Contiki's original CoAP example.
|
||||
* \author
|
||||
* Matthias Kovatsch <kovatsch@inf.ethz.ch> (original)
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "rest-engine.h"
|
||||
#include "dev/leds.h"
|
||||
|
||||
#include <string.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_post_put_handler(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
size_t len = 0;
|
||||
const char *color = NULL;
|
||||
const char *mode = NULL;
|
||||
uint8_t led = 0;
|
||||
int success = 1;
|
||||
|
||||
if((len = REST.get_query_variable(request, "color", &color))) {
|
||||
if(strncmp(color, "r", len) == 0) {
|
||||
led = LEDS_RED;
|
||||
} else if(strncmp(color, "g", len) == 0) {
|
||||
led = LEDS_GREEN;
|
||||
#if BOARD_SMARTRF06EB
|
||||
} else if(strncmp(color, "y", len) == 0) {
|
||||
led = LEDS_YELLOW;
|
||||
} else if(strncmp(color, "o", len) == 0) {
|
||||
led = LEDS_ORANGE;
|
||||
#endif
|
||||
} else {
|
||||
success = 0;
|
||||
}
|
||||
} else {
|
||||
success = 0;
|
||||
}
|
||||
|
||||
if(success && (len = REST.get_post_variable(request, "mode", &mode))) {
|
||||
if(strncmp(mode, "on", len) == 0) {
|
||||
leds_on(led);
|
||||
} else if(strncmp(mode, "off", len) == 0) {
|
||||
leds_off(led);
|
||||
} else {
|
||||
success = 0;
|
||||
}
|
||||
} else {
|
||||
success = 0;
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
REST.set_response_status(response, REST.status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* A simple actuator example, depending on the color query parameter and post
|
||||
* variable mode, corresponding led is activated or deactivated
|
||||
*/
|
||||
#if BOARD_SENSORTAG
|
||||
#define RESOURCE_PARAMS "r|g"
|
||||
#elif BOARD_SMARTRF06EB
|
||||
#define RESOURCE_PARAMS "r|g|y|o"
|
||||
#endif
|
||||
|
||||
RESOURCE(res_leds,
|
||||
"title=\"LEDs: ?color=" RESOURCE_PARAMS ", POST/PUT mode=on|off\";rt=\"Control\"",
|
||||
NULL,
|
||||
res_post_put_handler,
|
||||
res_post_put_handler,
|
||||
NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
269
examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c
Normal file
269
examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* 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
|
||||
* CoAP resource handler for the Sensortag-CC26xx sensors
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "rest-engine.h"
|
||||
#include "er-coap.h"
|
||||
#include "cc26xx-web-demo.h"
|
||||
#include "coap-server.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Generic resource handler for any sensor in this example. Ultimately gets
|
||||
* called by all handlers and populates the CoAP response
|
||||
*/
|
||||
static void
|
||||
res_get_handler_all(int sens_type, void *request, void *response,
|
||||
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
unsigned int accept = -1;
|
||||
const cc26xx_web_demo_sensor_reading_t *reading;
|
||||
|
||||
reading = cc26xx_web_demo_sensor_lookup(sens_type);
|
||||
|
||||
if(reading == NULL) {
|
||||
REST.set_response_status(response, REST.status.NOT_FOUND);
|
||||
REST.set_response_payload(response, coap_server_not_found_msg,
|
||||
strlen(coap_server_not_found_msg));
|
||||
return;
|
||||
}
|
||||
|
||||
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", reading->converted);
|
||||
|
||||
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, "{\"%s\":%s}",
|
||||
reading->descr, reading->converted);
|
||||
|
||||
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,
|
||||
"<%s val=\"%s\" unit=\"%s\"/>", reading->xml_element,
|
||||
reading->converted, reading->units);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* BatMon resources and handler: Temperature, Voltage */
|
||||
static void
|
||||
res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_batmon_volt(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_batmon_temp, "title=\"Battery Temp\";rt=\"C\"",
|
||||
res_get_handler_batmon_temp, NULL, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_batmon_volt, "title=\"Battery Voltage\";rt=\"mV\"",
|
||||
res_get_handler_batmon_volt, NULL, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if BOARD_SENSORTAG
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* MPU resources and handler: Accelerometer and Gyro */
|
||||
static void
|
||||
res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_mpu_gyro_z(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_mpu_acc_x, "title=\"Acc X\";rt=\"G\"", res_get_handler_mpu_acc_x,
|
||||
NULL, NULL, NULL);
|
||||
RESOURCE(res_mpu_acc_y, "title=\"Acc Y\";rt=\"G\"", res_get_handler_mpu_acc_y,
|
||||
NULL, NULL, NULL);
|
||||
RESOURCE(res_mpu_acc_z, "title=\"Acc Z\";rt=\"G\"", res_get_handler_mpu_acc_z,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
RESOURCE(res_mpu_gyro_x, "title=\"Gyro X\";rt=\"deg/sec\"",
|
||||
res_get_handler_mpu_gyro_x, NULL, NULL, NULL);
|
||||
RESOURCE(res_mpu_gyro_y, "title=\"Gyro Y\";rt=\"deg/sec\"",
|
||||
res_get_handler_mpu_gyro_y, NULL, NULL, NULL);
|
||||
RESOURCE(res_mpu_gyro_z, "title=\"Gyro Z\";rt=\"deg/sec\"",
|
||||
res_get_handler_mpu_gyro_z, NULL, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* TMP sensor resources and handlers: Object, Ambient */
|
||||
static void
|
||||
res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_amb_temp(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_tmp007_obj, "title=\"Temperature (Object)\";rt=\"C\"",
|
||||
res_get_handler_obj_temp, NULL, NULL, NULL);
|
||||
|
||||
RESOURCE(res_tmp007_amb, "title=\"Temperature (Ambient)\";rt=\"C\"",
|
||||
res_get_handler_amb_temp, NULL, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* BMP sensor resources: Temperature, Pressure */
|
||||
static void
|
||||
res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_bmp_press(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_PRES, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_bmp280_temp, "title=\"Barometer (Temperature)\";rt=\"C\"",
|
||||
res_get_handler_bmp_temp, NULL, NULL, NULL);
|
||||
|
||||
RESOURCE(res_bmp280_press,
|
||||
"title=\"Barometer (Pressure)\";rt=\"hPa (hectopascal / millibar)\"",
|
||||
res_get_handler_bmp_press, NULL, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* SHT21 sensor resources and handler: Temperature, Pressure */
|
||||
static void
|
||||
res_get_handler_sht_temp(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_TEMP, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_get_handler_sht_humidity(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_sht21_temp, "title=\"Temperature\";rt=\"C\"",
|
||||
res_get_handler_sht_temp, NULL, NULL, NULL);
|
||||
|
||||
RESOURCE(res_sht21_hum, "title=\"Humidity\";rt=\"%RH\"",
|
||||
res_get_handler_sht_humidity, NULL, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Illuminance resources and handler */
|
||||
static void
|
||||
res_get_handler_opt(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT, request, response,
|
||||
buffer, preferred_size, offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
RESOURCE(res_opt3001_light, "title=\"Illuminance\";rt=\"Lux\"",
|
||||
res_get_handler_opt, NULL, NULL, NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* BOARD_SENSORTAG */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
114
examples/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c
Normal file
114
examples/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||
* 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \addtogroup cc26xx-web-demo
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
* CoAP resource to toggle LEDs. Slightly modified copy of the one found
|
||||
* in Contiki's original CoAP example.
|
||||
* \author
|
||||
* Matthias Kovatsch <kovatsch@inf.ethz.ch> (original)
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "rest-engine.h"
|
||||
#include "dev/leds.h"
|
||||
|
||||
#include <string.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_post_handler_red(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
leds_toggle(LEDS_RED);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_post_handler_green(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
leds_toggle(LEDS_GREEN);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Toggles the red led */
|
||||
RESOURCE(res_toggle_red,
|
||||
"title=\"Red LED\";rt=\"Control\"",
|
||||
NULL,
|
||||
res_post_handler_red,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Toggles the green led */
|
||||
RESOURCE(res_toggle_green,
|
||||
"title=\"Green LED\";rt=\"Control\"",
|
||||
NULL,
|
||||
res_post_handler_green,
|
||||
NULL,
|
||||
NULL);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* An additional 2 LEDs on the Srf */
|
||||
#if BOARD_SMARTRF06EB
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_post_handler_yellow(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
leds_toggle(LEDS_YELLOW);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
res_post_handler_orange(void *request, void *response, uint8_t *buffer,
|
||||
uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
leds_toggle(LEDS_ORANGE);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Toggles the yellow led */
|
||||
RESOURCE(res_toggle_yellow,
|
||||
"title=\"Yellow LED\";rt=\"Control\"",
|
||||
NULL,
|
||||
res_post_handler_yellow,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Toggles the orange led */
|
||||
RESOURCE(res_toggle_orange,
|
||||
"title=\"Orange LED\";rt=\"Control\"",
|
||||
NULL,
|
||||
res_post_handler_orange,
|
||||
NULL,
|
||||
NULL);
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
45
examples/cc26xx/project-conf.h
Normal file
45
examples/cc26xx/project-conf.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef PROJECT_CONF_H_
|
||||
#define PROJECT_CONF_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Disable button shutdown functionality */
|
||||
#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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* PROJECT_CONF_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
Loading…
Reference in a new issue