diff --git a/arch/platform/cooja/platform.c b/arch/platform/cooja/platform.c index 9ef310bce..591abe67e 100644 --- a/arch/platform/cooja/platform.c +++ b/arch/platform/cooja/platform.c @@ -64,6 +64,7 @@ #include "dev/button-sensor.h" #include "dev/pir-sensor.h" #include "dev/vib-sensor.h" +#include "dev/moteid.h" #include "sys/node-id.h" #include "services/rpl-border-router/rpl-border-router.h" @@ -151,13 +152,13 @@ set_lladdr(void) { int i; for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) { - addr.u8[i + 1] = node_id & 0xff; - addr.u8[i + 0] = node_id >> 8; + addr.u8[i + 1] = simMoteID & 0xff; + addr.u8[i + 0] = simMoteID >> 8; } } #else /* NETSTACK_CONF_WITH_IPV6 */ - addr.u8[0] = node_id & 0xff; - addr.u8[1] = node_id >> 8; + addr.u8[0] = simMoteID & 0xff; + addr.u8[1] = simMoteID >> 8; #endif /* NETSTACK_CONF_WITH_IPV6 */ linkaddr_set_node_addr(&addr); } @@ -177,11 +178,6 @@ platform_init_stage_two() void platform_init_stage_three() { - if(node_id > 0) { - LOG_INFO("Node id is set to %u.\n", node_id); - } else { - LOG_INFO("Node id is not set.\n"); - } /* Initialize eeprom */ eeprom_init(); /* Start serial process */ diff --git a/arch/platform/jn516x/Makefile.jn516x b/arch/platform/jn516x/Makefile.jn516x index bb40b5638..93ba5f296 100644 --- a/arch/platform/jn516x/Makefile.jn516x +++ b/arch/platform/jn516x/Makefile.jn516x @@ -82,7 +82,7 @@ OBJDUMP:=$(CROSS_COMPILE)-objdump ARCH = jn516x-ccm-star.c exceptions.c rtimer-arch.c rtimer-arch-slow.c \ slip_uart0.c clock.c micromac-radio.c int-master.c \ - node-id.c watchdog.c slip.c dbg.c + watchdog.c slip.c dbg.c # Default uart0 for printf and slip TARGET_WITH_UART0 ?= 1 TARGET_WITH_UART1 ?= 0 diff --git a/arch/platform/jn516x/platform.c b/arch/platform/jn516x/platform.c index 20dabfb61..9d44444e8 100644 --- a/arch/platform/jn516x/platform.c +++ b/arch/platform/jn516x/platform.c @@ -113,8 +113,7 @@ static uint32_t sleep_start_ticks; #define LOG_LEVEL LOG_LEVEL_MAIN /*---------------------------------------------------------------------------*/ /* Reads MAC from SoC - * Must be called before node_id_restore() - * and network addresses initialization */ + * Must be called before network addresses initialization */ static void init_node_mac(void) { @@ -139,14 +138,9 @@ set_linkaddr(void) #if NETSTACK_CONF_WITH_IPV6 memcpy(addr.u8, node_mac, sizeof(addr.u8)); #else - if(node_id == 0) { - int i; - for(i = 0; i < LINKADDR_SIZE; ++i) { - addr.u8[i] = node_mac[LINKADDR_SIZE - 1 - i]; - } - } else { - addr.u8[0] = node_id & 0xff; - addr.u8[1] = node_id >> 8; + int i; + for(i = 0; i < LINKADDR_SIZE; ++i) { + addr.u8[i] = node_mac[LINKADDR_SIZE - 1 - i]; } #endif linkaddr_set_node_addr(&addr); @@ -194,20 +188,6 @@ platform_init_stage_one(void) leds_init(); leds_on(LEDS_ALL); init_node_mac(); - - node_id_restore(); - -#if WITH_TINYOS_AUTO_IDS - node_id = TOS_NODE_ID; -#endif /* WITH_TINYOS_AUTO_IDS */ - /* for setting "hardcoded" IEEE 802.15.4 MAC addresses */ -#ifdef IEEE_802154_MAC_ADDRESS - { - uint8_t ieee[] = IEEE_802154_MAC_ADDRESS; - memcpy(node_mac, ieee, sizeof(uip_lladdr.addr)); - node_mac[7] = node_id & 0xff; - } -#endif } /*---------------------------------------------------------------------------*/ void @@ -225,12 +205,6 @@ platform_init_stage_two(void) void platform_init_stage_three(void) { - if(node_id > 0) { - LOG_INFO("Node id is set to %u.\n", node_id); - } else { - LOG_INFO("Node id is not set.\n"); - } - #ifndef UIP_FALLBACK_INTERFACE uart0_set_input(serial_line_input_byte); serial_line_init(); diff --git a/arch/platform/native/platform.c b/arch/platform/native/platform.c index c5c4f23e7..d00efaac1 100644 --- a/arch/platform/native/platform.c +++ b/arch/platform/native/platform.c @@ -120,9 +120,6 @@ static uint8_t mac_addr[] = PLATFORM_CONF_MAC_ADDR; static uint8_t mac_addr[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; #endif /* PLATFORM_CONF_MAC_ADDR */ -#if !NETSTACK_CONF_WITH_IPV6 -static uint16_t node_id = 0x0102; -#endif /* !NETSTACK_CONF_WITH_IPV6 */ /*---------------------------------------------------------------------------*/ int select_set_callback(int fd, const struct select_callback *callback) @@ -187,14 +184,9 @@ set_lladdr(void) #if NETSTACK_CONF_WITH_IPV6 memcpy(addr.u8, mac_addr, sizeof(addr.u8)); #else - if(node_id == 0) { - int i; - for(i = 0; i < sizeof(linkaddr_t); ++i) { - addr.u8[i] = mac_addr[7 - i]; - } - } else { - addr.u8[0] = node_id & 0xff; - addr.u8[1] = node_id >> 8; + int i; + for(i = 0; i < sizeof(linkaddr_t); ++i) { + addr.u8[i] = mac_addr[7 - i]; } #endif linkaddr_set_node_addr(&addr); diff --git a/arch/platform/sky/Makefile.common b/arch/platform/sky/Makefile.common index 3d688b573..c8de6d6ad 100644 --- a/arch/platform/sky/Makefile.common +++ b/arch/platform/sky/Makefile.common @@ -1,6 +1,6 @@ # $Id: Makefile.common,v 1.3 2010/08/24 16:24:11 joxe Exp $ -ARCH=spi-legacy.c ds2411.c xmem.c i2c.c node-id.c sensors.c cfs-coffee.c \ +ARCH=spi-legacy.c ds2411.c xmem.c i2c.c sensors.c cfs-coffee.c \ cc2420.c cc2420-arch.c cc2420-arch-sfd.c \ sky-sensors.c uip-ipchksum.c \ uart1.c slip_uart1.c uart1-putchar.c platform.c diff --git a/arch/platform/sky/platform.c b/arch/platform/sky/platform.c index deaa53b5a..670e5443d 100644 --- a/arch/platform/sky/platform.c +++ b/arch/platform/sky/platform.c @@ -103,14 +103,9 @@ set_lladdr(void) #if NETSTACK_CONF_WITH_IPV6 memcpy(addr.u8, ds2411_id, sizeof(addr.u8)); #else - if(node_id == 0) { - int i; - for(i = 0; i < sizeof(linkaddr_t); ++i) { - addr.u8[i] = ds2411_id[7 - i]; - } - } else { - addr.u8[0] = node_id & 0xff; - addr.u8[1] = node_id >> 8; + int i; + for(i = 0; i < sizeof(linkaddr_t); ++i) { + addr.u8[i] = ds2411_id[7 - i]; } #endif linkaddr_set_node_addr(&addr); @@ -153,23 +148,7 @@ platform_init_stage_two(void) * Hardware initialization done! */ -#if WITH_TINYOS_AUTO_IDS - node_id = TOS_NODE_ID; -#else /* WITH_TINYOS_AUTO_IDS */ - /* Restore node id if such has been stored in external mem */ - node_id_restore(); -#endif /* WITH_TINYOS_AUTO_IDS */ - - /* for setting "hardcoded" IEEE 802.15.4 MAC addresses */ -#ifdef IEEE_802154_MAC_ADDRESS - { - uint8_t ieee[] = IEEE_802154_MAC_ADDRESS; - memcpy(ds2411_id, ieee, sizeof(uip_lladdr.addr)); - ds2411_id[7] = node_id & 0xff; - } -#endif - - random_init(ds2411_id[0] + node_id); + random_init(ds2411_id[0]); leds_off(LEDS_BLUE); @@ -198,12 +177,6 @@ platform_init_stage_three(void) cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); - if(node_id > 0) { - LOG_INFO("Node id: %u\n", node_id); - } else { - LOG_INFO("Node id: N/A\n"); - } - LOG_INFO("CC2420 CCA threshold %i\n", CC2420_CONF_CCA_THRESH); #if !NETSTACK_CONF_WITH_IPV6 diff --git a/arch/platform/srf06-cc26xx/platform.c b/arch/platform/srf06-cc26xx/platform.c index 362b9614e..d71e597f1 100644 --- a/arch/platform/srf06-cc26xx/platform.c +++ b/arch/platform/srf06-cc26xx/platform.c @@ -81,8 +81,6 @@ #define LOG_MODULE "CC26xx/CC13xx" #define LOG_LEVEL LOG_LEVEL_MAIN /*---------------------------------------------------------------------------*/ -unsigned short node_id = 0; -/*---------------------------------------------------------------------------*/ /** \brief Board specific iniatialisation */ void board_init(void); /*---------------------------------------------------------------------------*/ @@ -130,9 +128,6 @@ set_rf_params(void) NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, IEEE802154_DEFAULT_CHANNEL); NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8); - - /* also set the global node id */ - node_id = short_addr; #endif } /*---------------------------------------------------------------------------*/ @@ -227,8 +222,6 @@ platform_init_stage_three() } LOG_INFO_("\n"); - LOG_INFO(" Node ID: %d\n", node_id); - #if BOARD_HAS_SENSORS process_start(&sensors_process, NULL); #endif diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h b/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h index 7da0e9458..dda3e46e5 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h @@ -149,8 +149,13 @@ #define EXT_FLASH_SPI_PIN_MISO 18 #define EXT_FLASH_SPI_PIN_CS 14 +#if SENSORTAG_CC2650_REV_1_2_0 +#define EXT_FLASH_DEVICE_ID 0x12 +#define EXT_FLASH_MID 0xEF +#else #define EXT_FLASH_DEVICE_ID 0x14 #define EXT_FLASH_MID 0xC2 +#endif #define EXT_FLASH_PROGRAM_PAGE_SIZE 256 #define EXT_FLASH_ERASE_SECTOR_SIZE 4096 diff --git a/examples/6tisch/etsi-plugtest-2017/node.c b/examples/6tisch/etsi-plugtest-2017/node.c index 3046bb291..32d0429c0 100644 --- a/examples/6tisch/etsi-plugtest-2017/node.c +++ b/examples/6tisch/etsi-plugtest-2017/node.c @@ -37,7 +37,7 @@ */ #include "contiki.h" -#include "node-id.h" +#include "sys/node-id.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" diff --git a/examples/6tisch/simple-node/node.c b/examples/6tisch/simple-node/node.c index d2f75ae33..381d81f8e 100644 --- a/examples/6tisch/simple-node/node.c +++ b/examples/6tisch/simple-node/node.c @@ -37,7 +37,7 @@ */ #include "contiki.h" -#include "node-id.h" +#include "sys/node-id.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" #include "net/ipv6/uip-sr.h" diff --git a/examples/6tisch/sixtop/node-sixtop.c b/examples/6tisch/sixtop/node-sixtop.c index 67bee378a..e2dfe08c2 100755 --- a/examples/6tisch/sixtop/node-sixtop.c +++ b/examples/6tisch/sixtop/node-sixtop.c @@ -38,7 +38,7 @@ */ #include "contiki.h" -#include "node-id.h" +#include "sys/node-id.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" diff --git a/examples/libs/shell/Makefile b/examples/libs/shell/Makefile new file mode 100644 index 000000000..b44069cf8 --- /dev/null +++ b/examples/libs/shell/Makefile @@ -0,0 +1,6 @@ +CONTIKI_PROJECT = example +all: $(CONTIKI_PROJECT) + +MODULES += os/services/shell +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/libs/shell/README.md b/examples/libs/shell/README.md new file mode 100644 index 000000000..a76aa8c05 --- /dev/null +++ b/examples/libs/shell/README.md @@ -0,0 +1 @@ +This is a minimal example for the shell. diff --git a/arch/platform/jn516x/dev/node-id.c b/examples/libs/shell/example.c similarity index 80% rename from arch/platform/jn516x/dev/node-id.c rename to examples/libs/shell/example.c index c29aa8282..9d2320c58 100644 --- a/arch/platform/jn516x/dev/node-id.c +++ b/examples/libs/shell/example.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, SICS Swedish ICT. + * Copyright (c) 2018, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,30 +32,25 @@ /** * \file - * For compatibility with Contiki node-id interface - * + * A very simple example using the shell * \author - * Beshr Al Nahas + * Simon Duquennoy */ #include "contiki.h" -#include "sys/node-id.h" -#include "contiki.h" +#include /* For printf() */ /*---------------------------------------------------------------------------*/ -extern unsigned char node_mac[8]; -unsigned short node_id = 0; +PROCESS(example_process, "Example process: shell"); +AUTOSTART_PROCESSES(&example_process); /*---------------------------------------------------------------------------*/ -void -node_id_restore(void) +PROCESS_THREAD(example_process, ev, data) { - /* base node-id on MAC address */ - node_id = (node_mac[6] << 8) | node_mac[7]; + PROCESS_BEGIN(); + + /* This process does nothing. Connect to the node with `make login` + * to use the shell. */ + + PROCESS_END(); } /*---------------------------------------------------------------------------*/ -void -node_id_burn(unsigned short id) -{ - /* does not burn anything */ - node_id = id; -} diff --git a/examples/libs/simple-energest/Makefile b/examples/libs/simple-energest/Makefile new file mode 100644 index 000000000..056aa5c43 --- /dev/null +++ b/examples/libs/simple-energest/Makefile @@ -0,0 +1,6 @@ +CONTIKI_PROJECT = example +all: $(CONTIKI_PROJECT) + +MODULES += os/services/simple-energest +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/libs/simple-energest/README.md b/examples/libs/simple-energest/README.md new file mode 100644 index 000000000..42e382b5f --- /dev/null +++ b/examples/libs/simple-energest/README.md @@ -0,0 +1 @@ +This is a minimal example for the module simple-energest. diff --git a/arch/platform/sky/node-id.c b/examples/libs/simple-energest/example.c similarity index 73% rename from arch/platform/sky/node-id.c rename to examples/libs/simple-energest/example.c index ce6f68f85..e9d6d585c 100644 --- a/arch/platform/sky/node-id.c +++ b/examples/libs/simple-energest/example.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Swedish Institute of Computer Science. + * Copyright (c) 2018, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,40 +32,25 @@ /** * \file - * Utility to store a node id in the external flash + * A very simple example of simple-energest * \author - * Adam Dunkels + * Simon Duquennoy */ -#include "sys/node-id.h" #include "contiki.h" -#include "dev/xmem.h" - -unsigned short node_id = 0; +#include /* For printf() */ /*---------------------------------------------------------------------------*/ -void -node_id_restore(void) +PROCESS(example_process, "Example process: simple-energest"); +AUTOSTART_PROCESSES(&example_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(example_process, ev, data) { - unsigned char buf[4]; - xmem_pread(buf, 4, NODE_ID_XMEM_OFFSET); - if(buf[0] == 0xad && - buf[1] == 0xde) { - node_id = (buf[2] << 8) | buf[3]; - } else { - node_id = 0; - } -} -/*---------------------------------------------------------------------------*/ -void -node_id_burn(unsigned short id) -{ - unsigned char buf[4]; - buf[0] = 0xad; - buf[1] = 0xde; - buf[2] = id >> 8; - buf[3] = id & 0xff; - xmem_erase(XMEM_ERASE_UNIT_SIZE, NODE_ID_XMEM_OFFSET); - xmem_pwrite(buf, 4, NODE_ID_XMEM_OFFSET); + PROCESS_BEGIN(); + + /* Do nothing, just let simple-energest write its summary + * at a period of SIMPLE_ENERGEST_CONF_PERIOD */ + + PROCESS_END(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/lwm2m-ipso-objects/Makefile b/examples/lwm2m-ipso-objects/Makefile index 7fa79d1ee..c2cef2cfd 100644 --- a/examples/lwm2m-ipso-objects/Makefile +++ b/examples/lwm2m-ipso-objects/Makefile @@ -11,4 +11,7 @@ MODULES += os/services/lwm2m MODULES += os/services/ipso-objects CONTIKI=../.. +include $(CONTIKI)/Makefile.identify-target +MODULES_REL += $(TARGET) + include $(CONTIKI)/Makefile.include diff --git a/examples/lwm2m-ipso-objects/project-conf.h b/examples/lwm2m-ipso-objects/project-conf.h index a7ad8b3ea..01f919866 100644 --- a/examples/lwm2m-ipso-objects/project-conf.h +++ b/examples/lwm2m-ipso-objects/project-conf.h @@ -30,9 +30,6 @@ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ -/* No sleep on CC2538 to enable full 32 KiB RAM */ -#define LPM_CONF_ENABLE 0 - #ifdef BOARD_STRING #define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING #elif defined(CONTIKI_TARGET_WISMOTE) @@ -62,4 +59,12 @@ /* Enable client-side support for COAP observe */ #define COAP_OBSERVE_CLIENT 1 +/* Definitions to enable Queue Mode, include the dynamic adaptation and change the default parameters */ +/* #define LWM2M_QUEUE_MODE_CONF_ENABLED 1 + #define LWM2M_QUEUE_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION 1 + #define LWM2M_QUEUE_MODE_CONF_DEFAULT_CLIENT_AWAKE_TIME 2000 + #define LWM2M_QUEUE_MODE_CONF_DEFAULT_CLIENT_SLEEP_TIME 10000 + #define LWM2M_QUEUE_MODE_CONF_DEFAULT_DYNAMIC_ADAPTATION_FLAG 1 + #define LWM2M_QUEUE_MODE_OBJECT_CONF_ENABLED 0 */ + #endif /* PROJECT_CONF_H_ */ diff --git a/examples/lwm2m-ipso-objects/zoul/module-macros.h b/examples/lwm2m-ipso-objects/zoul/module-macros.h new file mode 100644 index 000000000..4db4e82fe --- /dev/null +++ b/examples/lwm2m-ipso-objects/zoul/module-macros.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018, RISE SICS AB. + * 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 HOLDER 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. + */ +/*---------------------------------------------------------------------------*/ +/* Only sleep mode 1 on Zoul to enable full 32 KiB RAM */ +#define LPM_CONF_MAX_PM 1 +/*---------------------------------------------------------------------------*/ +/* Macros to enter sleep mode and wake up in the Zoul module. Sleep consists + * on turn off the radio and start a RTIMER to wake up, and wake up consists on + * turn on the radio again + */ +#define LWM2M_Q_MODE_WAKE_UP() do { \ + NETSTACK_MAC.on(); \ +} while(0) + +#define LWM2M_Q_MODE_SLEEP_MS(TIME_MS) do { \ + uint64_t aux = TIME_MS * RTIMER_SECOND; \ + NETSTACK_MAC.off(); \ + rtimer_arch_schedule(RTIMER_NOW() + (rtimer_clock_t)(aux / 1000)); \ +} while(0) + + diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md b/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md index 9a4617b3c..912fcb72a 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md @@ -10,11 +10,17 @@ demonstrate the CC26xx capability. The applications are: * A web server which can be used to display sensor readings but also to configure MQTT functionality -The example has been configured to run for all CC26xx-based boards: i) The -SensorTag 2.0 and ii) The Srf06EB with a CC26xx or CC13xx EM mounted on it. +The example has been configured to run for all CC26xx-based boards. -To change between target boards, follow the instructions in the platform's -REDME file. Do not forget to `make clean` when switching between the boards. +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, diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h b/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h index ccd0bf8fb..36114eeb7 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h @@ -53,6 +53,16 @@ */ #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 /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c index 42fa11fb7..df72b69b3 100644 --- a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c +++ b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c @@ -38,7 +38,7 @@ #include "net/routing/routing.h" #include "net/ipv6/uip-debug.h" #include "lib/random.h" -#include "node-id.h" +#include "sys/node-id.h" #include "waveform.h" #include "leds.h" #include "net/ipv6/uiplib.h" diff --git a/os/contiki-main.c b/os/contiki-main.c index b9aea5cd6..c756cf206 100644 --- a/os/contiki-main.c +++ b/os/contiki-main.c @@ -42,6 +42,7 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "contiki-net.h" +#include "sys/node-id.h" #include "sys/platform.h" #include "sys/energest.h" #include "sys/stack-check.h" @@ -51,6 +52,7 @@ #include "services/rpl-border-router/rpl-border-router.h" #include "services/orchestra/orchestra.h" #include "services/shell/serial-shell.h" +#include "services/simple-energest/simple-energest.h" #include #include @@ -86,6 +88,9 @@ main(void) platform_init_stage_two(); + netstack_init(); + node_id_init(); + LOG_INFO("Starting " CONTIKI_VERSION_STRING "\n"); LOG_INFO("- Routing: %s\n", NETSTACK_ROUTING.name); LOG_INFO("- Net: %s\n", NETSTACK_NETWORK.name); @@ -97,9 +102,8 @@ main(void) LOG_INFO("- 802.15.4 Default channel: %u\n", IEEE802154_DEFAULT_CHANNEL); #endif /* MAC_CONF_WITH_TSCH */ - netstack_init(); - - LOG_INFO("Link-layer address "); + LOG_INFO("Node ID: %u\n", node_id); + LOG_INFO("Link-layer address: "); LOG_INFO_LLADDR(&linkaddr_node_addr); LOG_INFO_("\n"); @@ -110,7 +114,7 @@ main(void) process_start(&tcpip_process, NULL); lladdr = uip_ds6_get_link_local(-1); - LOG_INFO("Tentative link-local IPv6 address "); + LOG_INFO("Tentative link-local IPv6 address: "); LOG_INFO_6ADDR(lladdr != NULL ? &lladdr->ipaddr : NULL); LOG_INFO_("\n"); } @@ -138,6 +142,10 @@ main(void) LOG_DBG("With CoAP\n"); #endif /* BUILD_WITH_SHELL */ +#if BUILD_WITH_SIMPLE_ENERGEST + simple_energest_init(); +#endif /* BUILD_WITH_SIMPLE_ENERGEST */ + autostart_start(autostart_processes); watchdog_start(); diff --git a/os/net/app-layer/coap/coap-callback-api.c b/os/net/app-layer/coap/coap-callback-api.c index b1b05597e..0f0ab2c99 100644 --- a/os/net/app-layer/coap/coap-callback-api.c +++ b/os/net/app-layer/coap/coap-callback-api.c @@ -65,7 +65,7 @@ static void coap_request_callback(void *callback_data, coap_message_t *response) /*---------------------------------------------------------------------------*/ -static void +static int progress_request(coap_request_state_t *state) { coap_message_t *request = state->request; request->mid = coap_get_mid(); @@ -83,7 +83,9 @@ progress_request(coap_request_state_t *state) { coap_send_transaction(state->transaction); LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid); + return 1; } + return 0; } /*---------------------------------------------------------------------------*/ @@ -134,7 +136,7 @@ coap_request_callback(void *callback_data, coap_message_t *response) /*---------------------------------------------------------------------------*/ -void +int coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, coap_message_t *request, void (*callback)(coap_request_state_t *state)) @@ -151,7 +153,7 @@ coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, state->remote_endpoint = endpoint; state->callback = callback; - progress_request(state); + return progress_request(state); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/net/app-layer/coap/coap-callback-api.h b/os/net/app-layer/coap/coap-callback-api.h index 6de7ab587..69ceea4f5 100644 --- a/os/net/app-layer/coap/coap-callback-api.h +++ b/os/net/app-layer/coap/coap-callback-api.h @@ -65,7 +65,15 @@ struct coap_request_state { void (*callback)(coap_request_state_t *state); }; -void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, +/** + * \brief Send a CoAP request to a remote endpoint + * \param state The state to handle the CoAP request + * \param endpoint The destination endpoint + * \param request The request to be sent + * \param callback callback to execute when the response arrives or the timeout expires + * \return 1 if there is a transaction available to send, 0 otherwise + */ +int coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, coap_message_t *request, void (*callback)(coap_request_state_t *state)); diff --git a/os/net/app-layer/coap/coap-observe.c b/os/net/app-layer/coap/coap-observe.c index 83f5edf4a..d6ef3887e 100644 --- a/os/net/app-layer/coap/coap-observe.c +++ b/os/net/app-layer/coap/coap-observe.c @@ -353,4 +353,18 @@ coap_observe_handler(coap_resource_t *resource, coap_message_t *coap_req, } } /*---------------------------------------------------------------------------*/ +uint8_t +coap_has_observers(char *path) +{ + coap_observer_t *obs = NULL; + + for(obs = (coap_observer_t *)list_head(observers_list); obs; + obs = obs->next) { + if((strncmp(obs->url, path, strlen(path))) == 0) { + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/net/app-layer/coap/coap-observe.h b/os/net/app-layer/coap/coap-observe.h index c276522c5..93898f954 100644 --- a/os/net/app-layer/coap/coap-observe.h +++ b/os/net/app-layer/coap/coap-observe.h @@ -80,5 +80,7 @@ void coap_notify_observers_sub(coap_resource_t *resource, const char *subpath); void coap_observe_handler(coap_resource_t *resource, coap_message_t *request, coap_message_t *response); +uint8_t coap_has_observers(char *path); + #endif /* COAP_OBSERVE_H_ */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 6f2aeefd8..0c4d9f5fd 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -39,6 +39,7 @@ * \author * Joakim Eriksson * Niclas Finne + * Carlos Gonzalo Peces */ #include "lwm2m-engine.h" @@ -56,7 +57,6 @@ #include #include #include - #ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME #include "net/ipv6/uip-ds6.h" #endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ @@ -80,10 +80,24 @@ #define USE_RD_CLIENT 1 #endif /* LWM2M_ENGINE_CONF_USE_RD_CLIENT */ + +#if LWM2M_QUEUE_MODE_ENABLED + /* Queue Mode is handled using the RD Client and the Q-Mode object */ +#define USE_RD_CLIENT 1 +#endif + #if USE_RD_CLIENT #include "lwm2m-rd-client.h" #endif +#if LWM2M_QUEUE_MODE_ENABLED +#include "lwm2m-queue-mode.h" +#include "lwm2m-notification-queue.h" +#if LWM2M_QUEUE_MODE_OBJECT_ENABLED +#include "lwm2m-queue-mode-object.h" +#endif /* LWM2M_QUEUE_MODE_OBJECT_ENABLED */ +#endif /* LWM2M_QUEUE_MODE_ENABLED */ + /* MACRO for getting out resource ID from resource array ID + flags */ #define RSC_ID(x) ((uint16_t)(x & 0xffff)) #define RSC_READABLE(x) ((x & LWM2M_RESOURCE_READ) > 0) @@ -129,7 +143,6 @@ static struct { /* in the future also a timeout */ } created; - COAP_HANDLER(lwm2m_handler, lwm2m_handler_callback); LIST(object_list); LIST(generic_object_list); @@ -554,6 +567,10 @@ lwm2m_engine_init(void) #if USE_RD_CLIENT lwm2m_rd_client_init(endpoint); #endif + +#if LWM2M_QUEUE_MODE_ENABLED && LWM2M_QUEUE_MODE_OBJECT_ENABLED + lwm2m_queue_mode_object_init(); +#endif } /*---------------------------------------------------------------------------*/ /* @@ -1373,6 +1390,10 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, context.inbuf->size = coap_get_payload(request, (const uint8_t **)&context.inbuf->buffer); context.inbuf->pos = 0; +#if LWM2M_QUEUE_MODE_ENABLED +lwm2m_queue_mode_request_received(); +#endif /* LWM2M_QUEUE_MODE_ENABLED */ + /* Maybe this should be part of CoAP itself - this seems not to be working with the leshan server */ #define LWM2M_CONF_ENTITY_TOO_LARGE_BLOCK1 0 @@ -1632,14 +1653,46 @@ lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, return COAP_HANDLER_STATUS_PROCESSED; } /*---------------------------------------------------------------------------*/ -void lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, +static void +lwm2m_send_notification(char* path) +{ +#if LWM2M_QUEUE_MODE_ENABLED && LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + if(lwm2m_queue_mode_get_dynamic_adaptation_flag()) { + lwm2m_queue_mode_set_handler_from_notification(); + } +#endif + coap_notify_observers_sub(NULL, path); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, uint16_t resource) { char path[20]; /* 60000/60000/60000 */ if(obj != NULL) { snprintf(path, 20, "%d/%d/%d", obj->object_id, obj->instance_id, resource); - coap_notify_observers_sub(NULL, path); } + +#if LWM2M_QUEUE_MODE_ENABLED + + if(coap_has_observers(path)) { + /* Client is sleeping -> add the notification to the list */ + if(!lwm2m_rd_client_is_client_awake()) { + lwm2m_notification_queue_add_notification_path(obj->object_id, obj->instance_id, resource); + + /* if it is the first notification -> wake up and send update */ + if(!lwm2m_queue_mode_is_waked_up_by_notification()) { + lwm2m_queue_mode_set_waked_up_by_notification(); + lwm2m_rd_client_fsm_execute_queue_mode_update(); + } + /* Client is awake -> send the notification */ + } else { + lwm2m_send_notification(path); + } + } +#else + lwm2m_send_notification(path); +#endif } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-engine.h b/os/services/lwm2m/lwm2m-engine.h index 62a667e99..0ca24fb90 100644 --- a/os/services/lwm2m/lwm2m-engine.h +++ b/os/services/lwm2m/lwm2m-engine.h @@ -39,12 +39,14 @@ * \author * Joakim Eriksson * Niclas Finne + * Carlos Gonzalo Peces */ #ifndef LWM2M_ENGINE_H #define LWM2M_ENGINE_H #include "lwm2m-object.h" +#include "lwm2m-queue-mode-conf.h" #define LWM2M_FLOAT32_BITS 10 #define LWM2M_FLOAT32_FRAC (1L << LWM2M_FLOAT32_BITS) @@ -114,6 +116,5 @@ void lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); - #endif /* LWM2M_ENGINE_H */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-notification-queue.c b/os/services/lwm2m/lwm2m-notification-queue.c new file mode 100644 index 000000000..c901bef82 --- /dev/null +++ b/os/services/lwm2m/lwm2m-notification-queue.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 HOLDER 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 lwm2m + * @{ + */ + +/** + * \file + * Implementation of functions to manage the queue to store notifications + when waiting for the response to the update message in Queue Mode. + * \author + * Carlos Gonzalo Peces + */ +/*---------------------------------------------------------------------------*/ +#include "lwm2m-notification-queue.h" + +#if LWM2M_QUEUE_MODE_ENABLED + +#include "lwm2m-queue-mode.h" +#include "lwm2m-engine.h" +#include "coap-engine.h" +#include "lib/memb.h" +#include "lib/list.h" +#include +#include +#include +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-notification-queue" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#ifdef LWM2M_NOTIFICATION_QUEUE_CONF_LENGTH +#define LWM2M_NOTIFICATION_QUEUE_LENGTH LWM2M_NOTIFICATION_QUEUE_CONF_LENGTH +#else +#define LWM2M_NOTIFICATION_QUEUE_LENGTH COAP_MAX_OBSERVERS +#endif + +/*---------------------------------------------------------------------------*/ +/* Queue to store the notifications in the period when the client has woken up, sent the update and it's waiting for the server response*/ +MEMB(notification_memb, notification_path_t, LWM2M_NOTIFICATION_QUEUE_LENGTH); /* Length + 1 to allocate the new path to add */ +LIST(notification_paths_queue); +/*---------------------------------------------------------------------------*/ +void +lwm2m_notification_queue_init(void) +{ + list_init(notification_paths_queue); +} +/*---------------------------------------------------------------------------*/ +static void +extend_path(notification_path_t *path_object, char *path, int path_size) +{ + switch(path_object->level) { + case 1: + snprintf(path, path_size, "%u", path_object->reduced_path[0]); + break; + case 2: + snprintf(path, path_size, "%u/%u", path_object->reduced_path[0], path_object->reduced_path[1]); + break; + case 3: + snprintf(path, path_size, "%u/%u/%u", path_object->reduced_path[0], path_object->reduced_path[1], path_object->reduced_path[2]); + break; + } +} +/*---------------------------------------------------------------------------*/ +static int +is_notification_path_present(uint16_t object_id, uint16_t instance_id, uint16_t resource_id) +{ + notification_path_t *iteration_path = (notification_path_t *)list_head(notification_paths_queue); + while(iteration_path != NULL) { + if(iteration_path->reduced_path[0] == object_id && iteration_path->reduced_path[1] == instance_id + && iteration_path->reduced_path[2] == resource_id) { + return 1; + } + iteration_path = iteration_path->next; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +remove_notification_path(notification_path_t *path) +{ + list_remove(notification_paths_queue, path); + memb_free(¬ification_memb, path); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_notification_queue_add_notification_path(uint16_t object_id, uint16_t instance_id, uint16_t resource_id) +{ + if(is_notification_path_present(object_id, instance_id, resource_id)) { + LOG_DBG("Notification path already present, not queueing it\n"); + return; + } + notification_path_t *path_object = memb_alloc(¬ification_memb); + if(path_object == NULL) { + LOG_DBG("Queue is full, could not allocate new notification\n"); + return; + } + path_object->reduced_path[0] = object_id; + path_object->reduced_path[1] = instance_id; + path_object->reduced_path[2] = resource_id; + path_object->level = 3; + list_add(notification_paths_queue, path_object); + LOG_DBG("Notification path added to the list: %u/%u/%u\n", object_id, instance_id, resource_id); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_notification_queue_send_notifications() +{ + char path[20]; + notification_path_t *iteration_path = (notification_path_t *)list_head(notification_paths_queue); + notification_path_t *aux = iteration_path; + + while(iteration_path != NULL) { + extend_path(iteration_path, path, sizeof(path)); +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + if(lwm2m_queue_mode_get_dynamic_adaptation_flag()) { + lwm2m_queue_mode_set_handler_from_notification(); + } +#endif + LOG_DBG("Sending stored notification with path: %s\n", path); + coap_notify_observers_sub(NULL, path); + aux = iteration_path; + iteration_path = iteration_path->next; + remove_notification_path(aux); + } +} +#endif /* LWM2M_QUEUE_MODE_ENABLED */ +/** @} */ \ No newline at end of file diff --git a/os/services/lwm2m/lwm2m-notification-queue.h b/os/services/lwm2m/lwm2m-notification-queue.h new file mode 100644 index 000000000..e3f4719ac --- /dev/null +++ b/os/services/lwm2m/lwm2m-notification-queue.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 HOLDER 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 lwm2m + * @{ + */ + +/** + * \file + * Header file for functions to manage the queue to store notifications + when waiting for the response to the update message in Queue Mode. + * \author + * Carlos Gonzalo Peces + */ + +#ifndef LWM2M_NOTIFICATION_QUEUE_H +#define LWM2M_NOTIFICATION_QUEUE_H + +#include "contiki.h" +#include "lwm2m-queue-mode-conf.h" + +#include + +typedef struct notification_path { + struct notification_path *next; + uint16_t reduced_path[3]; + uint8_t level; /* The depth level of the path: 1. object, 2. object/instance, 3. object/instance/resource */ +} notification_path_t; + +void lwm2m_notification_queue_init(void); + +void lwm2m_notification_queue_add_notification_path(uint16_t object_id, uint16_t instance_id, uint16_t resource_id); + +void lwm2m_notification_queue_send_notifications(); + +#endif /* LWM2M_NOTIFICATION_QUEUE_H */ +/** @} */ \ No newline at end of file diff --git a/os/services/lwm2m/lwm2m-queue-mode-conf.h b/os/services/lwm2m/lwm2m-queue-mode-conf.h new file mode 100644 index 000000000..3432c112a --- /dev/null +++ b/os/services/lwm2m/lwm2m-queue-mode-conf.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 HOLDER 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 lwm2m + * @{ + */ + +/** + * \file + * Queue Mode Configuration Parameters + * \author + * Carlos Gonzalo Peces + */ + +#ifndef LWM2M_QUEUE_MODE_CONF_H +#define LWM2M_QUEUE_MODE_CONF_H + +#include "contiki.h" + +/* Enable the Queue Mode */ +#ifdef LWM2M_QUEUE_MODE_CONF_ENABLED +#define LWM2M_QUEUE_MODE_ENABLED LWM2M_QUEUE_MODE_CONF_ENABLED +#else +#define LWM2M_QUEUE_MODE_ENABLED 0 +#endif /* LWM2M_QUEUE_MODE_CONF_ENABLED */ + +/* Default Sleeping Time */ +#ifdef LWM2M_QUEUE_MODE_CONF_DEFAULT_CLIENT_SLEEP_TIME +#define LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEP_TIME LWM2M_QUEUE_MODE_CONF_DEFAULT_CLIENT_SLEEP_TIME +#else +#define LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEP_TIME 10000 /* msec */ +#endif /* LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEPING_TIME */ + +/* Default Awake Time */ +#ifdef LWM2M_QUEUE_MODE_CONF_DEFAULT_CLIENT_AWAKE_TIME +#define LWM2M_QUEUE_MODE_DEFAULT_CLIENT_AWAKE_TIME LWM2M_QUEUE_MODE_CONF_DEFAULT_CLIENT_AWAKE_TIME +#else +#define LWM2M_QUEUE_MODE_DEFAULT_CLIENT_AWAKE_TIME 5000 /* msec */ +#endif /* LWM2M_QUEUE_MODE_DEFAULT_CLIENT_AWAKE_TIME */ + +/* Include the possibility to do the dynamic adaptation of the client awake time */ +#ifdef LWM2M_QUEUE_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION +#define LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION LWM2M_QUEUE_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION +#else +#define LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION 0 /* not included */ +#endif /* LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION */ + +/* Default value for the dynamic adaptation flag */ +#ifdef LWM2M_QUEUE_MODE_CONF_DEFAULT_DYNAMIC_ADAPTATION_FLAG +#define LWM2M_QUEUE_MODE_DEFAULT_DYNAMIC_ADAPTATION_FLAG LWM2M_QUEUE_MODE_CONF_DEFAULT_DYNAMIC_ADAPTATION_FLAG +#else +#define LWM2M_QUEUE_MODE_DEFAULT_DYNAMIC_ADAPTATION_FLAG 0 /* disabled */ +#endif /* LWM2M_QUEUE_MODE_DEFAULT_DYNAMIC_ADAPTATION_FLAG */ + +/* Length of the list of times for the dynamic adaptation */ +#define LWM2M_QUEUE_MODE_DYNAMIC_ADAPTATION_WINDOW_LENGTH 10 + +/* Enable and disable the Queue Mode Object */ +#ifdef LWM2M_QUEUE_MODE_OBJECT_CONF_ENABLED +#define LWM2M_QUEUE_MODE_OBJECT_ENABLED LWM2M_QUEUE_MODE_OBJECT_CONF_ENABLED +#else +#define LWM2M_QUEUE_MODE_OBJECT_ENABLED 0 /* not included */ +#endif /* LWM2M_QUEUE_MODE_OBJECT_ENABLED */ + + + +#endif /* LWM2M_QUEUE_MODE_CONF_H */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-queue-mode-object.c b/os/services/lwm2m/lwm2m-queue-mode-object.c new file mode 100644 index 000000000..a3c000d69 --- /dev/null +++ b/os/services/lwm2m/lwm2m-queue-mode-object.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 HOLDER 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 lwm2m + * @{ + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M Queue Mode object + to manage the parameters from the server side + * \author + * Carlos Gonzalo Peces + */ + +#include "lwm2m-object.h" +#include "lwm2m-queue-mode.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-qmode-object" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#if LWM2M_QUEUE_MODE_ENABLED && LWM2M_QUEUE_MODE_OBJECT_ENABLED + +#define LWM2M_QUEUE_MODE_OBJECT_ID 30000 +#define LWM2M_AWAKE_TIME_ID 30000 +#define LWM2M_SLEEP_TIME_ID 30001 + +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION +#define LWM2M_DYNAMIC_ADAPTATION_FLAG_ID 30002 +#define UPDATE_WITH_MEAN 0 /* 1-mean time 0-maximum time */ +#endif + +static const lwm2m_resource_id_t resources[] = +{ RW(LWM2M_AWAKE_TIME_ID), + RW(LWM2M_SLEEP_TIME_ID), +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + RW(LWM2M_DYNAMIC_ADAPTATION_FLAG_ID), +#endif +}; + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) +{ + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_AWAKE_TIME_ID: + lwm2m_object_write_int(ctx, (int32_t)lwm2m_queue_mode_get_awake_time()); + return LWM2M_STATUS_OK; + case LWM2M_SLEEP_TIME_ID: + lwm2m_object_write_int(ctx, (int32_t)lwm2m_queue_mode_get_sleep_time()); + return LWM2M_STATUS_OK; +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + case LWM2M_DYNAMIC_ADAPTATION_FLAG_ID: + lwm2m_object_write_int(ctx, (int32_t)lwm2m_queue_mode_get_dynamic_adaptation_flag()); + return LWM2M_STATUS_OK; +#endif + } + } else if(ctx->operation == LWM2M_OP_WRITE) { + switch(ctx->resource_id) { + int32_t value_read; + size_t len; + + case LWM2M_AWAKE_TIME_ID: + + len = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, + &value_read); + LOG_DBG("Client Awake Time write request value: %d\n", (int)value_read); + if(len == 0) { + LOG_WARN("FAIL: could not write awake time\n"); + return LWM2M_STATUS_WRITE_ERROR; + } else { + lwm2m_queue_mode_set_awake_time(value_read); + return LWM2M_STATUS_OK; + } + + case LWM2M_SLEEP_TIME_ID: + len = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, + &value_read); + LOG_DBG("Client Sleep Time write request value: %d\n", (int)value_read); + if(len == 0) { + LOG_WARN("FAIL: could not write sleep time\n"); + return LWM2M_STATUS_WRITE_ERROR; + } else { + lwm2m_queue_mode_set_sleep_time(value_read); + return LWM2M_STATUS_OK; + } +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + case LWM2M_DYNAMIC_ADAPTATION_FLAG_ID: + len = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, + &value_read); + LOG_DBG("Dynamic Adaptation Flag request value: %d\n", (int)value_read); + if(len == 0) { + LOG_WARN("FAIL: could not write dynamic flag\n"); + return LWM2M_STATUS_WRITE_ERROR; + } else { + lwm2m_queue_mode_set_dynamic_adaptation_flag(value_read); + return LWM2M_STATUS_OK; + } +#endif + } + } + + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t queue_object = { + .object_id = LWM2M_QUEUE_MODE_OBJECT_ID, + .instance_id = 0, + .resource_ids = resources, + .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t), + .resource_dim_callback = NULL, + .callback = lwm2m_callback, +}; +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_object_init(void) +{ + lwm2m_engine_add_object(&queue_object); +} +#endif /* LWM2M_QUEUE_MODE_ENABLED && LWM2M_QUEUE_MODE_OBJECT_ENABLED */ +/** @} */ \ No newline at end of file diff --git a/os/services/lwm2m/lwm2m-queue-mode-object.h b/os/services/lwm2m/lwm2m-queue-mode-object.h new file mode 100644 index 000000000..017b797fc --- /dev/null +++ b/os/services/lwm2m/lwm2m-queue-mode-object.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 HOLDER 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 oma-lwm2m + * @{ + */ + +/** + * \file + * Header file for the Contiki OMA LWM2M Queue Mode object + to manage the parameters from the server side + * \author + * Carlos Gonzalo Peces + */ + +#ifndef LWM2M_QUEUE_MODE_OBJECT_H_ +#define LWM2M_QUEUE_MODE_OBJECT_H_ + +#include "lwm2m-queue-mode-conf.h" + +void lwm2m_queue_mode_object_init(void); + +#endif /* LWM2M_Q_OBJECT_H_ */ +/** @} */ \ No newline at end of file diff --git a/os/services/lwm2m/lwm2m-queue-mode.c b/os/services/lwm2m/lwm2m-queue-mode.c new file mode 100644 index 000000000..aad80ce3e --- /dev/null +++ b/os/services/lwm2m/lwm2m-queue-mode.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 HOLDER 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 lwm2m + * @{ + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M Queue Mode for managing the parameters + * \author + * Carlos Gonzalo Peces + */ + +#include "lwm2m-queue-mode.h" + +#if LWM2M_QUEUE_MODE_ENABLED + +#include "lwm2m-engine.h" +#include "lwm2m-rd-client.h" +#include "lib/memb.h" +#include "lib/list.h" +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-queue-mode" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +/* Queue Mode dynamic adaptation masks */ +#define FIRST_REQUEST_MASK 0x01 +#define HANDLER_FROM_NOTIFICATION_MASK 0x02 + +static uint16_t queue_mode_awake_time = LWM2M_QUEUE_MODE_DEFAULT_CLIENT_AWAKE_TIME; +static uint32_t queue_mode_sleep_time = LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEP_TIME; + +/* Flag for notifications */ +static uint8_t waked_up_by_notification; + +/* For the dynamic adaptation of the awake time */ +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION +static uint8_t queue_mode_dynamic_adaptation_flag = LWM2M_QUEUE_MODE_DEFAULT_DYNAMIC_ADAPTATION_FLAG; + +/* Window to save the times and do the dynamic adaptation of the awake time*/ +uint16_t times_window[LWM2M_QUEUE_MODE_DYNAMIC_ADAPTATION_WINDOW_LENGTH] = { 0 }; +uint8_t times_window_index = 0; +static uint8_t dynamic_adaptation_params = 0x00; /* bit0: first_request, bit1: handler from notification */ +static uint64_t previous_request_time; +static inline void clear_first_request(); +static inline uint8_t is_first_request(); +static inline void clear_handler_from_notification(); +static inline uint8_t get_handler_from_notification(); +#endif /* LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION */ +/*---------------------------------------------------------------------------*/ +uint16_t +lwm2m_queue_mode_get_awake_time() +{ + LOG_DBG("Client Awake Time: %d ms\n", (int)queue_mode_awake_time); + return queue_mode_awake_time; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_set_awake_time(uint16_t time) +{ + queue_mode_awake_time = time; +} +/*---------------------------------------------------------------------------*/ +uint32_t +lwm2m_queue_mode_get_sleep_time() +{ + LOG_DBG("Client Sleep Time: %d ms\n", (int)queue_mode_sleep_time); + return queue_mode_sleep_time; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_set_sleep_time(uint32_t time) +{ + queue_mode_sleep_time = time; +} +/*---------------------------------------------------------------------------*/ +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION +uint8_t +lwm2m_queue_mode_get_dynamic_adaptation_flag() +{ + LOG_DBG("Dynamic Adaptation Flag: %d ms\n", (int)queue_mode_dynamic_adaptation_flag); + return queue_mode_dynamic_adaptation_flag; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_set_dynamic_adaptation_flag(uint8_t flag) +{ + queue_mode_dynamic_adaptation_flag = flag; +} +#endif +/*---------------------------------------------------------------------------*/ +#if !UPDATE_WITH_MEAN +static uint16_t +get_maximum_time() +{ + uint16_t max_time = 0; + uint8_t i; + for(i = 0; i < LWM2M_QUEUE_MODE_DYNAMIC_ADAPTATION_WINDOW_LENGTH; i++) { + if(times_window[i] > max_time) { + max_time = times_window[i]; + } + } + return max_time; +} +#endif +/*---------------------------------------------------------------------------*/ +#if UPDATE_WITH_MEAN +static uint16_t +get_mean_time() +{ + uint16_t mean_time = 0; + uint8_t i; + for(i = 0; i < LWM2M_QUEUE_MODE_DYNAMIC_ADAPTATION_WINDOW_LENGTH; i++) { + if(mean_time == 0) { + mean_time = times_window[i]; + } else { + if(times_window[i] != 0) { + mean_time = (mean_time + times_window[i]) / 2; + } + } + } + return mean_time; +} +#endif +/*---------------------------------------------------------------------------*/ +static void +update_awake_time() +{ +#if UPDATE_WITH_MEAN + uint16_t mean_time = get_mean_time(); + LOG_DBG("Dynamic Adaptation: updated awake time: %d ms\n", (int)mean_time); + lwm2m_queue_mode_set_awake_time(mean_time + (mean_time >> 1)); /* 50% margin */ + return; +#else + uint16_t max_time = get_maximum_time(); + LOG_DBG("Dynamic Adaptation: updated awake time: %d ms\n", (int)max_time); + lwm2m_queue_mode_set_awake_time(max_time + (max_time >> 1)); /* 50% margin */ + return; +#endif +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_add_time_to_window(uint16_t time) +{ + if(times_window_index == LWM2M_QUEUE_MODE_DYNAMIC_ADAPTATION_WINDOW_LENGTH) { + times_window_index = 0; + } + times_window[times_window_index] = time; + times_window_index++; + update_awake_time(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +lwm2m_queue_mode_is_waked_up_by_notification() +{ + return waked_up_by_notification; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_clear_waked_up_by_notification() +{ + waked_up_by_notification = 0; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_set_waked_up_by_notification() +{ + waked_up_by_notification = 1; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_request_received() +{ + if(lwm2m_rd_client_is_client_awake()) { + lwm2m_rd_client_restart_client_awake_timer(); + } +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + if(lwm2m_queue_mode_get_dynamic_adaptation_flag() && !get_handler_from_notification()) { + if(is_first_request()) { + previous_request_time = coap_timer_uptime(); + clear_first_request(); + } else { + if(coap_timer_uptime() - previous_request_time >= 0) { + if(coap_timer_uptime() - previous_request_time > 0xffff) { + lwm2m_queue_mode_add_time_to_window(0xffff); + } else { + lwm2m_queue_mode_add_time_to_window(coap_timer_uptime() - previous_request_time); + } + } + previous_request_time = coap_timer_uptime(); + } + } + if(get_handler_from_notification()) { + clear_handler_from_notification(); + } +#endif /* LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION */ +} +/*---------------------------------------------------------------------------*/ +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION +void +lwm2m_queue_mode_set_first_request() +{ + dynamic_adaptation_params |= FIRST_REQUEST_MASK; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_queue_mode_set_handler_from_notification() +{ + dynamic_adaptation_params |= HANDLER_FROM_NOTIFICATION_MASK; +} +/*---------------------------------------------------------------------------*/ +static inline uint8_t +is_first_request() +{ + return dynamic_adaptation_params & FIRST_REQUEST_MASK; +} +/*---------------------------------------------------------------------------*/ +static inline uint8_t +get_handler_from_notification() +{ + return (dynamic_adaptation_params & HANDLER_FROM_NOTIFICATION_MASK) != 0; +} +/*---------------------------------------------------------------------------*/ +static inline void +clear_first_request() +{ + dynamic_adaptation_params &= ~FIRST_REQUEST_MASK; +} +/*---------------------------------------------------------------------------*/ +static inline void +clear_handler_from_notification() +{ + dynamic_adaptation_params &= ~HANDLER_FROM_NOTIFICATION_MASK; +} +#endif /* LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION */ +#endif /* LWM2M_QUEUE_MODE_ENABLED */ +/** @} */ + diff --git a/os/services/lwm2m/lwm2m-queue-mode.h b/os/services/lwm2m/lwm2m-queue-mode.h new file mode 100644 index 000000000..5c65face5 --- /dev/null +++ b/os/services/lwm2m/lwm2m-queue-mode.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * 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 HOLDER 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 oma-lwm2m + * @{ + */ + +/** + * \file + * Header file for the Contiki OMA LWM2M Queue Mode implementation + to manage the parameters + * \author + * Carlos Gonzalo Peces + */ + +#ifndef LWM2M_QUEUE_MODE_H_ +#define LWM2M_QUEUE_MODE_H_ + +#include "lwm2m-queue-mode-conf.h" +#include + +uint16_t lwm2m_queue_mode_get_awake_time(); +void lwm2m_queue_mode_set_awake_time(uint16_t time); +uint32_t lwm2m_queue_mode_get_sleep_time(); +void lwm2m_queue_mode_set_sleep_time(uint32_t time); + +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION +uint8_t lwm2m_queue_mode_get_dynamic_adaptation_flag(); +void lwm2m_queue_mode_set_dynamic_adaptation_flag(uint8_t flag); +void lwm2m_queue_mode_add_time_to_window(uint16_t time); +#endif + +uint8_t lwm2m_queue_mode_is_waked_up_by_notification(); +void lwm2m_queue_mode_clear_waked_up_by_notification(); +void lwm2m_queue_mode_set_waked_up_by_notification(); + +void lwm2m_queue_mode_set_first_request(); +void lwm2m_queue_mode_set_handler_from_notification(); + +void lwm2m_queue_mode_request_received(); + +#endif /* LWM2M_QUEUE_MODE_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c index 03d21e33e..63c9443e1 100644 --- a/os/services/lwm2m/lwm2m-rd-client.c +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -41,8 +41,8 @@ * Joakim Eriksson * Niclas Finne * Joel Hoglund + * Carlos Gonzalo Peces */ - #include "lwm2m-engine.h" #include "lwm2m-object.h" #include "lwm2m-device.h" @@ -62,6 +62,11 @@ #include "rpl.h" #endif /* UIP_CONF_IPV6_RPL */ +#if LWM2M_QUEUE_MODE_ENABLED +#include "lwm2m-queue-mode.h" +#include "lwm2m-notification-queue.h" +#endif /* LWM2M_QUEUE_MODE_ENABLED */ + /* Log configuration */ #include "coap-log.h" #define LOG_MODULE "lwm2m-rd" @@ -100,6 +105,10 @@ static coap_message_t request[1]; /* This way the message can be treated as #define DEREGISTER_SENT 11 #define DEREGISTER_FAILED 12 #define DEREGISTERED 13 +#if LWM2M_QUEUE_MODE_ENABLED +#define QUEUE_MODE_AWAKE 14 +#define QUEUE_MODE_SEND_UPDATE 15 +#endif #define FLAG_RD_DATA_DIRTY 0x01 #define FLAG_RD_DATA_UPDATE_TRIGGERED 0x02 @@ -121,6 +130,18 @@ static void (*rd_callback)(coap_request_state_t *state); static coap_timer_t block1_timer; +#if LWM2M_QUEUE_MODE_ENABLED +static coap_timer_t queue_mode_client_awake_timer; /* Timer to control the client's + * awake time + */ +static uint8_t queue_mode_client_awake; /* 1 - client is awake, + * 0 - client is sleeping + */ +static uint16_t queue_mode_client_awake_time; /* The time to be awake */ +/* Callback for the client awake timer */ +static void queue_mode_awake_timer_callback(coap_timer_t *timer); +#endif + static void check_periodic_observations(); static void update_callback(coap_request_state_t *state); @@ -147,7 +168,8 @@ set_rd_data(coap_message_t *request) } /*---------------------------------------------------------------------------*/ static void -prepare_update(coap_message_t *request, int triggered) { +prepare_update(coap_message_t *request, int triggered) +{ coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); coap_set_header_uri_path(request, session_info.assigned_ep); @@ -423,7 +445,16 @@ registration_callback(coap_request_state_t *state) state->response->location_path_len); session_info.assigned_ep[state->response->location_path_len] = 0; /* if we decide to not pass the lt-argument on registration, we should force an initial "update" to register lifetime with server */ +#if LWM2M_QUEUE_MODE_ENABLED +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + if(lwm2m_queue_mode_get_dynamic_adaptation_flag()) { + lwm2m_queue_mode_set_first_request(); + } +#endif + lwm2m_rd_client_fsm_execute_queue_mode_awake(); /* Avoid 500 ms delay and move directly to the state*/ +#else rd_state = REGISTRATION_DONE; +#endif /* remember the last reg time */ last_update = coap_timer_uptime(); LOG_DBG_("Done (assigned EP='%s')!\n", session_info.assigned_ep); @@ -468,8 +499,23 @@ update_callback(coap_request_state_t *state) LOG_DBG_("Done!\n"); /* remember the last reg time */ last_update = coap_timer_uptime(); +#if LWM2M_QUEUE_MODE_ENABLED + /* If it has been waked up by a notification, send the stored notifications in queue */ + if(lwm2m_queue_mode_is_waked_up_by_notification()) { + + lwm2m_queue_mode_clear_waked_up_by_notification(); + lwm2m_notification_queue_send_notifications(); + } +#if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION + if(lwm2m_queue_mode_get_dynamic_adaptation_flag()) { + lwm2m_queue_mode_set_first_request(); + } +#endif /* LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION */ + lwm2m_rd_client_fsm_execute_queue_mode_awake(); /* Avoid 500 ms delay and move directly to the state*/ +#else rd_state = REGISTRATION_DONE; rd_flags &= ~FLAG_RD_DATA_UPDATE_TRIGGERED; +#endif /* LWM2M_QUEUE_MODE_ENABLED */ } else { /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */ LOG_DBG_("Failed with code %d. Retrying registration\n", @@ -516,7 +562,15 @@ periodic_process(coap_timer_t *timer) uint64_t now; /* reschedule the CoAP timer */ +#if LWM2M_QUEUE_MODE_ENABLED + /* In Queue Mode, the machine is not executed periodically, but with the awake/sleeping times */ + if(!((rd_state & 0xF) == 0xE)) { + coap_timer_reset(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); + } +#else coap_timer_reset(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); +#endif + now = coap_timer_uptime(); LOG_DBG("RD Client - state: %d, ms: %lu\n", rd_state, @@ -685,6 +739,27 @@ periodic_process(coap_timer_t *timer) rd_state = UPDATE_SENT; } break; +#if LWM2M_QUEUE_MODE_ENABLED + case QUEUE_MODE_AWAKE: + LOG_DBG("Queue Mode: Client is AWAKE at %lu\n", (unsigned long)coap_timer_uptime()); + queue_mode_client_awake = 1; + queue_mode_client_awake_time = lwm2m_queue_mode_get_awake_time(); + coap_timer_set(&queue_mode_client_awake_timer, queue_mode_client_awake_time); + break; + case QUEUE_MODE_SEND_UPDATE: +/* Define this macro to make the necessary actions for waking up, + * depending on the platform + */ +#ifdef LWM2M_QUEUE_MODE_WAKE_UP + LWM2M_QUEUE_MODE_WAKE_UP(); +#endif /* LWM2M_QUEUE_MODE_WAKE_UP */ + prepare_update(request, rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED); + coap_send_request(&rd_request_state, &session_info.server_ep, request, + update_callback); + last_rd_progress = coap_timer_uptime(); + rd_state = UPDATE_SENT; + break; +#endif /* LWM2M_QUEUE_MODE_ENABLED */ case UPDATE_SENT: /* just wait until the callback kicks us to the next state... */ @@ -718,15 +793,27 @@ lwm2m_rd_client_init(const char *ep) { session_info.ep = ep; /* default binding U = UDP, UQ = UDP Q-mode*/ +#if LWM2M_QUEUE_MODE_ENABLED + session_info.binding = "UQ"; + /* Enough margin to ensure that the client is not unregistered (we + * do not know the time it can stay awake) + */ + session_info.lifetime = (LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEP_TIME / 1000) * 2; +#else session_info.binding = "U"; if(session_info.lifetime == 0) { session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME; } +#endif + rd_state = INIT; /* call the RD client periodically */ coap_timer_set_callback(&rd_timer, periodic_process); coap_timer_set(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); +#if LWM2M_QUEUE_MODE_ENABLED + coap_timer_set_callback(&queue_mode_client_awake_timer, queue_mode_awake_timer_callback); +#endif } /*---------------------------------------------------------------------------*/ static void @@ -735,4 +822,54 @@ check_periodic_observations(void) /* TODO */ } /*---------------------------------------------------------------------------*/ +/* + *Queue Mode Support + */ +#if LWM2M_QUEUE_MODE_ENABLED +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_restart_client_awake_timer(void) +{ + coap_timer_set(&queue_mode_client_awake_timer, queue_mode_client_awake_time); +} +/*---------------------------------------------------------------------------*/ +uint8_t +lwm2m_rd_client_is_client_awake(void) +{ + return queue_mode_client_awake; +} +/*---------------------------------------------------------------------------*/ +static void +queue_mode_awake_timer_callback(coap_timer_t *timer) +{ + /* Timer has expired, no requests has been received, client can go to sleep */ + LOG_DBG("Queue Mode: Client is SLEEPING at %lu\n", (unsigned long)coap_timer_uptime()); + queue_mode_client_awake = 0; + +/* Define this macro to enter sleep mode depending on the platform */ +#ifdef LWM2M_QUEUE_MODE_SLEEP_MS + LWM2M_QUEUE_MODE_SLEEP_MS(lwm2m_queue_mode_get_sleep_time()); +#endif /* LWM2M_QUEUE_MODE_SLEEP_MS */ + rd_state = QUEUE_MODE_SEND_UPDATE; + coap_timer_set(&rd_timer, lwm2m_queue_mode_get_sleep_time()); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_fsm_execute_queue_mode_awake() +{ + coap_timer_stop(&rd_timer); + rd_state = QUEUE_MODE_AWAKE; + periodic_process(&rd_timer); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_fsm_execute_queue_mode_update() +{ + coap_timer_stop(&rd_timer); + rd_state = QUEUE_MODE_SEND_UPDATE; + periodic_process(&rd_timer); +} +/*---------------------------------------------------------------------------*/ +#endif /* LWM2M_QUEUE_MODE_ENABLED */ +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-rd-client.h b/os/services/lwm2m/lwm2m-rd-client.h index 7fba7e0ae..cfc5c549d 100644 --- a/os/services/lwm2m/lwm2m-rd-client.h +++ b/os/services/lwm2m/lwm2m-rd-client.h @@ -40,6 +40,7 @@ * \author * Joakim Eriksson * Niclas Finne + * Carlos Gonzalo Peces */ #ifndef LWM2M_RD_CLIENT_H_ @@ -52,6 +53,7 @@ #define LWM2M_RD_CLIENT_DISCONNECTED 5 #include "lwm2m-object.h" +#include "lwm2m-queue-mode-conf.h" struct lwm2m_session_info; typedef void (*session_callback_t)(struct lwm2m_session_info *session, int status); @@ -75,6 +77,13 @@ void lwm2m_rd_client_init(const char *ep); void lwm2m_rd_client_set_session_callback(session_callback_t cb); +#if LWM2M_QUEUE_MODE_ENABLED +uint8_t lwm2m_rd_client_is_client_awake(void); +void lwm2m_rd_client_restart_client_awake_timer(void); +void lwm2m_rd_client_fsm_execute_queue_mode_awake(); +void lwm2m_rd_client_fsm_execute_queue_mode_update(); +#endif + #ifndef LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN #define LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN 15 #endif /* LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN */ diff --git a/os/services/simple-energest/module-macros.h b/os/services/simple-energest/module-macros.h new file mode 100644 index 000000000..f5ae1e890 --- /dev/null +++ b/os/services/simple-energest/module-macros.h @@ -0,0 +1,2 @@ +#define BUILD_WITH_SIMPLE_ENERGEST 1 +#define ENERGEST_CONF_ON 1 diff --git a/os/services/simple-energest/simple-energest.c b/os/services/simple-energest/simple-energest.c new file mode 100644 index 000000000..fc7393bc6 --- /dev/null +++ b/os/services/simple-energest/simple-energest.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018, RISE SICS. + * 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 simple-energest +* @{ +*/ + +/** + * \file + * A process that periodically prints out the time spent in + * radio tx, radio rx, total time and duty cycle. + * + * \author Simon Duquennoy + */ + +#include "contiki.h" +#include "sys/energest.h" +#include "simple-energest.h" +#include +#include + +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Energest" +#define LOG_LEVEL LOG_LEVEL_INFO + +static unsigned long last_tx, last_rx, last_time, last_cpu, last_lpm, last_deep_lpm; +static unsigned long delta_tx, delta_rx, delta_time, delta_cpu, delta_lpm, delta_deep_lpm; +static unsigned long curr_tx, curr_rx, curr_time, curr_cpu, curr_lpm, curr_deep_lpm; + +PROCESS(simple_energest_process, "Simple Energest"); +/*---------------------------------------------------------------------------*/ +static unsigned long +to_permil(unsigned long delta_metric, unsigned long delta_time) +{ + return (1000ul * (delta_metric)) / delta_time; +} +/*---------------------------------------------------------------------------*/ +static void +simple_energest_step(void) +{ + static unsigned count = 0; + + energest_flush(); + + curr_time = ENERGEST_GET_TOTAL_TIME(); + curr_cpu = energest_type_time(ENERGEST_TYPE_CPU); + curr_lpm = energest_type_time(ENERGEST_TYPE_LPM); + curr_deep_lpm = energest_type_time(ENERGEST_TYPE_DEEP_LPM); + curr_tx = energest_type_time(ENERGEST_TYPE_TRANSMIT); + curr_rx = energest_type_time(ENERGEST_TYPE_LISTEN); + + delta_time = curr_time - last_time; + delta_cpu = curr_cpu - last_cpu; + delta_lpm = curr_lpm - last_lpm; + delta_deep_lpm = curr_deep_lpm - last_deep_lpm; + delta_tx = curr_tx - last_tx; + delta_rx = curr_rx - last_rx; + + last_time = curr_time; + last_cpu = curr_cpu; + last_lpm = curr_lpm; + last_deep_lpm = curr_deep_lpm; + last_tx = curr_tx; + last_rx = curr_rx; + + LOG_INFO("--- Period summary #%u (%lu seconds)\n", count++, delta_time/ENERGEST_SECOND); + LOG_INFO("Total time : %10lu\n", delta_time); + LOG_INFO("CPU : %10lu/%10lu (%lu permil)\n", delta_cpu, delta_time, to_permil(delta_cpu, delta_time)); + LOG_INFO("LPM : %10lu/%10lu (%lu permil)\n", delta_lpm, delta_time, to_permil(delta_lpm, delta_time)); + LOG_INFO("Deep LPM : %10lu/%10lu (%lu permil)\n", delta_deep_lpm, delta_time, to_permil(delta_deep_lpm, delta_time)); + LOG_INFO("Radio Tx : %10lu/%10lu (%lu permil)\n", delta_tx, delta_time, to_permil(delta_tx, delta_time)); + LOG_INFO("Radio Rx : %10lu/%10lu (%lu permil)\n", delta_rx, delta_time, to_permil(delta_rx, delta_time)); + LOG_INFO("Radio total : %10lu/%10lu (%lu permil)\n", delta_tx+delta_rx, delta_time, to_permil(delta_tx+delta_rx, delta_time)); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(simple_energest_process, ev, data) +{ + static struct etimer periodic_timer; + PROCESS_BEGIN(); + + etimer_set(&periodic_timer, SIMPLE_ENERGEST_PERIOD); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer)); + etimer_reset(&periodic_timer); + simple_energest_step(); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +void +simple_energest_init(void) +{ + energest_flush(); + last_time = ENERGEST_GET_TOTAL_TIME(); + last_cpu = energest_type_time(ENERGEST_TYPE_CPU); + last_lpm = energest_type_time(ENERGEST_TYPE_LPM); + curr_tx = energest_type_time(ENERGEST_TYPE_TRANSMIT); + last_deep_lpm = energest_type_time(ENERGEST_TYPE_DEEP_LPM); + last_rx = energest_type_time(ENERGEST_TYPE_LISTEN); + process_start(&simple_energest_process, NULL); +} + +/** @} */ diff --git a/arch/platform/sky/apps/burn-nodeid.c b/os/services/simple-energest/simple-energest.h similarity index 54% rename from arch/platform/sky/apps/burn-nodeid.c rename to os/services/simple-energest/simple-energest.h index 128ba2ba9..4f7281e9c 100644 --- a/arch/platform/sky/apps/burn-nodeid.c +++ b/os/services/simple-energest/simple-energest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Swedish Institute of Computer Science. + * Copyright (c) 2018, RISE SICS. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,55 +26,35 @@ * 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 simple-energest + * @{ + */ + + /** + * \file + * A process that periodically prints out the time spent in + * radio tx, radio rx, total time and duty cycle. + * + * \author Simon Duquennoy + */ + +#ifndef SIMPLE_ENERGEST_H_ +#define SIMPLE_ENERGEST_H_ + +/** \brief The period at which Energest statistics will be logged */ +#ifdef SIMPLE_ENERGEST_CONF_PERIOD +#define SIMPLE_ENERGEST_PERIOD SIMPLE_ENERGEST_CONF_PERIOD +#else /* SIMPLE_ENERGEST_CONF_PERIOD */ +#define SIMPLE_ENERGEST_PERIOD (CLOCK_SECOND * 60) +#endif /* SIMPLE_ENERGEST_CONF_PERIOD */ + /** - * \file - * A program for burning a node ID into the flash ROM of a Tmote Sky node. - * \author - * Adam Dunkels + * Initialize the deployment module */ +void simple_energest_init(void); -#include "dev/leds.h" -#include "dev/watchdog.h" -#include "sys/node-id.h" -#include "contiki.h" -#include "sys/etimer.h" - -#include - -static struct etimer etimer; - -PROCESS(burn_process, "Burn node id"); -AUTOSTART_PROCESSES(&burn_process); -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(burn_process, ev, data) -{ - PROCESS_BEGIN(); - - etimer_set(&etimer, 5*CLOCK_SECOND); - PROCESS_WAIT_UNTIL(etimer_expired(&etimer)); - - watchdog_stop(); - leds_on(LEDS_RED); -#if NODEID - printf("Burning node id %d\n", NODEID); - node_id_burn(NODEID); - leds_on(LEDS_BLUE); - node_id_restore(); - printf("Restored node id %d\n", node_id); -#else -#error "burn-nodeid must be compiled with nodeid=" - node_id_restore(); - printf("Restored node id %d\n", node_id); -#endif - leds_off(LEDS_RED + LEDS_BLUE); - watchdog_start(); - while(1) { - PROCESS_WAIT_EVENT(); - } - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ +#endif /* SIMPLE_ENERGEST_H_ */ +/** @} */ diff --git a/arch/platform/cooja/sys/node-id.h b/os/sys/node-id.c similarity index 75% rename from arch/platform/cooja/sys/node-id.h rename to os/sys/node-id.c index a6876bd1f..7914256e9 100644 --- a/arch/platform/cooja/sys/node-id.h +++ b/os/sys/node-id.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Swedish Institute of Computer Science. + * Copyright (c) 2018, RISE SICS. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,14 +26,26 @@ * 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. + * */ -#ifndef NODE_ID_H_ -#define NODE_ID_H_ +/** + * \file + * Node-id management + * \author + * Simon Duquennoy + */ -#include "dev/moteid.h" +#include "contiki.h" +#include "sys/node-id.h" +#include "net/linkaddr.h" -#define node_id simMoteID +uint16_t node_id = 0; -#endif /* NODE_ID_H_ */ +void +node_id_init(void) { + /* Initialize with a default value derived from linkaddr */ + node_id = linkaddr_node_addr.u8[LINKADDR_SIZE - 1] + + (linkaddr_node_addr.u8[LINKADDR_SIZE - 2] << 8); +} diff --git a/os/sys/node-id.h b/os/sys/node-id.h index 0b6ebe6b1..58909ddaa 100644 --- a/os/sys/node-id.h +++ b/os/sys/node-id.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Swedish Institute of Computer Science. + * Copyright (c) 2018, RISE SICS. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,16 +28,28 @@ * * This file is part of the Contiki operating system. * - * Author: Adam Dunkels - * */ + /** + * \addtogroup node-id + * @{ + * + * \file + * Node-id (simple 16-bit identifiers) handling + * \author Simon Duquennoy + * + */ + #ifndef NODE_ID_H_ #define NODE_ID_H_ -void node_id_restore(void); -void node_id_burn(unsigned short node_id); - -extern unsigned short node_id; +/* A global variable that hosts the node ID */ +extern uint16_t node_id; +/** + * Initialize the node ID. Must be called after initialized of linkaddr + */ +void node_id_init(void); #endif /* NODE_ID_H_ */ + /** @} */ + diff --git a/tests/01-compile-base/Makefile b/tests/01-compile-base/Makefile index eae930138..d9ef0ba58 100644 --- a/tests/01-compile-base/Makefile +++ b/tests/01-compile-base/Makefile @@ -15,6 +15,8 @@ libs/data-structures/sky \ libs/stack-check/sky \ lwm2m-ipso-objects/native \ lwm2m-ipso-objects/native:MAKE_WITH_DTLS=1 \ +lwm2m-ipso-objects/native:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1 \ +lwm2m-ipso-objects/native:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1,LWM2M_Q_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1\ rpl-udp/sky \ rpl-border-router/native \ rpl-border-router/native:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \ diff --git a/tests/02-compile-arm-ports-01/Makefile b/tests/02-compile-arm-ports-01/Makefile index 5e73c4ecb..4bb1e9269 100644 --- a/tests/02-compile-arm-ports-01/Makefile +++ b/tests/02-compile-arm-ports-01/Makefile @@ -43,6 +43,8 @@ coap/coap-example-client/cc2538dk \ coap/coap-example-server/cc2538dk \ slip-radio/cc2538dk \ lwm2m-ipso-objects/cc2538dk \ +lwm2m-ipso-objects/cc2538dk:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1 \ +lwm2m-ipso-objects/native:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1,LWM2M_Q_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1\ multicast/cc2538dk \ dev/gpio-hal/cc2538dk \ dev/leds/cc2538dk \ diff --git a/tests/03-compile-arm-ports-02/Makefile b/tests/03-compile-arm-ports-02/Makefile index defd10a96..ceb1b79e3 100644 --- a/tests/03-compile-arm-ports-02/Makefile +++ b/tests/03-compile-arm-ports-02/Makefile @@ -17,6 +17,8 @@ coap/coap-example-server/zoul \ multicast/zoul \ lwm2m-ipso-objects/zoul \ lwm2m-ipso-objects/zoul:MAKE_WITH_DTLS=1 \ +lwm2m-ipso-objects/zoul:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1 \ +lwm2m-ipso-objects/zoul:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1,LWM2M_Q_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1\ hello-world/zoul \ sensniff/zoul \ sensniff/zoul:ZOUL_CONF_SUB_GHZ_SNIFFER=1 \ @@ -62,6 +64,8 @@ dev/gpio-hal/openmote-cc2538 \ dev/leds/openmote-cc2538 \ rpl-border-router/openmote-cc2538 \ libs/ipv6-hooks/openmote-cc2538 \ +libs/shell/openmote-cc2538 \ +libs/simple-energest/openmote-cc2538 \ TOOLS= diff --git a/tests/08-native-runs/01-test-data-structures.sh b/tests/08-native-runs/01-test-data-structures.sh index 790235638..2343756fe 100755 --- a/tests/08-native-runs/01-test-data-structures.sh +++ b/tests/08-native-runs/01-test-data-structures.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -16,7 +17,7 @@ sleep 2 echo "Closing native node" sleep 2 -pgrep $CODE | xargs kill -9 +kill_bg $CPID if grep -q "=check-me= FAILED" $CODE.log ; then echo "==== make.log ====" ; cat make.log; diff --git a/tests/09-ipv6/js/ping-test-lla.js b/tests/09-ipv6/js/ping-test-lla.js index 1823d87b2..d9beedf8b 100644 --- a/tests/09-ipv6/js/ping-test-lla.js +++ b/tests/09-ipv6/js/ping-test-lla.js @@ -8,7 +8,7 @@ while(1) { YIELD(); log.log(time + " " + id + " "+ msg + "\n"); - if(msg.contains("Node id is set to")) { + if(msg.contains("Node ID: ")) { if(id == 1) { write(sim.getMoteWithID(1), "rpl-set-root 1"); } diff --git a/tests/09-ipv6/js/ping-test-ula.js b/tests/09-ipv6/js/ping-test-ula.js index b78f0342a..adbd22ccf 100644 --- a/tests/09-ipv6/js/ping-test-ula.js +++ b/tests/09-ipv6/js/ping-test-ula.js @@ -9,7 +9,7 @@ while(1) { YIELD(); log.log(time + " " + id + " "+ msg + "\n"); - if(msg.contains("Node id is set to")) { + if(msg.contains("Node ID: ")) { if(id == 1) { write(sim.getMoteWithID(1), "rpl-set-root 1"); } diff --git a/tests/17-tun-rpl-br/04-border-router-traceroute.sh b/tests/17-tun-rpl-br/04-border-router-traceroute.sh index e1e9d6cdd..fe1333aab 100755 --- a/tests/17-tun-rpl-br/04-border-router-traceroute.sh +++ b/tests/17-tun-rpl-br/04-border-router-traceroute.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -38,8 +39,8 @@ HOPS=`wc $BASENAME.scriptlog -l | cut -f 1 -d ' '` echo "Closing simulation and tunslip6" sleep 1 -kill -9 $JPID -kill -9 $MPID +kill_bg $JPID +kill_bg $MPID sleep 1 rm COOJA.testlog rm COOJA.log diff --git a/tests/17-tun-rpl-br/05-native-ping.sh b/tests/17-tun-rpl-br/05-native-ping.sh index 9e677c16e..ea416aac4 100755 --- a/tests/17-tun-rpl-br/05-native-ping.sh +++ b/tests/17-tun-rpl-br/05-native-ping.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -22,7 +23,7 @@ STATUS=${PIPESTATUS[0]} echo "Closing native node" sleep 2 -pgrep hello-world | sudo xargs kill -9 +kill_bg $CPID if [ $STATUS -eq 0 ] ; then cp $BASENAME.log $BASENAME.testlog diff --git a/tests/17-tun-rpl-br/06-native-coap.sh b/tests/17-tun-rpl-br/06-native-coap.sh index 88627ec19..216d104f4 100755 --- a/tests/17-tun-rpl-br/06-native-coap.sh +++ b/tests/17-tun-rpl-br/06-native-coap.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -38,7 +39,7 @@ done echo "Closing native node" sleep 2 -pgrep coap-example | sudo xargs kill -9 +kill_bg $CPID if [ $TESTCOUNT -eq $OKCOUNT ] ; then printf "%-32s TEST OK %3d/%d\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" | tee $BASENAME.testlog; diff --git a/tests/17-tun-rpl-br/test-border-router.sh b/tests/17-tun-rpl-br/test-border-router.sh index f98ca81f4..c5653d480 100755 --- a/tests/17-tun-rpl-br/test-border-router.sh +++ b/tests/17-tun-rpl-br/test-border-router.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -44,8 +45,8 @@ REPLIES=`grep -c 'icmp_seq=' $BASENAME.scriptlog` echo "Closing simulation and tunslip6" sleep 1 -kill -9 $JPID -kill -9 $MPID +kill_bg $JPID +kill_bg $MPID sleep 1 rm COOJA.testlog rm COOJA.log diff --git a/tests/17-tun-rpl-br/test-native-border-router.sh b/tests/17-tun-rpl-br/test-native-border-router.sh index 636b6b973..50ea18179 100644 --- a/tests/17-tun-rpl-br/test-native-border-router.sh +++ b/tests/17-tun-rpl-br/test-native-border-router.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -43,8 +44,8 @@ REPLIES=`grep -c 'icmp_seq=' $BASENAME.scriptlog` echo "Closing simulation and nbr" sleep 1 -kill -9 $JPID -kill -9 $MPID +kill_bg $JPID +kill_bg $MPID sleep 1 rm COOJA.testlog rm COOJA.log diff --git a/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh index 9aacc2976..ec7502a21 100755 --- a/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh +++ b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -32,11 +33,11 @@ done echo "Closing native node" sleep 1 -pgrep ipso | sudo xargs kill -9 +kill_bg $CPID echo "Closing leshan" sleep 1 -pgrep java | sudo xargs kill -9 +kill_bg $LESHID if grep -q 'OK' leshan.err ; then diff --git a/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh index b13352447..a1257f36e 100755 --- a/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh +++ b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh @@ -1,4 +1,5 @@ #!/bin/bash +source ../utils.sh # Contiki directory CONTIKI=$1 @@ -33,11 +34,11 @@ done echo "Closing standalone example" sleep 1 -pgrep lwm2m-example | sudo xargs kill -9 +kill_bg $CPID echo "Closing leshan" sleep 1 -pgrep java | sudo xargs kill -9 +kill_bg $LESHID if grep -q 'OK' leshan.err ; then diff --git a/tests/18-coap-lwm2m/08-lwm2m-qmode-ipso-test.sh b/tests/18-coap-lwm2m/08-lwm2m-qmode-ipso-test.sh new file mode 100755 index 000000000..2b3d52c3e --- /dev/null +++ b/tests/18-coap-lwm2m/08-lwm2m-qmode-ipso-test.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=08-lwm2m-qmode-ipso-test + +IPADDR=fd00::302:304:506:708 + +# Starting Contiki-NG native node +echo "Starting native node - lwm2m/ipso objects with Q-Mode" +make -C $CONTIKI/examples/lwm2m-ipso-objects clean >/dev/null +make -C $CONTIKI/examples/lwm2m-ipso-objects DEFINES=LWM2M_QUEUE_MODE_CONF_ENABLED=1,LWM2M_QUEUE_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1,LWM2M_QUEUE_MODE_OBJECT_CONF_ENABLED=1 > make.log 2> make.err +sudo $CONTIKI/examples/lwm2m-ipso-objects/example-ipso-objects.native > node.log 2> node.err & +CPID=$! +sleep 10 + +echo "Downloading leshan with Q-Mode support" +wget -nc https://carlosgp143.github.io/resources/leshan-server-demo-qmode-support1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server with Q-Mode enabled" +java -jar leshan-server-demo-qmode-support1.0.0-SNAPSHOT-jar-with-dependencies.jar >leshan.log 2>leshan.err & +LESHID=$! + +COUNTER=10 +while [ $COUNTER -gt 0 ]; do + sleep 5 + aux=$(grep -c 'OK' leshan.err) + if [ $aux -eq 2 ] ; then + break + fi + let COUNTER-=1 +done + +echo "Closing native node" +sleep 1 +pgrep ipso | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + +#Two OKs needed: awake and sleeping +aux=$(grep -c 'OK' leshan.err) +if [ $aux -eq 2 ] +then + cp leshan.err $BASENAME.testlog; + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== leshan.log ====" ; cat leshan.log; + echo "==== leshan.err ====" ; cat leshan.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +rm make.log +rm make.err +rm node.log +rm node.err +rm leshan.log +rm leshan.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/18-coap-lwm2m/09-lwm2m-qmode-standalone-test.sh b/tests/18-coap-lwm2m/09-lwm2m-qmode-standalone-test.sh new file mode 100755 index 000000000..57f0e3f71 --- /dev/null +++ b/tests/18-coap-lwm2m/09-lwm2m-qmode-standalone-test.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=09-lwm2m-qmode-standalone-test + +# Building standalone posix example +echo "Compiling standalone posix example" +make CONTIKI_NG=../../$CONTIKI -C example-lwm2m-standalone/lwm2m clean >/dev/null +make CONTIKI_NG=../../$CONTIKI -C example-lwm2m-standalone/lwm2m DEFINES=LWM2M_QUEUE_MODE_CONF_ENABLED=1,LWM2M_QUEUE_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1,LWM2M_QUEUE_MODE_OBJECT_CONF_ENABLED=1 >make.log 2>make.err + +echo "Downloading leshan with Q-Mode support" +wget -nc https://carlosgp143.github.io/resources/leshan-server-demo-qmode-support1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server with Q-Mode enabled" +java -jar leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar -lp 5686 -slp 5687 >leshan.log 2>leshan.err & +LESHID=$! + +echo "Starting lwm2m standalone example" +example-lwm2m-standalone/lwm2m/lwm2m-example coap://127.0.0.1:5686 > node.log 2> node.err & + +CPID=$! + +COUNTER=10 +while [ $COUNTER -gt 0 ]; do + sleep 5 + aux=$(grep -c 'OK' leshan.err) + if [ $aux -eq 2 ] ; then + break + fi + let COUNTER-=1 +done + +echo "Closing standalone example" +sleep 1 +pgrep lwm2m-example | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + +aux=$(grep -c 'OK' leshan.err) +if [ $aux -eq 2 ] +then + cp leshan.err $BASENAME.testlog; + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== leshan.log ====" ; cat leshan.log; + echo "==== leshan.err ====" ; cat leshan.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +rm make.log +rm make.err +rm node.log +rm node.err +rm leshan.log +rm leshan.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/18-coap-lwm2m/pytests/test-qmode-awake.py b/tests/18-coap-lwm2m/pytests/test-qmode-awake.py new file mode 100644 index 000000000..775e1cff0 --- /dev/null +++ b/tests/18-coap-lwm2m/pytests/test-qmode-awake.py @@ -0,0 +1,20 @@ +import unittest, array, time + +class TestQueueModeAwake(unittest.TestCase): + global respAwakeTime + global respSleepTime + + def test_read_awake_time(self): + self.assertEqual(respAwakeTime.getCode().getName(), "CONTENT") + + def test_read_sleep_time(self): + self.assertEqual(respSleepTime.getCode().getName(), "CONTENT") + + +print "----------------------------------------" +print "LWM2M Queue Mode Awake State Tester" +print "----------------------------------------" + + +suite = unittest.TestLoader().loadTestsFromTestCase(TestQueueModeAwake) +unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/18-coap-lwm2m/pytests/test-qmode-sleep.py b/tests/18-coap-lwm2m/pytests/test-qmode-sleep.py new file mode 100644 index 000000000..66dc061ff --- /dev/null +++ b/tests/18-coap-lwm2m/pytests/test-qmode-sleep.py @@ -0,0 +1,19 @@ +from __future__ import with_statement +import unittest, array, time + +class TestQueueModeSleep(unittest.TestCase): + global client + + def test_read_awake_time(self): + self.assertIsNone(client.read("30000/0/30000")) + + def test_read_sleep_time(self): + self.assertIsNone(client.read("30000/0/30001")) + + +print "----------------------------------------" +print "LWM2M Queue Mode Sleep State Tester - name of client: ", client.endpoint +print "----------------------------------------" + +suite = unittest.TestLoader().loadTestsFromTestCase(TestQueueModeSleep) +unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/utils.sh b/tests/utils.sh new file mode 100755 index 000000000..bd00ca539 --- /dev/null +++ b/tests/utils.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +function echo_run( ) +{ + echo $@ + $@ +} + +function kill_bg( ) +{ + PID=$1 + CMD=$(ps -p $PID -o cmd=) + SUDO= + TOKILL=$PID + if [[ ${CMD:0:5} == "sudo " ]] ; then + SUDO="sudo " + TOKILL=$(ps --ppid $PID -o pid=) + fi + echo_run ${SUDO}kill -9 $TOKILL +}