Added SimpleLink examples folder

This commit is contained in:
Edvard Pettersen 2018-07-25 15:04:11 +02:00
parent 6ed5d73990
commit 972502b3e2
28 changed files with 6875 additions and 0 deletions

View File

@ -0,0 +1,10 @@
CONTIKI_PROJECT = start-demo
PROJECT_SOURCEFILES = start-demo.c
PLATFORMS_ONLY = simplelink
all: $(CONTIKI_PROJECT).$(TARGET)
CONTIKI = ../../../../..
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1,14 @@
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 send out BLE advertisements, if the chip has BLE capability. The
device will periodically send out BLE beacons with the platform name as
payload. Those beacons/BLE ADV packets can be captured with any BLE-capable
device. Two such applications for iOS are the TI Multitool and the TI
Sensortag app. They can be found in the Apple App Store. If you have a
BLE-capable Mac, you can also use LightBlue for OS X.

View File

@ -0,0 +1,43 @@
/*
* 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_
/*---------------------------------------------------------------------------*/
/* Enable the ROM bootloader */
#define ROM_BOOTLOADER_ENABLE 1
/*---------------------------------------------------------------------------*/
/* Change to match your configuration */
#define IEEE802154_CONF_PANID 0xABCD
#define IEEE802154_CONF_DEFAULT_CHANNEL 25
#define RF_BLE_CONF_ENABLED 1
/*---------------------------------------------------------------------------*/
#endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,425 @@
/*
* 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 CC13xx/CC26xx platforms
*
* This example will work for the following boards:
* - srf06-cc26xx: SmartRF06EB + CC13xx/CC26xx EM
* - CC2650 and CC1350 SensorTag
* - CC1310, CC1350, CC2650 LaunchPads
*
* 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_TRIGGER_1 button will toggle CC26XX_DEMO_LEDS_BUTTON
* - CC26XX_DEMO_TRIGGER_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
* - 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/watchdog.h"
#include "dev/button-hal.h"
#include "random.h"
#include "button-sensor.h"
#include "batmon-sensor.h"
#include "board-peripherals.h"
#include "rf/ble-beacond.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_REBOOT LEDS_ALL
/*---------------------------------------------------------------------------*/
#define CC26XX_DEMO_TRIGGER_1 BUTTON_HAL_ID_KEY_LEFT
#define CC26XX_DEMO_TRIGGER_2 BUTTON_HAL_ID_KEY_RIGHT
#if BOARD_SENSORTAG
#define CC26XX_DEMO_TRIGGER_3 BUTTON_HAL_ID_REED_RELAY
#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, hdc_timer, tmp_timer, mpu_timer;
/*---------------------------------------------------------------------------*/
static void init_bmp_reading(void *not_used);
static void init_opt_reading(void *not_used);
static void init_hdc_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_hdc_reading()
{
int value;
clock_time_t next = SENSOR_READING_PERIOD +
(random_rand() % SENSOR_READING_RANDOM);
value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP);
if(value != CC26XX_SENSOR_READING_ERROR) {
printf("HDC: Temp=%d.%02d C\n", value / 100, value % 100);
} else {
printf("HDC: Temp Read Error\n");
}
value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY);
if(value != CC26XX_SENSOR_READING_ERROR) {
printf("HDC: Humidity=%d.%02d %%RH\n", value / 100, value % 100);
} else {
printf("HDC: Humidity Read Error\n");
}
ctimer_set(&hdc_timer, next, init_hdc_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");
}
/* The OPT will turn itself off, so we don't need to call its DEACTIVATE */
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_hdc_reading(void *not_used)
{
SENSORS_ACTIVATE(hdc_1000_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 C\n", value);
value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
printf("Bat: Volt=%d mV\n", (value * 125) >> 5);
#if BOARD_SMARTRF06EB
SENSORS_ACTIVATE(als_sensor);
value = als_sensor.value(0);
printf("ALS: %d raw\n", value);
SENSORS_DEACTIVATE(als_sensor);
#endif
return;
}
/*---------------------------------------------------------------------------*/
static void
init_sensors(void)
{
SENSORS_ACTIVATE(batmon_sensor);
}
/*---------------------------------------------------------------------------*/
static void
init_sensor_readings(void)
{
#if BOARD_SENSORTAG
SENSORS_ACTIVATE(hdc_1000_sensor);
SENSORS_ACTIVATE(tmp_007_sensor);
SENSORS_ACTIVATE(opt_3001_sensor);
SENSORS_ACTIVATE(bmp_280_sensor);
init_mpu_reading(NULL);
#endif
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc26xx_demo_process, ev, data)
{
PROCESS_BEGIN();
printf("CC26XX demo\n");
init_sensors();
/* Init the BLE advertisement daemon */
rf_ble_beacond_start(0, BOARD_STRING);
etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL);
get_sync_sensor_readings();
init_sensor_readings();
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 == button_hal_periodic_event) {
button_hal_button_t *button = data;
printf("%s periodic event, duration %d seconds\n",
BUTTON_HAL_GET_DESCRIPTION(button),
button->press_duration_seconds);
} else if(ev == button_hal_release_event) {
button_hal_button_t *btn = (button_hal_button_t *)data;
printf("%s release event\n", BUTTON_HAL_GET_DESCRIPTION(btn));
if(btn->unique_id== CC26XX_DEMO_TRIGGER_1) {
leds_toggle(CC26XX_DEMO_LEDS_BUTTON);
} else if(btn->unique_id == CC26XX_DEMO_TRIGGER_2) {
leds_on(CC26XX_DEMO_LEDS_REBOOT);
watchdog_reboot();
#if BOARD_SENSORTAG
} else if(btn->unique_id == CC26XX_DEMO_TRIGGER_3) {
if(buzzer_state()) {
buzzer_stop();
} else {
buzzer_start(1000);
}
}
} else if(ev == sensors_event) {
if(data == &bmp_280_sensor) {
get_bmp_reading();
} else if(data == &opt_3001_sensor) {
get_light_reading();
} else if(data == &hdc_1000_sensor) {
get_hdc_reading();
} else if(data == &tmp_007_sensor) {
get_tmp_reading();
} else if(data == &mpu_9250_sensor) {
get_mpu_reading();
#endif
}
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
* @}
*/

View File

@ -0,0 +1,10 @@
CONTIKI_PROJECT = very-sleepy-demo
PLATFORMS_ONLY = srf06-cc26xx
all: $(CONTIKI_PROJECT)
MODULES += os/net/app-layer/coap
CONTIKI = ../../../..
include $(CONTIKI)/Makefile.include

View File

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

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
/*---------------------------------------------------------------------------*/
/* Change to match your configuration */
#define IEEE802154_CONF_PANID 0xABCD
#define IEEE802154_CONF_DEFAULT_CHANNEL 25
/*---------------------------------------------------------------------------*/
/* Enable the ROM bootloader */
#define ROM_BOOTLOADER_ENABLE 1
/*---------------------------------------------------------------------------*/
/* For very sleepy operation */
#define RF_BLE_CONF_ENABLED 0
#define UIP_DS6_CONF_PERIOD CLOCK_SECOND
#define UIP_CONF_TCP 0
#define RPL_CONF_LEAF_ONLY 1
/*
* We'll fail without RPL probing, so turn it on explicitly even though it's
* on by default
*/
#define RPL_CONF_WITH_PROBING 1
/*---------------------------------------------------------------------------*/
#endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,424 @@
/*
* Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "sys/etimer.h"
#include "sys/stimer.h"
#include "sys/process.h"
#include "dev/leds.h"
#include "dev/watchdog.h"
#include "dev/button-hal.h"
#include "batmon-sensor.h"
#include "board-peripherals.h"
#include "net/netstack.h"
#include "net/ipv6/uip-ds6-nbr.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/routing/routing.h"
#include "coap-engine.h"
#include "coap.h"
#include "ti-lib.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
/*---------------------------------------------------------------------------*/
/* Normal mode duration params in seconds */
#define NORMAL_OP_DURATION_DEFAULT 10
#define NORMAL_OP_DURATION_MIN 10
#define NORMAL_OP_DURATION_MAX 60
/*---------------------------------------------------------------------------*/
/* Observer notification period params in seconds */
#define PERIODIC_INTERVAL_DEFAULT 30
#define PERIODIC_INTERVAL_MIN 30
#define PERIODIC_INTERVAL_MAX 86400 /* 1 day */
/*---------------------------------------------------------------------------*/
#define VERY_SLEEPY_MODE_OFF 0
#define VERY_SLEEPY_MODE_ON 1
/*---------------------------------------------------------------------------*/
#define BUTTON_TRIGGER BUTTON_HAL_ID_KEY_LEFT
/*---------------------------------------------------------------------------*/
#define MAC_CAN_BE_TURNED_OFF 0
#define MAC_MUST_STAY_ON 1
#define KEEP_MAC_ON_MIN_PERIOD 10 /* secs */
/*---------------------------------------------------------------------------*/
#define PERIODIC_INTERVAL CLOCK_SECOND
/*---------------------------------------------------------------------------*/
#define POST_STATUS_BAD 0x80
#define POST_STATUS_HAS_MODE 0x40
#define POST_STATUS_HAS_DURATION 0x20
#define POST_STATUS_HAS_INTERVAL 0x10
#define POST_STATUS_NONE 0x00
/*---------------------------------------------------------------------------*/
typedef struct sleepy_config_s {
unsigned long interval;
unsigned long duration;
uint8_t mode;
} sleepy_config_t;
sleepy_config_t config;
/*---------------------------------------------------------------------------*/
#define STATE_NORMAL 0
#define STATE_NOTIFY_OBSERVERS 1
#define STATE_VERY_SLEEPY 2
/*---------------------------------------------------------------------------*/
static struct stimer st_duration;
static struct stimer st_interval;
static struct stimer st_min_mac_on_duration;
static struct etimer et_periodic;
static process_event_t event_new_config;
static uint8_t state;
/*---------------------------------------------------------------------------*/
const char *not_supported_msg = "Supported:text/plain,application/json";
/*---------------------------------------------------------------------------*/
PROCESS(very_sleepy_demo_process, "CC13xx/CC26xx very sleepy process");
AUTOSTART_PROCESSES(&very_sleepy_demo_process);
/*---------------------------------------------------------------------------*/
static void
readings_get_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
int temp;
int voltage;
if(request != NULL) {
coap_get_header_accept(request, &accept);
}
temp = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP);
voltage = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT);
if(accept == -1 || accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"{\"temp\":{\"v\":%d,\"u\":\"C\"},"
"\"voltage\":{\"v\":%d,\"u\":\"mV\"}}",
temp, (voltage * 125) >> 5);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV",
temp, (voltage * 125) >> 5);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, not_supported_msg,
strlen(not_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
RESOURCE(readings_resource, "title=\"Sensor Readings\";obs",
readings_get_handler, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
static void
conf_get_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
if(request != NULL) {
coap_get_header_accept(request, &accept);
}
if(accept == -1 || accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"{\"config\":{\"mode\":%u,\"duration\":%lu,\"interval\":%lu}}",
config.mode, config.duration, config.interval);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"Mode=%u, Duration=%lusecs, Interval=%lusecs",
config.mode, config.duration, config.interval);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, not_supported_msg,
strlen(not_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
conf_post_handler(coap_message_t *request, coap_message_t *response,
uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const char *ptr = NULL;
char tmp_buf[16];
unsigned long interval = 0;
unsigned long duration = 0;
uint8_t mode = VERY_SLEEPY_MODE_OFF;
uint8_t post_status = POST_STATUS_NONE;
int rv;
rv = coap_get_post_variable(request, "mode", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
rv = atoi(tmp_buf);
if(rv == 1) {
mode = VERY_SLEEPY_MODE_ON;
post_status |= POST_STATUS_HAS_MODE;
} else if(rv == 0) {
mode = VERY_SLEEPY_MODE_OFF;
post_status |= POST_STATUS_HAS_MODE;
} else {
post_status = POST_STATUS_BAD;
}
}
rv = coap_get_post_variable(request, "duration", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
rv = atoi(tmp_buf);
duration = (unsigned long)rv;
if(duration < NORMAL_OP_DURATION_MIN || duration > NORMAL_OP_DURATION_MAX) {
post_status = POST_STATUS_BAD;
} else {
post_status |= POST_STATUS_HAS_DURATION;
}
}
rv = coap_get_post_variable(request, "interval", &ptr);
if(rv && rv < 16) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, ptr, rv);
rv = atoi(tmp_buf);
interval = (unsigned long)rv;
if(interval < PERIODIC_INTERVAL_MIN || interval > PERIODIC_INTERVAL_MAX) {
post_status = POST_STATUS_BAD;
} else {
post_status |= POST_STATUS_HAS_INTERVAL;
}
}
if((post_status & POST_STATUS_BAD) == POST_STATUS_BAD ||
post_status == POST_STATUS_NONE) {
coap_set_status_code(response, BAD_REQUEST_4_00);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"mode=0|1&duration=[%u,%u]&interval=[%u,%u]",
NORMAL_OP_DURATION_MIN, NORMAL_OP_DURATION_MAX,
PERIODIC_INTERVAL_MIN, PERIODIC_INTERVAL_MAX);
coap_set_payload(response, buffer, strlen((char *)buffer));
return;
}
/* Values are sane. Update the config and notify the process */
if(post_status & POST_STATUS_HAS_MODE) {
config.mode = mode;
}
if(post_status & POST_STATUS_HAS_INTERVAL) {
config.interval = interval;
}
if(post_status & POST_STATUS_HAS_DURATION) {
config.duration = duration;
}
process_post(&very_sleepy_demo_process, event_new_config, NULL);
}
/*---------------------------------------------------------------------------*/
RESOURCE(very_sleepy_conf,
"title=\"Very sleepy conf: "
"GET|POST mode=0|1&interval=<secs>&duration=<secs>\";rt=\"Control\"",
conf_get_handler, conf_post_handler, NULL, NULL);
/*---------------------------------------------------------------------------*/
/*
* If our preferred parent is not NBR_REACHABLE in the ND cache, NUD will send
* a unicast NS and wait for NA. If NA fails then the neighbour will be removed
* from the ND cache and the default route will be deleted. To prevent this,
* keep the MAC on until the parent becomes NBR_REACHABLE. We also keep the MAC
* on if we are about to do RPL probing.
*
* In all cases, the radio will be locked on for KEEP_MAC_ON_MIN_PERIOD secs
*/
static uint8_t
keep_mac_on(void)
{
uip_ds6_nbr_t *nbr;
uint8_t rv = MAC_CAN_BE_TURNED_OFF;
if(!stimer_expired(&st_min_mac_on_duration)) {
return MAC_MUST_STAY_ON;
}
#if RPL_WITH_PROBING
/* Determine if we are about to send a RPL probe */
if(CLOCK_LT(etimer_expiration_time(
&rpl_get_default_instance()->dag.probing_timer.etimer),
(clock_time() + PERIODIC_INTERVAL))) {
rv = MAC_MUST_STAY_ON;
}
#endif
/* It's OK to pass a NULL pointer, the callee checks and returns NULL */
nbr = uip_ds6_nbr_lookup(uip_ds6_defrt_choose());
if(nbr == NULL) {
/* We don't have a default route, or it's not reachable (NUD likely). */
rv = MAC_MUST_STAY_ON;
} else {
if(nbr->state != NBR_REACHABLE) {
rv = MAC_MUST_STAY_ON;
}
}
if(rv == MAC_MUST_STAY_ON && stimer_expired(&st_min_mac_on_duration)) {
stimer_set(&st_min_mac_on_duration, KEEP_MAC_ON_MIN_PERIOD);
}
return rv;
}
/*---------------------------------------------------------------------------*/
static void
switch_to_normal(void)
{
state = STATE_NOTIFY_OBSERVERS;
/*
* Stay in normal mode for 'duration' secs.
* Transition back to normal in 'interval' secs, _including_ 'duration'
*/
stimer_set(&st_duration, config.duration);
stimer_set(&st_interval, config.interval);
}
/*---------------------------------------------------------------------------*/
static void
switch_to_very_sleepy(void)
{
state = STATE_VERY_SLEEPY;
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(very_sleepy_demo_process, ev, data)
{
uint8_t mac_keep_on;
PROCESS_BEGIN();
SENSORS_ACTIVATE(batmon_sensor);
config.mode = VERY_SLEEPY_MODE_OFF;
config.interval = PERIODIC_INTERVAL_DEFAULT;
config.duration = NORMAL_OP_DURATION_DEFAULT;
state = STATE_NORMAL;
event_new_config = process_alloc_event();
readings_resource.flags += IS_OBSERVABLE;
coap_activate_resource(&readings_resource, "sen/readings");
coap_activate_resource(&very_sleepy_conf, "very_sleepy_config");
printf("Very Sleepy Demo Process\n");
switch_to_normal();
etimer_set(&et_periodic, PERIODIC_INTERVAL);
while(1) {
PROCESS_YIELD();
if(ev == button_hal_release_event &&
((button_hal_button_t *)data)->unique_id == BUTTON_TRIGGER) {
switch_to_normal();
}
if(ev == event_new_config) {
stimer_set(&st_interval, config.interval);
stimer_set(&st_duration, config.duration);
}
if((ev == PROCESS_EVENT_TIMER && data == &et_periodic) ||
(ev == button_hal_release_event &&
((button_hal_button_t *)data)->unique_id == BUTTON_TRIGGER) ||
(ev == event_new_config)) {
/*
* Determine if the stack is about to do essential network maintenance
* and, if so, keep the MAC layer on
*/
mac_keep_on = keep_mac_on();
if(mac_keep_on == MAC_MUST_STAY_ON || state != STATE_VERY_SLEEPY) {
leds_on(LEDS_GREEN);
NETSTACK_MAC.on();
}
/*
* Next, switch between normal and very sleepy mode depending on config,
* send notifications to observers as required.
*/
if(state == STATE_NOTIFY_OBSERVERS) {
coap_notify_observers(&readings_resource);
state = STATE_NORMAL;
}
if(state == STATE_NORMAL) {
if(stimer_expired(&st_duration)) {
stimer_set(&st_duration, config.duration);
if(config.mode == VERY_SLEEPY_MODE_ON) {
switch_to_very_sleepy();
}
}
} else if(state == STATE_VERY_SLEEPY) {
if(stimer_expired(&st_interval)) {
switch_to_normal();
}
}
if(mac_keep_on == MAC_CAN_BE_TURNED_OFF && state == STATE_VERY_SLEEPY) {
leds_off(LEDS_GREEN);
NETSTACK_MAC.off();
} else {
leds_on(LEDS_GREEN);
NETSTACK_MAC.on();
}
/* Schedule next pass */
etimer_set(&et_periodic, PERIODIC_INTERVAL);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,19 @@
CONTIKI_PROJECT = web-demo
all: $(CONTIKI_PROJECT)
MODULES_REL += ./resources
PROJECT_SOURCEFILES += web-demo.c coap-server.c net-uart.c mqtt-client.c
PROJECT_SOURCEFILES += httpd-simple.c
ifeq ($(MAKE_ROUTING),MAKE_ROUTING_RPL_CLASSIC)
# 6lbr only supports RPL Classic
PROJECT_SOURCEFILES += cetic-6lbr-client.c
endif
# REST Engine shall use Erbium CoAP implementation
MODULES += os/net/app-layer/mqtt
MODULES += os/net/app-layer/coap
CONTIKI=../../../..
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1,185 @@
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 all CC26xx-based boards.
To change between target boards, follow the instructions in the wiki.
Do not forget to `make clean` when switching between the boards.
Specifically for some older CC2650 SensorTags, you may also need to change
`project-conf.h` such that `SENSORTAG_CC2650_REV_1_2_0` is defined as 1. To
check if your sensortag is one of those older ones, look for "REV: 1.2"
printed on the PCB. There may also be a sticker that reads "HW Rev 1.2.0". An
indication that you may need to do this is if you get a "Could not open flash
to load config" error on device startup.
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 a CoAP client.
You can achieve this by following the guides on how to set up your system
[in the wiki](https://github.com/contiki-ng/contiki-ng/wiki#setting-up-contiki-ng).
You should start by sending a CoAP GET request for the `.well-known/core`
resource. If you are using libcoap's CoAP client, this can be achieved by:
```
coap-client -m get coap://[<device IPv6 address here>]/.well-known/core
```
Adjust the above command to match the command line arguments of your CoAP
client.
The Device will respond with a list of all available CoAP resources. This list
will be different between the various CC13x0/CC26x0 boards.
Send a CoAP GET request for any of those resrouces to retrieve its value.
Send a CoAP POST to the `lt/g` or `lt/r` to toggle the green/red LED
respectively.
You can also use CoAP to enable/disable BLE advertisements! This can be done
by sending a PUT or POST request to the `dev/ble_advd` resource. Your request
should contain the desired payload, which can be:
* `mode=on|off`
* `name=<name>`
* `interval=<secs>`
or a combination of the above delimited with an amp. For example, you can set
as payload `mode=on&name=My CC26xx Device 4&interval=5`.
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.
IBM Watson IoT Platform
----------------------------
To use IBM Watson IoT Platform, you have to go to SECURITY tab of Device page to select "TLS Optional". This step is critical. If you don't do this, you need to use TLS for connection and default cc26xx-web-demo won't work.
![IBM Watson IoT Platform TLS Optional Configuration](img/ibm-watson-iot-platform-tls-optional.png)

View File

@ -0,0 +1,204 @@
/*
* 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/routing/routing.h"
#include "net/ipv6/uip.h"
#if ROUTING_CONF_RPL_CLASSIC
#include "net/routing/rpl-classic/rpl.h"
#include "net/routing/rpl-classic/rpl-private.h"
#else
#error The 6LBR client is only meant for RPL Classic. Set MAKE_ROUTING accordingly.
#endif
#include <string.h>
#include <stdio.h>
/*---------------------------------------------------------------------------*/
#define DEBUG 0
#include "net/ipv6/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_instance_t *instance;
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);
instance = rpl_get_default_instance();
if(instance && instance->current_dag->preferred_parent) {
add_ipaddr(buf + i, rpl_parent_get_ipaddr(instance->current_dag->preferred_parent));
} 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();
}
/*---------------------------------------------------------------------------*/
/**
* @}
*/

View File

@ -0,0 +1,167 @@
/*
* 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 "coap-engine.h"
#include "board-peripherals.h"
#include "rf-core/rf-ble.h"
#include "cc26xx-web-demo.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
/* Common resources */
extern coap_resource_t res_leds;
extern coap_resource_t res_batmon_temp;
extern coap_resource_t res_batmon_volt;
extern coap_resource_t res_device_sw;
extern coap_resource_t res_device_hw;
extern coap_resource_t res_device_uptime;
extern coap_resource_t res_device_cfg_reset;
extern coap_resource_t res_parent_rssi;
extern coap_resource_t res_parent_ip;
#if RF_BLE_ENABLED
extern coap_resource_t res_ble_advd;
#endif
extern coap_resource_t res_toggle_red;
extern coap_resource_t res_toggle_green;
/* Board-specific resources */
#if BOARD_SENSORTAG
extern coap_resource_t res_bmp280_temp;
extern coap_resource_t res_bmp280_press;
extern coap_resource_t res_tmp007_amb;
extern coap_resource_t res_tmp007_obj;
extern coap_resource_t res_hdc1000_temp;
extern coap_resource_t res_hdc1000_hum;
extern coap_resource_t res_opt3001_light;
extern coap_resource_t res_mpu_acc_x;
extern coap_resource_t res_mpu_acc_y;
extern coap_resource_t res_mpu_acc_z;
extern coap_resource_t res_mpu_gyro_x;
extern coap_resource_t res_mpu_gyro_y;
extern coap_resource_t res_mpu_gyro_z;
#else
extern coap_resource_t res_toggle_orange;
extern coap_resource_t res_toggle_yellow;
#endif
#if CC26XX_WEB_DEMO_ADC_DEMO
extern coap_resource_t res_adc_dio23;
#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)
{
coap_activate_resource(&res_toggle_green, "lt/g");
coap_activate_resource(&res_toggle_red, "lt/r");
coap_activate_resource(&res_leds, "lt");
#if BOARD_SENSORTAG
coap_activate_resource(&res_bmp280_temp, "sen/bar/temp");
coap_activate_resource(&res_bmp280_press, "sen/bar/pres");
coap_activate_resource(&res_tmp007_amb, "sen/tmp/amb");
coap_activate_resource(&res_tmp007_obj, "sen/tmp/obj");
coap_activate_resource(&res_hdc1000_temp, "sen/hdc/t");
coap_activate_resource(&res_hdc1000_hum, "sen/hdc/h");
coap_activate_resource(&res_opt3001_light, "sen/opt/light");
coap_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x");
coap_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y");
coap_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z");
coap_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x");
coap_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y");
coap_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z");
#elif BOARD_SMARTRF06EB
coap_activate_resource(&res_toggle_yellow, "lt/y");
coap_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");
coap_activate_resource(&res_batmon_temp, "sen/batmon/temp");
coap_activate_resource(&res_batmon_volt, "sen/batmon/voltage");
#if CC26XX_WEB_DEMO_ADC_DEMO
coap_activate_resource(&res_adc_dio23, "sen/adc/dio23");
#endif
coap_activate_resource(&res_device_hw, "dev/mdl/hw");
coap_activate_resource(&res_device_sw, "dev/mdl/sw");
coap_activate_resource(&res_device_uptime, "dev/uptime");
coap_activate_resource(&res_device_cfg_reset, "dev/cfg_reset");
coap_activate_resource(&res_parent_rssi, "net/parent/RSSI");
coap_activate_resource(&res_parent_ip, "net/parent/IPv6");
#if RF_BLE_ENABLED
coap_activate_resource(&res_ble_advd, "dev/ble_advd");
#endif
start_board_resources();
/* Define application-specific events here. */
while(1) {
PROCESS_WAIT_EVENT();
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/**
* @}
*/

View 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_ */
/*---------------------------------------------------------------------------*/
/**
* @}
*/

File diff suppressed because it is too large Load Diff

View 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_MAIN_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_ */

View File

@ -0,0 +1,925 @@
/*
* 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.h"
#include "net/routing/routing.h"
#include "mqtt.h"
#include "net/ipv6/uip.h"
#include "net/ipv6/uip-icmp6.h"
#include "sys/etimer.h"
#include "sys/ctimer.h"
#include "lib/sensors.h"
#include "dev/button-hal.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 5
#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 */
extern int def_rt_rssi;
/*---------------------------------------------------------------------------*/
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;
}
/*---------------------------------------------------------------------------*/
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);
/*---------------------------------------------------------------------------*/
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;
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);
}
/*---------------------------------------------------------------------------*/
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;
char def_rt_str[64];
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 */
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_status_t conn_attempt_result = mqtt_connect(&conn, conf->broker_ip,
conf->broker_port,
conf->pub_interval * 3);
if(conn_attempt_result == MQTT_STATUS_OK) {
state = MQTT_CLIENT_STATE_CONNECTING;
} else {
state = MQTT_CLIENT_STATE_CONFIG_ERROR;
}
}
/*---------------------------------------------------------------------------*/
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);
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 or in the case of an error */
if(conn.state == MQTT_CONN_STATE_NOT_CONNECTED || conn.state == MQTT_CONN_STATE_ERROR) {
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();
/* Main loop */
while(1) {
PROCESS_YIELD();
if(ev == button_hal_release_event) {
button_hal_button_t *btn = (button_hal_button_t *)data;
if(btn->unique_id == 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 == button_hal_release_event &&
((button_hal_button_t *)data)->unique_id ==
CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER)) {
state_machine();
}
if(ev == cc26xx_web_demo_load_config_defaults) {
init_config();
etimer_set(&publish_periodic_timer, NEW_CONFIG_WAIT_INTERVAL);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/**
* @}
*/

View File

@ -0,0 +1,71 @@
/*
* 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_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;
uint16_t broker_port;
} mqtt_client_config_t;
/*---------------------------------------------------------------------------*/
#endif /* MQTT_CLIENT_H_ */
/*---------------------------------------------------------------------------*/
/**
* @}
*/

View File

@ -0,0 +1,321 @@
/*
* 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.h"
#include "sys/process.h"
#include "dev/serial-line.h"
#include "dev/cc26xx-uart.h"
#include "net/ipv6/uip.h"
#include "net/ipv6/uip-udp-packet.h"
#include "net/ipv6/uiplib.h"
#include "net-uart.h"
#include "httpd-simple.h"
#include "sys/cc.h"
#include "ti-lib.h"
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
/*---------------------------------------------------------------------------*/
#define DEBUG DEBUG_NONE
#include "net/ipv6/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
/*---------------------------------------------------------------------------*/
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;
}
/*---------------------------------------------------------------------------*/
static void
release_uart(void)
{
cc26xx_uart_set_input(NULL);
}
/*---------------------------------------------------------------------------*/
static void
keep_uart_on(void)
{
cc26xx_uart_set_input(serial_line_input_byte);
}
/*---------------------------------------------------------------------------*/
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();
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View 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/ipv6/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_ */
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,79 @@
/*
* 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 IEEE802154_CONF_PANID 0xABCD
#define IEEE802154_CONF_DEFAULT_CHANNEL 26
#define RF_BLE_CONF_ENABLED 1
/*---------------------------------------------------------------------------*/
/* Enable TCP */
#define UIP_CONF_TCP 1
/* Enable/Disable Components of this Demo */
#define CC26XX_WEB_DEMO_CONF_MQTT_CLIENT 1
#define CC26XX_WEB_DEMO_CONF_6LBR_CLIENT ROUTING_CONF_RPL_CLASSIC
#define CC26XX_WEB_DEMO_CONF_COAP_SERVER 1
#define CC26XX_WEB_DEMO_CONF_NET_UART 1
/*
* ADC sensor functionality. To test this, an external voltage source should be
* connected to DIO23
* Enable/Disable DIO23 ADC reading by setting CC26XX_WEB_DEMO_CONF_ADC_DEMO
*/
#define CC26XX_WEB_DEMO_CONF_ADC_DEMO 0
/*---------------------------------------------------------------------------*/
/*
* Change to 1 if you are using an older CC2650 Sensortag (look for Rev: 1.2
* printed on the PCB, or for a sticker reading "HW Rev 1.2.0").
*
* This may be the case if you are getting this error:
* "Could not open flash to load config"
* when your sensortag is starting up.
*/
#define SENSORTAG_CC2650_REV_1_2_0 0
/*---------------------------------------------------------------------------*/
/* Enable the ROM bootloader */
#define ROM_BOOTLOADER_ENABLE 1
/*---------------------------------------------------------------------------*/
/*
* Shrink the size of the uIP buffer, routing table and ND cache.
* Set the TCP MSS
*/
#define UIP_CONF_BUFFER_SIZE 500
#define NETSTACK_MAX_ROUTE_ENTRIES 5
#define NBR_TABLE_CONF_MAX_NEIGHBORS 5
#define UIP_CONF_TCP_MSS 128
/*---------------------------------------------------------------------------*/
#endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,114 @@
/*
* 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 "coap-engine.h"
#include "coap.h"
#include "rf-core/rf-ble.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(coap_message_t *request, coap_message_t *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 = coap_get_post_variable(request, "name", &text);
if(len > 0 && len < BLE_NAME_BUF_LEN) {
memcpy(name, text, len);
rf_ble_beacond_config(0, name);
success = 1;
}
len = coap_get_post_variable(request, "interval", &text);
rv = atoi(text);
if(rv > 0) {
rf_ble_beacond_config((clock_time_t)(rv * CLOCK_SECOND), NULL);
success = 1;
}
len = coap_get_post_variable(request, "mode", &text);
if(len) {
if(strncmp(text, "on", len) == 0) {
if(rf_ble_beacond_start()) {
success = 1;
} else {
coap_set_status_code(response, FORBIDDEN_4_03);
coap_set_payload(response, forbidden_payload,
strlen(forbidden_payload));
return;
}
} else if(strncmp(text, "off", len) == 0) {
rf_ble_beacond_stop();
success = 1;
} else {
success = 0;
}
}
if(!success) {
coap_set_status_code(response, BAD_REQUEST_4_00);
}
}
/*---------------------------------------------------------------------------*/
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);
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,212 @@
/*
* 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 "coap-engine.h"
#include "coap.h"
#include "sys/clock.h"
#include "coap-server.h"
#include "cc26xx-web-demo.h"
#include "ti-lib.h"
#include <string.h>
#include <stdio.h>
/*---------------------------------------------------------------------------*/
static uint16_t
detect_chip(void)
{
if(ti_lib_chipinfo_chip_family_is_cc26xx()) {
if(ti_lib_chipinfo_supports_ieee_802_15_4() == true) {
if(ti_lib_chipinfo_supports_ble() == true) {
return 2650;
} else {
return 2630;
}
} else {
return 2640;
}
} else if(ti_lib_chipinfo_chip_family_is_cc13xx()) {
if(ti_lib_chipinfo_supports_ble() == false &&
ti_lib_chipinfo_supports_ieee_802_15_4() == false) {
return 1310;
} else if(ti_lib_chipinfo_supports_ble() == true &&
ti_lib_chipinfo_supports_ieee_802_15_4() == true) {
return 1350;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_hw(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
uint16_t chip = detect_chip();
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s on CC%u", BOARD_STRING,
chip);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"HW Ver\":\"%s on CC%u\"}",
BOARD_STRING, chip);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<hw-ver val=\"%s on CC%u\"/>", BOARD_STRING,
chip);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_sw(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", CONTIKI_VERSION_STRING);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"SW Ver\":\"%s\"}",
CONTIKI_VERSION_STRING);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<sw-ver val=\"%s\"/>", CONTIKI_VERSION_STRING);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_uptime(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%lu", clock_seconds());
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"uptime\":%lu}",
clock_seconds());
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<uptime val=\"%lu\" unit=\"sec\"/>", clock_seconds());
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_post_handler_cfg_reset(coap_message_t *request, coap_message_t *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);
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,111 @@
/*
* 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 "coap-engine.h"
#include "dev/leds.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
static void
res_post_put_handler(coap_message_t *request, coap_message_t *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 = coap_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 = coap_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) {
coap_set_status_code(response, BAD_REQUEST_4_00);
}
}
/*---------------------------------------------------------------------------*/
/*
* A simple actuator example, depending on the color query parameter and post
* variable mode, corresponding led is activated or deactivated
*/
#if BOARD_SENSORTAG || BOARD_LAUNCHPAD
#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);
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
/**
* \addtogroup cc26xx-web-demo
* @{
*
* \file
* CoAP resource handler for network-related resources
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "coap-engine.h"
#include "coap.h"
#include "net/ipv6/uip-ds6.h"
#include "coap-server.h"
#include "cc26xx-web-demo.h"
#include "ti-lib.h"
#include <string.h>
#include <stdio.h>
/*---------------------------------------------------------------------------*/
extern int def_rt_rssi;
/*---------------------------------------------------------------------------*/
static void
res_get_handler_parent_rssi(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", def_rt_rssi);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}",
def_rt_rssi);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"<parent-rssi val=\"%d\"/>", def_rt_rssi);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_pref_parent(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
unsigned int accept = -1;
char def_rt_str[64];
coap_get_header_accept(request, &accept);
memset(def_rt_str, 0, sizeof(def_rt_str));
cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str),
uip_ds6_defrt_choose());
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%s", def_rt_str);
coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}",
def_rt_str);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE,
"<parent=\"%s\"/>", def_rt_str);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
RESOURCE(res_parent_rssi, "title=\"Parent RSSI\";rt=\"dBm\"",
res_get_handler_parent_rssi, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
RESOURCE(res_parent_ip, "title=\"Preferred Parent\";rt=\"IPv6 address\"",
res_get_handler_pref_parent, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,301 @@
/*
* 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 "coap-engine.h"
#include "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, coap_message_t *request,
coap_message_t *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) {
coap_set_status_code(response, NOT_FOUND_4_04);
coap_set_payload(response, coap_server_not_found_msg,
strlen(coap_server_not_found_msg));
return;
}
coap_get_header_accept(request, &accept);
if(accept == -1 || accept == TEXT_PLAIN) {
coap_set_header_content_format(response, TEXT_PLAIN);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", reading->converted);
coap_set_payload(response, (uint8_t *)buffer,
strlen((char *)buffer));
} else if(accept == APPLICATION_JSON) {
coap_set_header_content_format(response, APPLICATION_JSON);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"%s\":%s}",
reading->descr, reading->converted);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else if(accept == APPLICATION_XML) {
coap_set_header_content_format(response, APPLICATION_XML);
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE,
"<%s val=\"%s\" unit=\"%s\"/>", reading->xml_element,
reading->converted, reading->units);
coap_set_payload(response, buffer, strlen((char *)buffer));
} else {
coap_set_status_code(response, NOT_ACCEPTABLE_4_06);
coap_set_payload(response, coap_server_supported_msg,
strlen(coap_server_supported_msg));
}
}
/*---------------------------------------------------------------------------*/
/* BatMon resources and handler: Temperature, Voltage */
static void
res_get_handler_batmon_temp(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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 CC26XX_WEB_DEMO_ADC_DEMO
/*---------------------------------------------------------------------------*/
static void
res_get_handler_adc_dio23(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_ADC_DIO23, request, response,
buffer, preferred_size, offset);
}
/*---------------------------------------------------------------------------*/
RESOURCE(res_adc_dio23, "title=\"ADC DIO23\";rt=\"mV\"",
res_get_handler_adc_dio23, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
#endif
/*---------------------------------------------------------------------------*/
#if BOARD_SENSORTAG
/*---------------------------------------------------------------------------*/
/* MPU resources and handler: Accelerometer and Gyro */
static void
res_get_handler_mpu_acc_x(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *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);
/*---------------------------------------------------------------------------*/
/* HDC1000 sensor resources and handler: Temperature, Pressure */
static void
res_get_handler_hdc_temp(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, request, response,
buffer, preferred_size, offset);
}
/*---------------------------------------------------------------------------*/
static void
res_get_handler_hdc_humidity(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, request, response,
buffer, preferred_size, offset);
}
/*---------------------------------------------------------------------------*/
RESOURCE(res_hdc1000_temp, "title=\"Temperature\";rt=\"C\"",
res_get_handler_hdc_temp, NULL, NULL, NULL);
RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"",
res_get_handler_hdc_humidity, NULL, NULL, NULL);
/*---------------------------------------------------------------------------*/
/* Illuminance resources and handler */
static void
res_get_handler_opt(coap_message_t *request, coap_message_t *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 */
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,118 @@
/*
* 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 "coap-engine.h"
#include "dev/leds.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
static void
res_post_handler_red(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
leds_toggle(LEDS_RED);
}
/*---------------------------------------------------------------------------*/
static void
res_post_handler_green(coap_message_t *request, coap_message_t *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(coap_message_t *request, coap_message_t *response,
uint8_t *buffer,
uint16_t preferred_size, int32_t *offset)
{
leds_toggle(LEDS_YELLOW);
}
/*---------------------------------------------------------------------------*/
static void
res_post_handler_orange(coap_message_t *request, coap_message_t *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
/*---------------------------------------------------------------------------*/
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,234 @@
/*
* 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
#ifdef CC26XX_WEB_DEMO_CONF_ADC_DEMO
#define CC26XX_WEB_DEMO_ADC_DEMO CC26XX_WEB_DEMO_CONF_ADC_DEMO
#else
#define CC26XX_WEB_DEMO_ADC_DEMO 0
#endif
/*---------------------------------------------------------------------------*/
/* Active probing of RSSI from our preferred parent */
#if (CC26XX_WEB_DEMO_COAP_SERVER || CC26XX_WEB_DEMO_MQTT_CLIENT)
#define CC26XX_WEB_DEMO_READ_PARENT_RSSI 1
#else
#define CC26XX_WEB_DEMO_READ_PARENT_RSSI 0
#endif
#define CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MAX 86400 /* secs: 1 day */
#define CC26XX_WEB_DEMO_RSSI_MEASURE_INTERVAL_MIN 5 /* secs */
/*---------------------------------------------------------------------------*/
/* User configuration */
/* Take a sensor reading on button press */
#define CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER BUTTON_HAL_ID_KEY_LEFT
/* 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 BUTTON_HAL_ID_REED_RELAY
#elif BOARD_LAUNCHPAD
#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER BUTTON_HAL_ID_KEY_LEFT
#else
#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER BUTTON_HAL_ID_KEY_DOWN
#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"
#if CPU_FAMILY_CC13XX
#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc13xx"
#else
#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc26xx"
#endif
#define CC26XX_WEB_DEMO_DEFAULT_EVENT_TYPE_ID "status"
#define CC26XX_WEB_DEMO_DEFAULT_SUBSCRIBE_CMD_TYPE "+"
#define CC26XX_WEB_DEMO_DEFAULT_BROKER_PORT 1883
#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_HDC_TEMP 6
#define CC26XX_WEB_DEMO_SENSOR_HDC_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
#define CC26XX_WEB_DEMO_SENSOR_ADC_DIO23 15
/*---------------------------------------------------------------------------*/
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;
int def_rt_ping_interval;
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_ */
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/