diff --git a/.gitignore b/.gitignore index 74bef3888..f8f72f54b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,8 +20,6 @@ tools/tunslip6 build tools/coffee-manager/build/ tools/coffee-manager/coffee.jar -tools/collect-view/build/ -tools/collect-view/dist/ COOJA.testlog # platform build artifacts diff --git a/.gitmodules b/.gitmodules index f2cd29451..36eb3cd95 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,9 @@ [submodule "tools/cooja"] path = tools/cooja url = https://github.com/contiki-ng/cooja.git +[submodule "os/net/security/tinydtls"] + path = os/net/security/tinydtls + url = https://github.com/contiki-ng/tinydtls.git +[submodule "tests/18-coap-lwm2m/example-lwm2m-standalone"] + path = tests/18-coap-lwm2m/example-lwm2m-standalone + url = https://github.com/contiki-ng/example-lwm2m-standalone.git diff --git a/.travis.yml b/.travis.yml index 7591dd772..00dba89ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ before_install: - ant -q -f $CNG_HOST_PATH/tools/cooja/build.xml jar script: # The test script for each build. - - docker run --privileged -v $CNG_HOST_PATH:/home/user/contiki-ng -ti $DOCKER_IMG bash -c "make -C tests/??-$TEST_NAME"; + - docker run --privileged -v $CNG_HOST_PATH:/home/user/contiki-ng -ti $DOCKER_IMG bash --login -c "make -C tests/??-$TEST_NAME"; # Check outcome of the test - $CNG_HOST_PATH/tests/check-test.sh $CNG_HOST_PATH/tests/??-$TEST_NAME; exit $?; @@ -26,6 +26,7 @@ env: - TEST_NAME='rpl-lite' - TEST_NAME='rpl-classic' - TEST_NAME='tun-rpl-br' + - TEST_NAME='coap-lwm2m' - TEST_NAME='simulation-base' - TEST_NAME='ieee802154' - TEST_NAME='compile-nxp-ports' diff --git a/LICENSE.md b/LICENSE.md index c180b146d..b2f909d44 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Contiki is licensed under the 3-clause BSD license. This license gives +Contiki-NG is licensed under the 3-clause BSD license. This license gives everyone the right to use and distribute the code, either in binary or source code format, as long as the copyright license is retained in the source code. diff --git a/Makefile.include b/Makefile.include index ec927b88b..0df048e7b 100644 --- a/Makefile.include +++ b/Makefile.include @@ -52,9 +52,15 @@ ifneq ("$(wildcard project-conf.h)","") CFLAGS += -DPROJECT_CONF_PATH=\"project-conf.h\" endif -MODULES += os os/net os/net/mac os/storage +MODULES += os os/net os/net/mac os/net/mac/framer os/net/routing os/storage -oname = ${patsubst %.c,%.o,${patsubst %.S,%.o,$(1)}} +define oname +${patsubst %.c,%.o, \ +${patsubst %.S,%.o, \ +${patsubst %.s,%.o, \ +$(1) \ +}}} +endef CONTIKI_OBJECTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CONTIKI_SOURCEFILES)}} PROJECT_OBJECTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(PROJECT_SOURCEFILES)}} @@ -145,7 +151,7 @@ ifeq ($(WITH_IP64),1) endif # Configure Routing protocol -MAKE_ROUTING_NONE = 0 +MAKE_ROUTING_NULLROUTING = 0 MAKE_ROUTING_RPL_CLASSIC = 1 MAKE_ROUTING_RPL_LITE = 2 @@ -153,19 +159,18 @@ MAKE_ROUTING_RPL_LITE = 2 ifeq ($(MAKE_NET),MAKE_NET_IPV6) MAKE_ROUTING ?= MAKE_ROUTING_RPL_LITE else -MAKE_ROUTING ?= MAKE_ROUTING_NONE +MAKE_ROUTING ?= MAKE_ROUTING_NULLROUTING endif ifeq ($(MAKE_ROUTING),MAKE_ROUTING_RPL_CLASSIC) - CFLAGS += -DUIP_CONF_IPV6_RPL=1 - CFLAGS += -DUIP_CONF_IPV6_RPL_CLASSIC=1 - MODULES += os/net/rpl-classic + CFLAGS += -DROUTING_CONF_RPL_CLASSIC=1 + MODULES += os/net/routing/rpl-classic else ifeq ($(MAKE_ROUTING),MAKE_ROUTING_RPL_LITE) - CFLAGS += -DUIP_CONF_IPV6_RPL=1 - CFLAGS += -DUIP_CONF_IPV6_RPL_LITE=1 - MODULES += os/net/rpl-lite -else - CFLAGS += -DUIP_CONF_IPV6_RPL=0 + CFLAGS += -DROUTING_CONF_RPL_LITE=1 + MODULES += os/net/routing/rpl-lite +else ifeq ($(MAKE_ROUTING),MAKE_ROUTING_NULLROUTING) + CFLAGS += -DROUTING_CONF_NULLROUTING=1 + MODULES += os/net/routing/nullrouting endif MODULEDIRS = $(MODULES_REL) ${wildcard ${addprefix $(CONTIKI)/, $(MODULES)}} @@ -220,6 +225,7 @@ SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) $(CONTIKI_ARCH_DIRS) vpath %.c $(SOURCEDIRS) vpath %.S $(SOURCEDIRS) +vpath %.s $(SOURCEDIRS) CFLAGS += ${addprefix -I,$(SOURCEDIRS) $(CONTIKI)} @@ -274,6 +280,9 @@ ifndef CUSTOM_RULE_S_TO_OBJECTDIR_O $(OBJECTDIR)/%.o: %.S | $(OBJECTDIR) $(TRACE_AS) $(Q)$(AS) $(ASFLAGS) -o $@ $< +$(OBJECTDIR)/%.o: %.s | $(OBJECTDIR) + $(TRACE_AS) + $(Q)$(AS) $(ASFLAGS) -o $@ $< endif ifndef CUSTOM_RULE_C_TO_OBJECTDIR_S @@ -366,6 +375,9 @@ viewconf: @echo "##### \"MAKE_MAC\": ______________________________ $(MAKE_MAC)" @echo "##### \"MAKE_NET\": ______________________________ $(MAKE_NET)" @echo "##### \"MAKE_ROUTING\": __________________________ $(MAKE_ROUTING)" +ifdef MAKE_COAP_DTLS_KEYSTORE + @echo "##### \"MAKE_COAP_DTLS_KEYSTORE\": _______________ $(MAKE_COAP_DTLS_KEYSTORE)" +endif @echo "----------------- C variables: -----------------" $(Q)$(CC) $(CFLAGS) -E $(CONTIKI)/tools/viewconf.c | grep \#\#\#\#\# @echo "------------------------------------------------" diff --git a/README.md b/README.md index 86dadeb75..f29f369c1 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,25 @@ -# Contiki-NG: the Next Generation Contiki +# Contiki-NG: The OS for Next Generation IoT Devices [![Build Status](https://travis-ci.org/contiki-ng/contiki-ng.svg?branch=master)](https://travis-ci.org/contiki-ng/contiki-ng/branches) +[![License](https://img.shields.io/badge/License-3--Clause%20BSD-brightgreen.svg)](https://github.com/contiki-ng/contiki-ng/blob/master/LICENSE.md) +[![Latest release](https://img.shields.io/github/release/contiki-ng/contiki-ng.svg)](https://github.com/contiki-ng/contiki-ng/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/contiki-ng/contiki-ng.svg)](https://github.com/contiki-ng/contiki-ng/releases/latest) +[![Last commit](https://img.shields.io/github/last-commit/contiki-ng/contiki-ng.svg)](https://github.com/contiki-ng/contiki-ng/commit/HEAD) + +Contiki-NG is an open-source, cross-platform operating system for Next-Generation IoT devices. It focuses on dependable (secure and reliable) low-power communication and standard protocols, such as IPv6/6LoWPAN, 6TiSCH, RPL, and CoAP. Contiki-NG comes with extensive documentation, tutorials, a roadmap, release cycle, and well-defined development flow for smooth integration of community contributions. + +Unless excplicitly stated otherwise, Contiki-NG sources are distributed under +the terms of the [3-clause BSD license](LICENSE.md). + +Contiki-NG started as a fork of the Contiki OS and retains some of its original features. + +Find out more: -Contiki-NG is a fork of Contiki, with focus on next generation IoT protocols and platforms. -Important links: * GitHub repository: https://github.com/contiki-ng/contiki-ng * Documentation: https://github.com/contiki-ng/contiki-ng/wiki +* Web site: http://contiki-ng.org + +Engage with the community: + * Gitter: https://gitter.im/contiki-ng * Twitter: https://twitter.com/contiki_ng -* Web site: http://contiki-ng.org diff --git a/arch/cpu/arm/arm-def.h b/arch/cpu/arm/arm-def.h index 63a70a535..2cd31604c 100644 --- a/arch/cpu/arm/arm-def.h +++ b/arch/cpu/arm/arm-def.h @@ -42,16 +42,6 @@ /*---------------------------------------------------------------------------*/ #include /*---------------------------------------------------------------------------*/ -/** - * \name Compiler configuration - * - * Those values are not meant to be modified by the user - * @{ - */ -#define CCIF -#define CLIF -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name Macros and typedefs * diff --git a/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c b/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c index 4e9902297..696f2e455 100644 --- a/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c +++ b/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c @@ -122,5 +122,5 @@ const struct configuration_st { }; -const struct usb_st_configuration_descriptor const *configuration_head = -(struct usb_st_configuration_descriptor const*)&configuration_block; +const struct usb_st_configuration_descriptor* const configuration_head = +(const struct usb_st_configuration_descriptor*)&configuration_block; diff --git a/arch/cpu/arm/common/usb/descriptors.h b/arch/cpu/arm/common/usb/descriptors.h index f54184395..6c89f3c03 100644 --- a/arch/cpu/arm/common/usb/descriptors.h +++ b/arch/cpu/arm/common/usb/descriptors.h @@ -6,5 +6,5 @@ #endif extern const struct usb_st_device_descriptor device_descriptor; -extern const struct usb_st_configuration_descriptor const *configuration_head; +extern const struct usb_st_configuration_descriptor* const configuration_head; #endif /* DESCRIPTORS_H_RPFUB8O7OV__ */ diff --git a/arch/cpu/cc2538/Makefile.cc2538 b/arch/cpu/cc2538/Makefile.cc2538 index c0a2bb2f0..f6e76f571 100644 --- a/arch/cpu/cc2538/Makefile.cc2538 +++ b/arch/cpu/cc2538/Makefile.cc2538 @@ -17,7 +17,7 @@ CONTIKI_CPU_DIRS = . dev usb usb/common usb/common/cdc-acm CONTIKI_CPU_SOURCEFILES += soc.c clock.c rtimer-arch.c uart.c watchdog.c CONTIKI_CPU_SOURCEFILES += nvic.c sys-ctrl.c gpio.c ioc.c spi.c adc.c CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ecb.c cbc.c ctr.c cbc-mac.c gcm.c -CONTIKI_CPU_SOURCEFILES += ccm.c sha256.c +CONTIKI_CPU_SOURCEFILES += ccm.c sha256.c gpio-hal-arch.c CONTIKI_CPU_SOURCEFILES += cc2538-aes-128.c cc2538-ccm-star.c CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c int-master.c CONTIKI_CPU_SOURCEFILES += pka.c bignum-driver.c ecc-driver.c ecc-algorithm.c diff --git a/arch/cpu/cc2538/cc2538-def.h b/arch/cpu/cc2538/cc2538-def.h index 39dd18c13..32aed6111 100644 --- a/arch/cpu/cc2538/cc2538-def.h +++ b/arch/cpu/cc2538/cc2538-def.h @@ -64,6 +64,8 @@ /* Path to headers with implementation of mutexes and memory barriers */ #define MUTEX_CONF_ARCH_HEADER_PATH "mutex-cortex.h" #define MEMORY_BARRIER_CONF_ARCH_HEADER_PATH "memory-barrier-cortex.h" + +#define GPIO_HAL_CONF_ARCH_HDR_PATH "dev/gpio-hal-arch.h" /*---------------------------------------------------------------------------*/ #endif /* CC2538_DEF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc2538/clock.c b/arch/cpu/cc2538/clock.c index 2842a3be8..839c72242 100644 --- a/arch/cpu/cc2538/clock.c +++ b/arch/cpu/cc2538/clock.c @@ -114,7 +114,7 @@ clock_init(void) REG(GPT_0_BASE + GPTIMER_TAPR) = PRESCALER_VALUE; } /*---------------------------------------------------------------------------*/ -CCIF clock_time_t +clock_time_t clock_time(void) { return rt_ticks_startup / RTIMER_CLOCK_TICK_RATIO; @@ -126,7 +126,7 @@ clock_set_seconds(unsigned long sec) rt_ticks_epoch = (uint64_t)sec * RTIMER_SECOND; } /*---------------------------------------------------------------------------*/ -CCIF unsigned long +unsigned long clock_seconds(void) { return rt_ticks_epoch / RTIMER_SECOND; diff --git a/arch/cpu/cc2538/dev/gpio-hal-arch.c b/arch/cpu/cc2538/dev/gpio-hal-arch.c new file mode 100644 index 000000000..dd8e5c513 --- /dev/null +++ b/arch/cpu/cc2538/dev/gpio-hal-arch.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-gpio-hal + * @{ + * + * \file + * Implementation file for the CC2538 GPIO HAL functions + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "dev/gpio.h" +#include "dev/ioc.h" + +#include +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg) +{ + uint8_t port, pin_num, pin_mask; + uint32_t port_base; + + port = PIN_TO_PORT(pin); + port_base = PIN_TO_PORT_BASE(pin); + pin_num = pin % 8; + pin_mask = GPIO_PIN_MASK(pin_num); + + gpio_hal_pin_cfg_t tmp; + + tmp = cfg & GPIO_HAL_PIN_CFG_EDGE_BOTH; + if(tmp == GPIO_HAL_PIN_CFG_EDGE_NONE) { + GPIO_DISABLE_INTERRUPT(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_RISING) { + GPIO_DETECT_EDGE(port_base, pin_mask); + GPIO_TRIGGER_SINGLE_EDGE(port_base, pin_mask); + GPIO_DETECT_RISING(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_FALLING) { + GPIO_DETECT_EDGE(port_base, pin_mask); + GPIO_TRIGGER_SINGLE_EDGE(port_base, pin_mask); + GPIO_DETECT_FALLING(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_BOTH) { + GPIO_DETECT_EDGE(port_base, pin_mask); + GPIO_TRIGGER_BOTH_EDGES(port_base, pin_mask); + } + + tmp = cfg & GPIO_HAL_PIN_CFG_PULL_MASK; + if(tmp == GPIO_HAL_PIN_CFG_PULL_NONE) { + ioc_set_over(port, pin_num, IOC_OVERRIDE_DIS); + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_DOWN) { + ioc_set_over(port, pin_num, IOC_OVERRIDE_PDE); + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_UP) { + ioc_set_over(port, pin_num, IOC_OVERRIDE_PUE); + } + + tmp = cfg & GPIO_HAL_PIN_CFG_INT_MASK; + if(tmp == GPIO_HAL_PIN_CFG_INT_DISABLE) { + GPIO_DISABLE_INTERRUPT(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_INT_ENABLE) { + GPIO_ENABLE_INTERRUPT(port_base, pin_mask); + } + + GPIO_SOFTWARE_CONTROL(port_base, pin_mask); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_cfg_t +gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin) +{ + uint8_t port, pin_num, pin_mask; + uint32_t port_base; + gpio_hal_pin_cfg_t cfg; + uint32_t tmp; + + port = PIN_TO_PORT(pin); + port_base = PIN_TO_PORT_BASE(pin); + pin_num = pin % 8; + pin_mask = GPIO_PIN_MASK(pin_num); + + cfg = 0; + + /* Pull */ + tmp = ioc_get_over(port, pin_num); + if(tmp == IOC_OVERRIDE_PUE) { + cfg |= GPIO_HAL_PIN_CFG_PULL_UP; + } else if(tmp == IOC_OVERRIDE_PDE) { + cfg |= GPIO_HAL_PIN_CFG_PULL_DOWN; + } else { + cfg |= GPIO_HAL_PIN_CFG_PULL_NONE; + } + + /* Interrupt enable/disable */ + tmp = REG((port_base) + GPIO_IE) & pin_mask; + if(tmp == 0) { + cfg |= GPIO_HAL_PIN_CFG_INT_DISABLE; + } else { + cfg |= GPIO_HAL_PIN_CFG_INT_ENABLE; + } + + /* Edge detection */ + if(REG((port_base) + GPIO_IS) & pin_mask) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_NONE; + } else { + if(REG((port_base) + GPIO_IBE) & pin_mask) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_BOTH; + } else { + if(REG((port_base) + GPIO_IEV) & pin_mask) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_RISING; + } else { + cfg |= GPIO_HAL_PIN_CFG_EDGE_FALLING; + } + } + } + + return cfg; +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value) +{ + if(value == 1) { + gpio_hal_arch_set_pin(pin); + return; + } + gpio_hal_arch_clear_pin(pin); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins) +{ + GPIO_SET_PIN(GPIO_A_BASE, pins & 0xFF); + GPIO_SET_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF); + GPIO_SET_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF); + GPIO_SET_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins) +{ + GPIO_CLR_PIN(GPIO_A_BASE, pins & 0xFF); + GPIO_CLR_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF); + GPIO_CLR_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF); + GPIO_CLR_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_mask_t +gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_pin_mask_t rv = 0; + + rv |= GPIO_READ_PIN(GPIO_A_BASE, pins & 0xFF); + rv |= GPIO_READ_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF) << 8; + rv |= GPIO_READ_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF) << 16; + rv |= GPIO_READ_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF) << 24; + + return rv; +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins, gpio_hal_pin_mask_t value) +{ + GPIO_WRITE_PIN(GPIO_A_BASE, pins & 0xFF, value & 0xFF); + GPIO_WRITE_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF, (value >> 8) & 0xFF); + GPIO_WRITE_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF, (value >> 16) & 0xFF); + GPIO_WRITE_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF, (value >> 24) & 0xFF); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/platform/zoul/remote-revb/leds-res-arch.c b/arch/cpu/cc2538/dev/gpio-hal-arch.h similarity index 53% rename from arch/platform/zoul/remote-revb/leds-res-arch.c rename to arch/cpu/cc2538/dev/gpio-hal-arch.h index 59484c2ff..78842634a 100644 --- a/arch/platform/zoul/remote-revb/leds-res-arch.c +++ b/arch/cpu/cc2538/dev/gpio-hal-arch.h @@ -1,17 +1,16 @@ /* - * Copyright (c) 2015, Zolertia - http://www.zolertia.com - * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * 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. @@ -29,73 +28,59 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/*---------------------------------------------------------------------------*/ /** - * \addtogroup zoul + * \addtogroup cc2538 * @{ * - * \defgroup remote-revb-leds RE-Mote revision B arch LED + * \defgroup cc2538-gpio-hal CC2538 GPIO HAL implementation * - * LED driver implementation for the RE-Mote revision B * @{ * * \file - * LED driver implementation for the RE-Mote revision B + * Header file for the CC2538 GPIO HAL functions + * + * \note + * Do not include this header directly */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_HAL_ARCH_H_ +#define GPIO_HAL_ARCH_H_ +/*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "reg.h" -#include "dev/leds.h" #include "dev/gpio.h" -#include "dev/ioc.h" + +#include /*---------------------------------------------------------------------------*/ -#define LEDS_PORTB_PIN_MASK (LEDS_GREEN_PIN_MASK | LEDS_BLUE_PIN_MASK) +#define PIN_TO_PORT(pin) (pin >> 3) +#define PIN_TO_PORT_BASE(pin) GPIO_PORT_TO_BASE(PIN_TO_PORT(pin)) /*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - /* Initialize LED2 (Green) and LED3 (Blue) */ - GPIO_SOFTWARE_CONTROL(GPIO_B_BASE, LEDS_PORTB_PIN_MASK); - GPIO_SET_OUTPUT(GPIO_B_BASE, LEDS_PORTB_PIN_MASK); - GPIO_CLR_PIN(GPIO_B_BASE, LEDS_PORTB_PIN_MASK); +#define gpio_hal_arch_interrupt_enable(p) \ + GPIO_ENABLE_INTERRUPT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) - /* Initialize LED1 (Red) */ - GPIO_SOFTWARE_CONTROL(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - GPIO_SET_OUTPUT(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - GPIO_CLR_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); -} +#define gpio_hal_arch_interrupt_disable(p) \ + GPIO_DISABLE_INTERRUPT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) + +#define gpio_hal_arch_pin_set_input(p) do { \ + GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ + GPIO_SET_INPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ +} while(0); + +#define gpio_hal_arch_pin_set_output(p) do { \ + GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ + GPIO_SET_OUTPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ +} while(0); + +#define gpio_hal_arch_set_pin(p) \ + GPIO_SET_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) + +#define gpio_hal_arch_clear_pin(p) \ + GPIO_CLR_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) + +#define gpio_hal_arch_read_pin(p) \ + (GPIO_READ_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) == 0 ? 0 : 1) /*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - uint8_t mask_leds; - - mask_leds = GPIO_READ_PIN(LEDS_GREEN_PORT_BASE, LEDS_GREEN_PIN_MASK) == 0 ? 0: LEDS_GREEN; - mask_leds |= GPIO_READ_PIN(LEDS_BLUE_PORT_BASE, LEDS_BLUE_PIN_MASK) == 0 ? 0 : LEDS_BLUE; - mask_leds |= GPIO_READ_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK) == 0 ? 0 : LEDS_RED; - - return mask_leds; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - if(leds & LEDS_GREEN) { - GPIO_SET_PIN(LEDS_GREEN_PORT_BASE, LEDS_GREEN_PIN_MASK); - } else { - GPIO_CLR_PIN(LEDS_GREEN_PORT_BASE, LEDS_GREEN_PIN_MASK); - } - - if(leds & LEDS_BLUE) { - GPIO_SET_PIN(LEDS_BLUE_PORT_BASE, LEDS_BLUE_PIN_MASK); - } else { - GPIO_CLR_PIN(LEDS_BLUE_PORT_BASE, LEDS_BLUE_PIN_MASK); - } - - if(leds & LEDS_RED) { - GPIO_SET_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - } else { - GPIO_CLR_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - } -} +#endif /* GPIO_HAL_ARCH_H_ */ /*---------------------------------------------------------------------------*/ /** * @} diff --git a/arch/cpu/cc2538/dev/gpio.c b/arch/cpu/cc2538/dev/gpio.c index a09ca6dc3..c5c72594b 100644 --- a/arch/cpu/cc2538/dev/gpio.c +++ b/arch/cpu/cc2538/dev/gpio.c @@ -37,46 +37,13 @@ */ #include "contiki.h" #include "dev/leds.h" +#include "dev/gpio-hal.h" #include "dev/gpio.h" #include "dev/nvic.h" #include "reg.h" #include "lpm.h" #include - -/** - * \brief Pointer to a function to be called when a GPIO interrupt is detected. - * Callbacks for Port A, Pins[0:7] are stored in positions [0:7] of this - * buffer, Port B callbacks in [8:15] and so on - */ -static gpio_callback_t gpio_callbacks[32]; -/*---------------------------------------------------------------------------*/ -void -gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin) -{ - gpio_callbacks[(port << 3) + pin] = f; -} -/*---------------------------------------------------------------------------*/ -/** \brief Run through all registered GPIO callbacks and invoke those - * associated with the \a port and the pins specified by \a mask - * \param mask Search callbacks associated with pins specified by this mask - * \param port Search callbacks associated with this port. Here, port is - * specified as a number between 0 and 3. Port A: 0, Port B: 1 etc */ -void -notify(uint8_t mask, uint8_t port) -{ - uint8_t i; - gpio_callback_t *f = &gpio_callbacks[port << 3]; - - for(i = 0; i < 8; i++) { - if(mask & (1 << i)) { - if((*f) != NULL) { - (*f)(port, i); - } - } - f++; - } -} /*---------------------------------------------------------------------------*/ /** \brief Interrupt service routine for Port \a port * \param port Number between 0 and 3. Port A: 0, Port B: 1, etc. @@ -93,7 +60,7 @@ gpio_port_isr(uint8_t port) int_status = GPIO_GET_MASKED_INT_STATUS(base); power_up_int_status = GPIO_GET_POWER_UP_INT_STATUS(port); - notify(int_status | power_up_int_status, port); + gpio_hal_event_handler((int_status | power_up_int_status) << (port << 3)); GPIO_CLEAR_INTERRUPT(base, int_status); GPIO_CLEAR_POWER_UP_INTERRUPT(port, power_up_int_status); @@ -110,9 +77,4 @@ GPIO_PORT_ISR(b, B) GPIO_PORT_ISR(c, C) GPIO_PORT_ISR(d, D) /*---------------------------------------------------------------------------*/ -void -gpio_init() -{ - memset(gpio_callbacks, 0, sizeof(gpio_callbacks)); -} /** @} */ diff --git a/arch/cpu/cc2538/dev/gpio.h b/arch/cpu/cc2538/dev/gpio.h index 00ee1b1dc..67b28cf0d 100644 --- a/arch/cpu/cc2538/dev/gpio.h +++ b/arch/cpu/cc2538/dev/gpio.h @@ -42,27 +42,12 @@ */ #ifndef GPIO_H_ #define GPIO_H_ - +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" #include "reg.h" #include - -/** - * \brief Type definition for callbacks invoked by the GPIO ISRs - * \param port The port that triggered the GPIO interrupt. \e port is passed - * by its numeric representation (Port A:0, B:1 etc). Defines for - * these numeric representations are GPIO_x_NUM - * \param pin The pin that triggered the interrupt, specified by number - * (0, 1, ..., 7) - * - * This is the prototype of a function pointer passed to - * gpio_register_callback(). These callbacks are registered on a port/pin - * basis. When a GPIO port generates an interrupt, if a callback has been - * registered for the port/pin combination, the ISR will invoke it. The ISR - * will pass the port/pin as arguments in that call, so that a developer can - * re-use the same callback for multiple port/pin combinations - */ -typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); /*---------------------------------------------------------------------------*/ /** \name Base addresses for the GPIO register instances * @{ @@ -341,6 +326,14 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * number. */ #define GPIO_PORT_TO_BASE(PORT) (GPIO_A_BASE + ((PORT) << 12)) + +/** + * \brief Converts a port/pin pair to GPIO HAL pin number + * \param PORT The port number in the range 0 - 3 (GPIO_n_NUM). + * \param PIN The pin number in the range 0 - 7. + * \return The pin representation using GPIO HAL semantics + */ +#define GPIO_PORT_PIN_TO_GPIO_HAL_PIN(PORT, PIN) (((PORT) << 3) + (PIN)) /** @} */ /*---------------------------------------------------------------------------*/ /** \name GPIO Register offset declarations @@ -612,21 +605,6 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); #define GPIO_IRQ_DETECT_UNMASK_PAIACK0 0x00000001 /**< Port A bit 0 */ /** @} */ /*---------------------------------------------------------------------------*/ -/** \brief Initialise the GPIO module */ -void gpio_init(); - -/** - * \brief Register GPIO callback - * \param f Pointer to a function to be called when \a pin of \a port - * generates an interrupt - * \param port Associate \a f with this port. \e port must be specified with - * its numeric representation (Port A:0, B:1 etc). Defines for these - * numeric representations are GPIO_x_NUM - * \param pin Associate \a f with this pin, which is specified by number - * (0, 1, ..., 7) - */ -void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin); - #endif /* GPIO_H_ */ /** diff --git a/arch/cpu/cc2538/dev/ioc.c b/arch/cpu/cc2538/dev/ioc.c index 53a9218a9..5bb631c46 100644 --- a/arch/cpu/cc2538/dev/ioc.c +++ b/arch/cpu/cc2538/dev/ioc.c @@ -56,6 +56,12 @@ ioc_set_over(uint8_t port, uint8_t pin, uint8_t over) ioc_over[(port << 3) + pin] = over; } /*---------------------------------------------------------------------------*/ +uint32_t +ioc_get_over(uint8_t port, uint8_t pin) +{ + return ioc_over[(port << 3) + pin] & 0x0F; +} +/*---------------------------------------------------------------------------*/ void ioc_set_sel(uint8_t port, uint8_t pin, uint8_t sel) { diff --git a/arch/cpu/cc2538/dev/ioc.h b/arch/cpu/cc2538/dev/ioc.h index 7fad9d275..ae14a616f 100644 --- a/arch/cpu/cc2538/dev/ioc.h +++ b/arch/cpu/cc2538/dev/ioc.h @@ -249,6 +249,22 @@ void ioc_init(); */ void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over); +/** + * \brief Get Port:Pin override function + * \param port The port as a number (PA: 0, PB: 1 etc) + * \param pin The pin as a number + * \return The override function + * + * The return value can be one of + * + * - IOC_OVERRIDE_OE: Output + * - IOC_OVERRIDE_PUE: Pull-Up + * - IOC_OVERRIDE_PDE: Pull-Down + * - IOC_OVERRIDE_ANA: Analog + * - IOC_OVERRIDE_DIS: Disabled + */ +uint32_t ioc_get_over(uint8_t port, uint8_t pin); + /** * \brief Function select for Port:Pin * \param port The port as a number (PA: 0, PB: 1 etc) diff --git a/arch/cpu/cc2538/soc.c b/arch/cpu/cc2538/soc.c index e0ab1a918..1aa910095 100644 --- a/arch/cpu/cc2538/soc.c +++ b/arch/cpu/cc2538/soc.c @@ -41,6 +41,7 @@ #include "dev/ioc.h" #include "dev/nvic.h" #include "dev/sys-ctrl.h" +#include "dev/gpio-hal.h" #include "lpm.h" #include "reg.h" #include "soc.h" @@ -123,7 +124,7 @@ soc_init() clock_init(); lpm_init(); rtimer_init(); - gpio_init(); + gpio_hal_init(); } /*----------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/cpu/cc2538/usb/cdc-acm-descriptors.c b/arch/cpu/cc2538/usb/cdc-acm-descriptors.c index eb2a9d7b3..fd56ed303 100644 --- a/arch/cpu/cc2538/usb/cdc-acm-descriptors.c +++ b/arch/cpu/cc2538/usb/cdc-acm-descriptors.c @@ -161,7 +161,7 @@ const struct configuration_st { }; -const struct usb_st_configuration_descriptor const *configuration_head = -(struct usb_st_configuration_descriptor const *)&configuration_block; +const struct usb_st_configuration_descriptor* const configuration_head = +(const struct usb_st_configuration_descriptor*)&configuration_block; /** @} */ diff --git a/arch/cpu/cc2538/usb/common/descriptors.h b/arch/cpu/cc2538/usb/common/descriptors.h index f54184395..6c89f3c03 100644 --- a/arch/cpu/cc2538/usb/common/descriptors.h +++ b/arch/cpu/cc2538/usb/common/descriptors.h @@ -6,5 +6,5 @@ #endif extern const struct usb_st_device_descriptor device_descriptor; -extern const struct usb_st_configuration_descriptor const *configuration_head; +extern const struct usb_st_configuration_descriptor* const configuration_head; #endif /* DESCRIPTORS_H_RPFUB8O7OV__ */ diff --git a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx index 7c6ab55b3..979d7f5e4 100644 --- a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -32,7 +32,7 @@ CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c soc-rtc.c uart.c CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c aux-ctrl.c CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c adc-sensor.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c -CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c oscillators.c +CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c gpio-hal-arch.c oscillators.c CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c CONTIKI_CPU_SOURCEFILES += ble-cc2650.c ble-hal-cc26xx.c ble-addr.c rf-ble-cmd.c CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c int-master.c diff --git a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h index e8720b5f4..7b914ac1e 100644 --- a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h +++ b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h @@ -99,6 +99,10 @@ /* Path to headers with implementation of mutexes and memory barriers */ #define MUTEX_CONF_ARCH_HEADER_PATH "mutex-cortex.h" #define MEMORY_BARRIER_CONF_ARCH_HEADER_PATH "memory-barrier-cortex.h" + +#define GPIO_HAL_CONF_ARCH_HDR_PATH "dev/gpio-hal-arch.h" +/*---------------------------------------------------------------------------*/ +#define GPIO_HAL_CONF_ARCH_SW_TOGGLE 0 /*---------------------------------------------------------------------------*/ #endif /* CC13XX_CC26XX_DEF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc26xx-cc13xx/clock.c b/arch/cpu/cc26xx-cc13xx/clock.c index 981bbb4b2..172d1c3fd 100644 --- a/arch/cpu/cc26xx-cc13xx/clock.c +++ b/arch/cpu/cc26xx-cc13xx/clock.c @@ -124,7 +124,7 @@ update_clock_variable(void) count = (aon_rtc_secs_now * CLOCK_SECOND) + (aon_rtc_ticks_now >> 9); } /*---------------------------------------------------------------------------*/ -CCIF clock_time_t +clock_time_t clock_time(void) { update_clock_variable(); @@ -142,7 +142,7 @@ clock_update(void) } } /*---------------------------------------------------------------------------*/ -CCIF unsigned long +unsigned long clock_seconds(void) { bool interrupts_disabled; diff --git a/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c b/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c index 1f736bb53..c88b2e5fe 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c +++ b/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c @@ -39,7 +39,6 @@ #include "contiki.h" #include "lib/sensors.h" #include "dev/adc-sensor.h" -#include "gpio-interrupt.h" #include "sys/timer.h" #include "lpm.h" diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c new file mode 100644 index 000000000..a7b025800 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx-gpio-hal + * @{ + * + * \file + * Implementation file for the CC13xx/CC26xx GPIO HAL functions + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "ti-lib.h" +#include "ti-lib-rom.h" +#include "dev/gpio-hal.h" + +#include +/*---------------------------------------------------------------------------*/ +#define CONFIG_MASK (IOC_IOPULL_M | IOC_INT_M | IOC_IOMODE_OPEN_SRC_INV) +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg) +{ + uint32_t config; + gpio_hal_pin_cfg_t tmp; + + /* Clear settings that we are about to change, keep everything else */ + config = ti_lib_rom_ioc_port_configure_get(pin); + config &= ~CONFIG_MASK; + + tmp = cfg & GPIO_HAL_PIN_CFG_EDGE_BOTH; + if(tmp == GPIO_HAL_PIN_CFG_EDGE_NONE) { + config |= IOC_NO_EDGE; + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_RISING) { + config |= IOC_RISING_EDGE; + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_FALLING) { + config |= IOC_FALLING_EDGE; + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_BOTH) { + config |= IOC_BOTH_EDGES; + } + + tmp = cfg & GPIO_HAL_PIN_CFG_PULL_MASK; + if(tmp == GPIO_HAL_PIN_CFG_PULL_NONE) { + config |= IOC_NO_IOPULL; + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_DOWN) { + config |= IOC_IOPULL_DOWN; + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_UP) { + config |= IOC_IOPULL_UP; + } + + tmp = cfg & GPIO_HAL_PIN_CFG_INT_MASK; + if(tmp == GPIO_HAL_PIN_CFG_INT_DISABLE) { + config |= IOC_INT_DISABLE; + } else if(tmp == GPIO_HAL_PIN_CFG_INT_ENABLE) { + config |= IOC_INT_ENABLE; + } + + ti_lib_rom_ioc_port_configure_set(pin, IOC_PORT_GPIO, config); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_cfg_t +gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin) +{ + gpio_hal_pin_cfg_t cfg; + uint32_t tmp; + uint32_t config; + + cfg = 0; + config = ti_lib_rom_ioc_port_configure_get(pin); + + /* Pull */ + tmp = config & IOC_IOPULL_M; + if(tmp == IOC_IOPULL_UP) { + cfg |= GPIO_HAL_PIN_CFG_PULL_UP; + } else if(tmp == IOC_IOPULL_DOWN) { + cfg |= GPIO_HAL_PIN_CFG_PULL_DOWN; + } else if(tmp == IOC_NO_IOPULL) { + cfg |= GPIO_HAL_PIN_CFG_PULL_NONE; + } + + /* Interrupt enable/disable */ + tmp = config & IOC_INT_ENABLE; + if(tmp == IOC_INT_DISABLE) { + cfg |= GPIO_HAL_PIN_CFG_INT_DISABLE; + } else if(tmp == IOC_INT_ENABLE) { + cfg |= GPIO_HAL_PIN_CFG_INT_ENABLE; + } + + /* Edge detection */ + tmp = config & IOC_BOTH_EDGES; + if(tmp == IOC_NO_EDGE) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_NONE; + } else if(tmp == IOC_FALLING_EDGE) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_FALLING; + } else if(tmp == IOC_RISING_EDGE) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_RISING; + } else if(tmp == IOC_BOTH_EDGES) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_BOTH; + } + + return cfg; +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_mask_t +gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_pin_mask_t oe_pins; + + /* For pins configured as output we need to read DOUT31_0 */ + oe_pins = ti_lib_gpio_get_output_enable_multi_dio(pins); + + pins &= ~oe_pins; + + return (HWREG(GPIO_BASE + GPIO_O_DOUT31_0) & oe_pins) | + ti_lib_gpio_read_multi_dio(pins); +} +/*---------------------------------------------------------------------------*/ +uint8_t +gpio_hal_arch_read_pin(gpio_hal_pin_t pin) +{ + if(ti_lib_gpio_get_output_enable_dio(pin)) { + return (HWREG(GPIO_BASE + GPIO_O_DOUT31_0) >> pin) & 1; + } + + return ti_lib_gpio_read_dio(pin); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h new file mode 100644 index 000000000..7d87670c5 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx + * @{ + * + * \defgroup cc26xx-gpio-hal CC13xx/CC26xx GPIO HAL implementation + * + * @{ + * + * \file + * Header file for the CC13xx/CC26xx GPIO HAL functions + * + * \note + * Do not include this header directly + */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_HAL_ARCH_H_ +#define GPIO_HAL_ARCH_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "ti-lib.h" +#include "ti-lib-rom.h" + +#include +/*---------------------------------------------------------------------------*/ +#define gpio_hal_arch_interrupt_enable(p) interrupt_enable(p) +#define gpio_hal_arch_interrupt_disable(p) ti_lib_rom_ioc_int_disable(p) + +#define gpio_hal_arch_pin_set_input(p) ti_lib_rom_ioc_pin_type_gpio_input(p) +#define gpio_hal_arch_pin_set_output(p) ti_lib_rom_ioc_pin_type_gpio_output(p) + +#define gpio_hal_arch_set_pin(p) ti_lib_gpio_set_dio(p) +#define gpio_hal_arch_clear_pin(p) ti_lib_gpio_clear_dio(p) +#define gpio_hal_arch_toggle_pin(p) ti_lib_gpio_toggle_dio(p) +#define gpio_hal_arch_write_pin(p, v) ti_lib_gpio_write_dio(p, v) + +#define gpio_hal_arch_set_pins(p) ti_lib_gpio_set_multi_dio(p) +#define gpio_hal_arch_clear_pins(p) ti_lib_gpio_clear_multi_dio(p) +#define gpio_hal_arch_toggle_pins(p) ti_lib_gpio_toggle_multi_dio(p) +#define gpio_hal_arch_write_pins(p, v) ti_lib_gpio_write_multi_dio(p, v) +/*---------------------------------------------------------------------------*/ +static inline void +interrupt_enable(gpio_hal_pin_t pin) +{ + ti_lib_gpio_clear_event_dio(pin); + ti_lib_rom_ioc_int_enable(pin); +} +/*---------------------------------------------------------------------------*/ +#endif /* GPIO_HAL_ARCH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c b/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c index 348d0646a..c90e9239d 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c +++ b/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c @@ -29,72 +29,33 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup cc26xx-gpio-interrupts + * \addtogroup cc26xx * @{ * * \file - * Implementation of CC13xx/CC26xx GPIO interrupt handling. + * CC13xx/CC26xx GPIO interrupt ISR. */ /*---------------------------------------------------------------------------*/ -#include "ioc.h" -#include "gpio-interrupt.h" -#include "lpm.h" +#include "contiki.h" +#include "dev/gpio-hal.h" #include "ti-lib.h" #include /*---------------------------------------------------------------------------*/ #define gpio_interrupt_isr GPIOIntHandler /*---------------------------------------------------------------------------*/ -/* Handler array */ -static gpio_interrupt_handler_t handlers[NUM_IO_MAX]; -/*---------------------------------------------------------------------------*/ -void -gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f) -{ - uint8_t interrupts_disabled = ti_lib_int_master_disable(); - - /* Clear interrupts on specified pins */ - ti_lib_gpio_clear_event_dio(ioid); - - handlers[ioid] = f; - - /* Re-enable interrupts */ - if(!interrupts_disabled) { - ti_lib_int_master_enable(); - } -} -/*---------------------------------------------------------------------------*/ -void -gpio_interrupt_init() -{ - int i; - - for(i = 0; i < NUM_IO_MAX; i++) { - handlers[i] = NULL; - } - - ti_lib_int_enable(INT_AON_GPIO_EDGE); -} -/*---------------------------------------------------------------------------*/ void gpio_interrupt_isr(void) { - uint32_t pin_mask; - uint8_t i; + gpio_hal_pin_mask_t pin_mask; /* Read interrupt flags */ pin_mask = (HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) & GPIO_DIO_ALL_MASK); + gpio_hal_event_handler(pin_mask); + /* Clear the interrupt flags */ HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) = pin_mask; - - /* Run custom ISRs */ - for(i = 0; i < NUM_IO_MAX; i++) { - /* Call the handler if there is one registered for this event */ - if((pin_mask & (1 << i)) && handlers[i] != NULL) { - handlers[i](i); - } - } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c b/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c index cf1676570..a5479a4ee 100644 --- a/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c @@ -263,6 +263,20 @@ static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4); static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN(4); static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN(4); +#define RX_BUF_INCLUDE_CRC 1 +#define RX_BUF_INCLUDE_RSSI 1 +#define RX_BUF_INCLUDE_CORR 1 +#define RX_BUF_INCLUDE_TIMESTAMP 1 + +/* The size of the metadata (excluding the packet length field) */ +#define RX_BUF_METADATA_SIZE \ + (2 * RX_BUF_INCLUDE_CRC + RX_BUF_INCLUDE_RSSI + RX_BUF_INCLUDE_CORR + 4 * RX_BUF_INCLUDE_TIMESTAMP) + +/* The offset of the packet length in a rx buffer */ +#define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t) +/* The offset of the packet data in a rx buffer */ +#define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + 1) + /* The RX Data Queue */ static dataQueue_t rx_data_queue = { 0 }; @@ -565,22 +579,22 @@ init_rx_buffers(void) entry = (rfc_dataEntry_t *)rx_buf_0; entry->pNextEntry = rx_buf_1; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); entry = (rfc_dataEntry_t *)rx_buf_1; entry->pNextEntry = rx_buf_2; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); entry = (rfc_dataEntry_t *)rx_buf_2; entry->pNextEntry = rx_buf_3; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); entry = (rfc_dataEntry_t *)rx_buf_3; entry->pNextEntry = rx_buf_0; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); } /*---------------------------------------------------------------------------*/ static void @@ -601,11 +615,11 @@ init_rf_params(void) cmd->rxConfig.bAutoFlushCrc = 1; cmd->rxConfig.bAutoFlushIgn = 0; cmd->rxConfig.bIncludePhyHdr = 0; - cmd->rxConfig.bIncludeCrc = 1; - cmd->rxConfig.bAppendRssi = 1; - cmd->rxConfig.bAppendCorrCrc = 1; + cmd->rxConfig.bIncludeCrc = RX_BUF_INCLUDE_CRC; + cmd->rxConfig.bAppendRssi = RX_BUF_INCLUDE_RSSI; + cmd->rxConfig.bAppendCorrCrc = RX_BUF_INCLUDE_CORR; cmd->rxConfig.bAppendSrcInd = 0; - cmd->rxConfig.bAppendTimestamp = 1; + cmd->rxConfig.bAppendTimestamp = RX_BUF_INCLUDE_TIMESTAMP; cmd->pRxQ = &rx_data_queue; cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats; @@ -1079,15 +1093,15 @@ read_frame(void *buf, unsigned short buf_len) return 0; } - if(rx_read_entry[8] < 4) { - PRINTF("RF: too short\n"); + len = rx_read_entry[RX_BUF_LENGTH_OFFSET]; + if(len <= RX_BUF_METADATA_SIZE) { + PRINTF("RF: too short!"); release_data_entry(); return 0; } - len = rx_read_entry[8] - 8; - + len -= RX_BUF_METADATA_SIZE; if(len > buf_len) { PRINTF("RF: too long\n"); @@ -1095,13 +1109,13 @@ read_frame(void *buf, unsigned short buf_len) return 0; } - memcpy(buf, (char *)&rx_read_entry[9], len); + memcpy(buf, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET, len); - last_rssi = (int8_t)rx_read_entry[9 + len + 2]; - last_corr_lqi = (uint8_t)rx_read_entry[9 + len + 3] & STATUS_CORRELATION; + last_rssi = (int8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 2]; + last_corr_lqi = (uint8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 3] & STATUS_CORRELATION; /* get the timestamp */ - memcpy(&rat_timestamp, (char *)rx_read_entry + 9 + len + 4, 4); + memcpy(&rat_timestamp, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET + len + 4, 4); last_packet_timestamp = calc_last_packet_timestamp(rat_timestamp); diff --git a/arch/cpu/msp430/leds-arch.c b/arch/cpu/msp430/leds-arch.c index fe63d8ae4..c8131ee3e 100644 --- a/arch/cpu/msp430/leds-arch.c +++ b/arch/cpu/msp430/leds-arch.c @@ -46,10 +46,10 @@ leds_arch_init(void) LEDS_PxOUT |= (LEDS_CONF_RED | LEDS_CONF_GREEN | LEDS_CONF_YELLOW); } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { - unsigned char leds; + leds_mask_t leds; leds = LEDS_PxOUT; return ((leds & LEDS_CONF_RED) ? 0 : LEDS_RED) | ((leds & LEDS_CONF_GREEN) ? 0 : LEDS_GREEN) @@ -57,7 +57,7 @@ leds_arch_get(void) } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char leds) +leds_arch_set(leds_mask_t leds) { LEDS_PxOUT = (LEDS_PxOUT & ~(LEDS_CONF_RED|LEDS_CONF_GREEN|LEDS_CONF_YELLOW)) | ((leds & LEDS_RED) ? 0 : LEDS_CONF_RED) diff --git a/arch/cpu/msp430/msp430-def.h b/arch/cpu/msp430/msp430-def.h index 2f14d7236..93e575702 100644 --- a/arch/cpu/msp430/msp430-def.h +++ b/arch/cpu/msp430/msp430-def.h @@ -79,9 +79,6 @@ typedef long off_t; /* Our clock resolution, this is the same as Unix HZ. */ #define CLOCK_CONF_SECOND 128UL -#define CCIF -#define CLIF - typedef int spl_t; spl_t splhigh_(void); diff --git a/arch/cpu/nrf52832/dev/clock.c b/arch/cpu/nrf52832/dev/clock.c index 68413c23b..496668ecb 100644 --- a/arch/cpu/nrf52832/dev/clock.c +++ b/arch/cpu/nrf52832/dev/clock.c @@ -116,7 +116,7 @@ clock_init(void) rtc_config(); } /*---------------------------------------------------------------------------*/ -CCIF clock_time_t +clock_time_t clock_time(void) { return (clock_time_t)(ticks & 0xFFFFFFFF); @@ -131,7 +131,7 @@ clock_update(void) } } /*---------------------------------------------------------------------------*/ -CCIF unsigned long +unsigned long clock_seconds(void) { return (unsigned long)ticks/CLOCK_CONF_SECOND; diff --git a/arch/dev/rgb-led/rgb-led.c b/arch/dev/rgb-led/rgb-led.c new file mode 100644 index 000000000..521583022 --- /dev/null +++ b/arch/dev/rgb-led/rgb-led.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup rgb-led + * @{ + * + * \file + * Implementation of the RGB LED driver. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/leds.h" +#include "dev/rgb-led/rgb-led.h" +/*---------------------------------------------------------------------------*/ +void +rgb_led_off(void) +{ + leds_off(LEDS_ALL); +} +/*----------------------------------------------------------------------------*/ +void +rgb_led_set(uint8_t colour) +{ + leds_mask_t leds = + ((colour & RGB_LED_RED) ? LEDS_RED : LEDS_COLOUR_NONE) | + ((colour & RGB_LED_GREEN) ? LEDS_GREEN : LEDS_COLOUR_NONE) | + ((colour & RGB_LED_BLUE) ? LEDS_BLUE : LEDS_COLOUR_NONE); + + leds_off(LEDS_ALL); + leds_on(leds); +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/dev/rgb-led/rgb-led.h b/arch/dev/rgb-led/rgb-led.h new file mode 100644 index 000000000..d0cd81d38 --- /dev/null +++ b/arch/dev/rgb-led/rgb-led.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef RGB_LED_H_ +#define RGB_LED_H_ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup dev + * @{ + */ +/*---------------------------------------------------------------------------*/ +/** + * \defgroup rgb-led Generic RGB LED driver + * + * This is a driver for a tri-color RGB LED part, such as for example the + * Broadcom (ex Avago Technologies) PLCC-4 Tricolor Black Surface LED present + * on all Zolertia Zoul-based boards. + * + * + * This driver sits on top of the LED HAL. Therefore, any port that wishes to + * use this driver should first implement the GPIO HAL and the new LED API. + * This driver will set the colour of the RGB LED by using combinations of + * LED_RED, LED_GREEN and LED_BLUE. Therefore, those must be correctly defined + * by the platform configuration. + * @{ + * + * \file + * Header file for the RGB LED driver. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include +/*---------------------------------------------------------------------------*/ +#define RGB_LED_RED 1 +#define RGB_LED_GREEN 2 +#define RGB_LED_BLUE 4 +#define RGB_LED_MAGENTA (RGB_LED_RED | RGB_LED_BLUE) +#define RGB_LED_YELLOW (RGB_LED_RED | RGB_LED_GREEN) +#define RGB_LED_CYAN (RGB_LED_GREEN | RGB_LED_BLUE ) +#define RGB_LED_WHITE (RGB_LED_RED | RGB_LED_GREEN | RGB_LED_BLUE) +/*---------------------------------------------------------------------------*/ +/** + * \brief Turn off the RGB LED + */ +void rgb_led_off(void); + +/** + * \brief Set the colour of the RGB LED + * \param colour The colour to set + * + * \e colour can take the value of one of the RGB_LED_xyz defines. + */ +void rgb_led_set(uint8_t colour); +/*---------------------------------------------------------------------------*/ +#endif /* RGB_LED_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/platform/cc2538dk/Makefile.cc2538dk b/arch/platform/cc2538dk/Makefile.cc2538dk index a9870079f..e7be95c28 100644 --- a/arch/platform/cc2538dk/Makefile.cc2538dk +++ b/arch/platform/cc2538dk/Makefile.cc2538dk @@ -6,7 +6,7 @@ endif CONTIKI_TARGET_DIRS = . dev -CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c +CONTIKI_TARGET_SOURCEFILES += leds-arch.c CONTIKI_TARGET_SOURCEFILES += platform.c CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c CONTIKI_TARGET_SOURCEFILES += button-sensor.c als-sensor.c @@ -19,8 +19,7 @@ CLEAN += *.cc2538dk CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538 include $(CONTIKI_CPU)/Makefile.cc2538 -MODULES += os/net os/net/mac os/net/mac/framer \ - os/storage/cfs +MODULES += os/storage/cfs PYTHON = python BSL_FLAGS += -e -w -v diff --git a/arch/platform/cc2538dk/contiki-conf.h b/arch/platform/cc2538dk/contiki-conf.h index 1a463a0be..649fde347 100644 --- a/arch/platform/cc2538dk/contiki-conf.h +++ b/arch/platform/cc2538dk/contiki-conf.h @@ -41,6 +41,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH diff --git a/arch/platform/cc2538dk/dev/board.h b/arch/platform/cc2538dk/dev/board.h index 6e3021ceb..0b2a4cd09 100644 --- a/arch/platform/cc2538dk/dev/board.h +++ b/arch/platform/cc2538dk/dev/board.h @@ -71,20 +71,25 @@ * @{ */ /*---------------------------------------------------------------------------*/ -#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */ -#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */ +#define LEDS_CONF_YELLOW 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_ORANGE 4 + +#define LEDS_ARCH_L1_PORT GPIO_C_NUM +#define LEDS_ARCH_L1_PIN 1 +#define LEDS_ARCH_L2_PORT GPIO_C_NUM +#define LEDS_ARCH_L2_PIN 2 +#define LEDS_ARCH_L3_PORT GPIO_C_NUM +#define LEDS_ARCH_L3_PIN 3 #if USB_SERIAL_CONF_ENABLE -#define LEDS_CONF_ALL 14 -#define LEDS_RED LEDS_ORANGE +#define LEDS_CONF_COUNT 3 #else -#define LEDS_CONF_ALL 15 -#define LEDS_RED 1 /**< LED1 (Red) -> PC0 */ +#define LEDS_ARCH_L4_PORT GPIO_C_NUM +#define LEDS_ARCH_L4_PIN 0 +#define LEDS_CONF_RED 8 +#define LEDS_CONF_COUNT 4 #endif - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/cc2538dk/dev/button-sensor.c b/arch/platform/cc2538dk/dev/button-sensor.c index 14d4e7d15..6c34bb847 100644 --- a/arch/platform/cc2538dk/dev/button-sensor.c +++ b/arch/platform/cc2538dk/dev/button-sensor.c @@ -88,15 +88,8 @@ config(uint32_t port_base, uint32_t pin_mask) GPIO_ENABLE_INTERRUPT(port_base, pin_mask); } /*---------------------------------------------------------------------------*/ -/** - * \brief Callback registered with the GPIO module. Gets fired with a button - * port/pin generates an interrupt - * \param port The port number that generated the interrupt - * \param pin The pin number that generated the interrupt. This is the pin - * absolute number (i.e. 0, 1, ..., 7), not a mask - */ static void -btn_callback(uint8_t port, uint8_t pin) +button_press_handler(gpio_hal_pin_mask_t pin_mask) { if(!timer_expired(&debouncetimer)) { return; @@ -104,19 +97,39 @@ btn_callback(uint8_t port, uint8_t pin) timer_set(&debouncetimer, CLOCK_SECOND / 8); - if((port == BUTTON_SELECT_PORT) && (pin == BUTTON_SELECT_PIN)) { + if(pin_mask & + (gpio_hal_pin_to_mask(BUTTON_SELECT_PIN) << (BUTTON_SELECT_PORT << 3))) { sensors_changed(&button_select_sensor); - } else if((port == BUTTON_LEFT_PORT) && (pin == BUTTON_LEFT_PIN)) { + } else if(pin_mask & + (gpio_hal_pin_to_mask(BUTTON_LEFT_PIN) << (BUTTON_LEFT_PORT << 3))) { sensors_changed(&button_left_sensor); - } else if((port == BUTTON_RIGHT_PORT) && (pin == BUTTON_RIGHT_PIN)) { + } else if(pin_mask & + (gpio_hal_pin_to_mask(BUTTON_RIGHT_PIN) << (BUTTON_RIGHT_PORT << 3))) { sensors_changed(&button_right_sensor); - } else if((port == BUTTON_UP_PORT) && (pin == BUTTON_UP_PIN)) { + } else if(pin_mask & + (gpio_hal_pin_to_mask(BUTTON_UP_PIN) << (BUTTON_UP_PORT << 3))) { sensors_changed(&button_up_sensor); - } else if((port == BUTTON_DOWN_PORT) && (pin == BUTTON_DOWN_PIN)) { + } else if(pin_mask & + (gpio_hal_pin_to_mask(BUTTON_DOWN_PIN) << (BUTTON_DOWN_PORT << 3))) { sensors_changed(&button_down_sensor); } } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t press_handler = { + .next = NULL, + .handler = button_press_handler, + .pin_mask = 0, +}; +/*---------------------------------------------------------------------------*/ +static void +register_btn_callback(uint8_t port_num, uint8_t pin) +{ + press_handler.pin_mask |= + gpio_hal_pin_to_mask(pin) << (port_num << 3); + + gpio_hal_register_handler(&press_handler); +} +/*---------------------------------------------------------------------------*/ /** * \brief Init function for the select button. * @@ -137,7 +150,7 @@ config_select(int type, int value) NVIC_EnableIRQ(BUTTON_SELECT_VECTOR); - gpio_register_callback(btn_callback, BUTTON_SELECT_PORT, BUTTON_SELECT_PIN); + register_btn_callback(BUTTON_SELECT_PORT, BUTTON_SELECT_PIN); return 1; } /*---------------------------------------------------------------------------*/ @@ -161,7 +174,7 @@ config_left(int type, int value) NVIC_EnableIRQ(BUTTON_LEFT_VECTOR); - gpio_register_callback(btn_callback, BUTTON_LEFT_PORT, BUTTON_LEFT_PIN); + register_btn_callback(BUTTON_LEFT_PORT, BUTTON_LEFT_PIN); return 1; } /*---------------------------------------------------------------------------*/ @@ -185,7 +198,7 @@ config_right(int type, int value) NVIC_EnableIRQ(BUTTON_RIGHT_VECTOR); - gpio_register_callback(btn_callback, BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN); + register_btn_callback(BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN); return 1; } /*---------------------------------------------------------------------------*/ @@ -209,7 +222,7 @@ config_up(int type, int value) NVIC_EnableIRQ(BUTTON_UP_VECTOR); - gpio_register_callback(btn_callback, BUTTON_UP_PORT, BUTTON_UP_PIN); + register_btn_callback(BUTTON_UP_PORT, BUTTON_UP_PIN); return 1; } /*---------------------------------------------------------------------------*/ @@ -233,7 +246,7 @@ config_down(int type, int value) NVIC_EnableIRQ(BUTTON_DOWN_VECTOR); - gpio_register_callback(btn_callback, BUTTON_DOWN_PORT, BUTTON_DOWN_PIN); + register_btn_callback(BUTTON_DOWN_PORT, BUTTON_DOWN_PIN); return 1; } /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/cc2538dk/dev/leds-arch.c b/arch/platform/cc2538dk/dev/leds-arch.c index 661f46160..c849355b4 100644 --- a/arch/platform/cc2538dk/dev/leds-arch.c +++ b/arch/platform/cc2538dk/dev/leds-arch.c @@ -1,16 +1,16 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * 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. @@ -28,45 +28,34 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup cc2538-smartrf - * @{ - * - * \defgroup cc2538dk-leds SmartRF06EB LED driver - * - * LED driver implementation for the TI SmartRF06EB + cc2538EM - * @{ - * - * \file - * LED driver implementation for the TI SmartRF06EB + cc2538EM - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "reg.h" #include "dev/leds.h" -#include "dev/gpio.h" +#include "dev/gpio-hal.h" +#include "dev/gpio-hal-arch.h" -#define LEDS_GPIO_PIN_MASK LEDS_ALL +#include /*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - GPIO_SET_OUTPUT(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return GPIO_READ_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - GPIO_WRITE_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK, leds); -} +const leds_t leds_arch_leds[] = { + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), + .negative_logic = false + }, +#if !USB_SERIAL_CONF_ENABLE + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L4_PORT, LEDS_ARCH_L4_PIN), + .negative_logic = false + }, +#endif +}; /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ + diff --git a/arch/platform/cc2538dk/platform.c b/arch/platform/cc2538dk/platform.c index 3897c6292..8add14292 100644 --- a/arch/platform/cc2538dk/platform.c +++ b/arch/platform/cc2538dk/platform.c @@ -74,7 +74,7 @@ #define LOG_LEVEL LOG_LEVEL_MAIN /*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; diff --git a/arch/platform/cooja/Makefile.cooja b/arch/platform/cooja/Makefile.cooja index 853e7eaf5..541ae51f0 100644 --- a/arch/platform/cooja/Makefile.cooja +++ b/arch/platform/cooja/Makefile.cooja @@ -40,9 +40,6 @@ ARCHIVE = $(OBJECTDIR)/$(LIBNAME).a JNILIB = $(OBJECTDIR)/$(LIBNAME).$(TARGET) CONTIKI_APP_OBJ = $(CONTIKI_APP).o -# Modules -MODULES += os/net os/net/mac os/net/mac/framer - ### COOJA platform sources COOJA = $(CONTIKI)/arch/platform/$(TARGET) CONTIKI_TARGET_DIRS = . dev lib sys cfs net diff --git a/arch/platform/cooja/contiki-conf.h b/arch/platform/cooja/contiki-conf.h index af7582ab9..5069e94e5 100644 --- a/arch/platform/cooja/contiki-conf.h +++ b/arch/platform/cooja/contiki-conf.h @@ -46,6 +46,8 @@ #define COOJA 1 +#define LEDS_CONF_LEGACY_API 1 + #ifndef EEPROM_CONF_SIZE #define EEPROM_CONF_SIZE 1024 #endif @@ -98,9 +100,6 @@ #define CC_CONF_VA_ARGS 1 #define CC_CONF_INLINE inline -#define CCIF -#define CLIF - /* These names are deprecated, use C99 names. */ #include typedef uint8_t u8_t; diff --git a/arch/platform/cooja/dev/leds-arch.c b/arch/platform/cooja/dev/leds-arch.c index db91e9baa..b65df2945 100644 --- a/arch/platform/cooja/dev/leds-arch.c +++ b/arch/platform/cooja/dev/leds-arch.c @@ -34,18 +34,18 @@ const struct simInterface leds_interface; // COOJA variables -unsigned char simLedsValue; +leds_mask_t simLedsValue; /*-----------------------------------------------------------------------------------*/ void leds_arch_init() { simLedsValue = 0; } /*-----------------------------------------------------------------------------------*/ -unsigned char leds_arch_get() { +leds_mask_t leds_arch_get() { return simLedsValue; } /*-----------------------------------------------------------------------------------*/ -void leds_arch_set(unsigned char leds) { +void leds_arch_set(leds_mask_t leds) { if(leds != simLedsValue) { simLedsValue = leds; } diff --git a/arch/platform/jn516x/Makefile.jn516x b/arch/platform/jn516x/Makefile.jn516x index d7aa80992..ecdcc2f58 100644 --- a/arch/platform/jn516x/Makefile.jn516x +++ b/arch/platform/jn516x/Makefile.jn516x @@ -143,8 +143,6 @@ endif CLEAN += *.jn516x CLEAN += *.jn516x.bin -MODULES += os/net os/net/mac os/net/mac/framer - CONTIKI_TARGET_SOURCEFILES += $(ARCH) CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) diff --git a/arch/platform/jn516x/dev/dongle/leds-arch.c b/arch/platform/jn516x/dev/dongle/leds-arch.c index 5eff3c63e..513d52b76 100644 --- a/arch/platform/jn516x/dev/dongle/leds-arch.c +++ b/arch/platform/jn516x/dev/dongle/leds-arch.c @@ -38,7 +38,7 @@ #define LED_G (1 << 16) #define LED_R (1 << 17) -static volatile uint8_t leds; +static volatile leds_mask_t leds; /*---------------------------------------------------------------------------*/ void @@ -49,14 +49,14 @@ leds_arch_init(void) leds = 0; } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { return leds; } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char c) +leds_arch_set(leds_mask_t c) { uint32 on_mask = 0; uint32 off_mask = 0; diff --git a/arch/platform/jn516x/jn516x-def.h b/arch/platform/jn516x/jn516x-def.h index 4861d00b3..596d55333 100644 --- a/arch/platform/jn516x/jn516x-def.h +++ b/arch/platform/jn516x/jn516x-def.h @@ -196,6 +196,8 @@ typedef uint32_t rtimer_clock_t; #define PLATFORM_HAS_SHT11 0 #define PLATFORM_HAS_RADIO 1 +#define LEDS_CONF_LEGACY_API 1 + #define PLATFORM_CONF_PROVIDES_MAIN_LOOP 1 /* CPU target speed in Hz @@ -217,9 +219,6 @@ typedef uint32_t rtimer_clock_t; #define CC_CONF_VA_ARGS 1 #define CC_CONF_INLINE inline -#define CCIF -#define CLIF - #ifdef HAVE_STDINT_H #include #else diff --git a/arch/platform/native/Makefile.native b/arch/platform/native/Makefile.native index 2d1ee4fbc..24f433796 100644 --- a/arch/platform/native/Makefile.native +++ b/arch/platform/native/Makefile.native @@ -33,5 +33,3 @@ MAKE_MAC ?= MAKE_MAC_NULLMAC ### Define the CPU directory CONTIKI_CPU=$(CONTIKI)/arch/cpu/native include $(CONTIKI)/arch/cpu/native/Makefile.native - -MODULES+=os/net os/net/mac os/net/mac/framer diff --git a/arch/platform/native/contiki-conf.h b/arch/platform/native/contiki-conf.h index 3a0329a82..b8a43a604 100644 --- a/arch/platform/native/contiki-conf.h +++ b/arch/platform/native/contiki-conf.h @@ -58,9 +58,6 @@ int select_set_callback(int fd, const struct select_callback *callback); #define EEPROM_CONF_SIZE 1024 #endif -#define CCIF -#define CLIF - /* These names are deprecated, use C99 names. */ typedef uint8_t u8_t; typedef uint16_t u16_t; @@ -69,6 +66,8 @@ typedef int32_t s32_t; typedef unsigned int uip_stats_t; +#define LEDS_CONF_LEGACY_API 1 + #ifndef UIP_CONF_BYTE_ORDER #define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN #endif diff --git a/arch/platform/native/dev/leds-arch.c b/arch/platform/native/dev/leds-arch.c index 1308c57dc..07addc84e 100644 --- a/arch/platform/native/dev/leds-arch.c +++ b/arch/platform/native/dev/leds-arch.c @@ -38,7 +38,7 @@ */ #include "dev/leds.h" -static unsigned char leds; +static leds_mask_t leds; /*---------------------------------------------------------------------------*/ void leds_arch_init(void) @@ -46,14 +46,14 @@ leds_arch_init(void) leds = 0; } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { return leds; } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char l) +leds_arch_set(leds_mask_t l) { leds = l; } diff --git a/arch/platform/native/platform.c b/arch/platform/native/platform.c index 4d1a1421c..fceab0207 100644 --- a/arch/platform/native/platform.c +++ b/arch/platform/native/platform.c @@ -111,7 +111,12 @@ static const struct select_callback *select_callback[SELECT_MAX]; static int select_max = 0; -static uint8_t serial_id[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; +#ifdef PLATFORM_CONF_MAC_ADDR +static uint8_t mac_addr[] = PLATFORM_CONF_MAC_ADDR; +#else /* 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 */ @@ -177,12 +182,12 @@ set_lladdr(void) memset(&addr, 0, sizeof(linkaddr_t)); #if NETSTACK_CONF_WITH_IPV6 - memcpy(addr.u8, serial_id, sizeof(addr.u8)); + 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] = serial_id[7 - i]; + addr.u8[i] = mac_addr[7 - i]; } } else { addr.u8[0] = node_id & 0xff; @@ -253,6 +258,7 @@ void platform_init_stage_two() { set_lladdr(); + serial_line_init(); } /*---------------------------------------------------------------------------*/ void diff --git a/arch/platform/nrf52dk/Makefile.nrf52dk b/arch/platform/nrf52dk/Makefile.nrf52dk index 9c3778a73..6187fc532 100644 --- a/arch/platform/nrf52dk/Makefile.nrf52dk +++ b/arch/platform/nrf52dk/Makefile.nrf52dk @@ -27,5 +27,3 @@ SMALL ?= 0 ### Define the CPU directory and pull in the correct CPU makefile. CONTIKI_CPU=$(CONTIKI)/arch/cpu/nrf52832 include $(CONTIKI_CPU)/Makefile.nrf52832 - -MODULES += os/net os/net/mac os/net/mac/framer diff --git a/arch/platform/nrf52dk/contiki-conf.h b/arch/platform/nrf52dk/contiki-conf.h index f7b8b1fa1..7b3b66314 100644 --- a/arch/platform/nrf52dk/contiki-conf.h +++ b/arch/platform/nrf52dk/contiki-conf.h @@ -41,6 +41,7 @@ #define CONTIKI_CONF_H #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH diff --git a/arch/platform/nrf52dk/dev/leds-arch.c b/arch/platform/nrf52dk/dev/leds-arch.c index 019589493..cda1317ef 100644 --- a/arch/platform/nrf52dk/dev/leds-arch.c +++ b/arch/platform/nrf52dk/dev/leds-arch.c @@ -55,14 +55,14 @@ leds_arch_init(void) LEDS_OFF(LEDS_MASK); } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { - return (unsigned char)(LED_IS_ON(LEDS_MASK) >> LED_START); + return (leds_mask_t)(LED_IS_ON(LEDS_MASK) >> LED_START); } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char leds) +leds_arch_set(leds_mask_t leds) { unsigned int mask = (unsigned int)leds << LED_START; LEDS_OFF(LEDS_MASK); diff --git a/arch/platform/nrf52dk/nrf52dk-def.h b/arch/platform/nrf52dk/nrf52dk-def.h index ea4060ca2..0e387f0f0 100644 --- a/arch/platform/nrf52dk/nrf52dk-def.h +++ b/arch/platform/nrf52dk/nrf52dk-def.h @@ -60,16 +60,17 @@ * @{ */ #define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_LEGACY_API 1 #define LEDS_1 (1 << (LED_1 - LED_START)) // 1 #define LEDS_2 (1 << (LED_2 - LED_START)) // 2 #define LEDS_3 (1 << (LED_3 - LED_START)) // 4 #define LEDS_4 (1 << (LED_4 - LED_START)) // 8 -#define LEDS_GREEN LEDS_1 -#define LEDS_YELLOW LEDS_2 -#define LEDS_RED LEDS_3 -#define LEDS_BLUE LEDS_4 +#define LEDS_CONF_GREEN LEDS_1 +#define LEDS_CONF_YELLOW LEDS_2 +#define LEDS_CONF_RED LEDS_3 +#define LEDS_CONF_BLUE LEDS_4 #define LEDS_CONF_ALL (LEDS_1 | LEDS_2 | LEDS_3 | LEDS_4) diff --git a/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 b/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 index 94174a0a1..37967fdde 100644 --- a/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 +++ b/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 @@ -26,8 +26,7 @@ CLEAN += *.openmote-cc2538 CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538 include $(CONTIKI_CPU)/Makefile.cc2538 -MODULES += os/net os/net/mac os/net/mac/framer \ - os/storage/cfs +MODULES += os/storage/cfs PYTHON = python BSL_FLAGS += -e --bootloader-invert-lines -w -v -b 450000 diff --git a/arch/platform/openmote-cc2538/board.h b/arch/platform/openmote-cc2538/board.h index 56724a753..f7fbfc6c2 100644 --- a/arch/platform/openmote-cc2538/board.h +++ b/arch/platform/openmote-cc2538/board.h @@ -63,14 +63,21 @@ * @{ */ /*---------------------------------------------------------------------------*/ -#define LEDS_RED 16 /**< LED1 (Red) -> PC4 */ -#define LEDS_YELLOW 64 /**< LED2 (Yellow) -> PC6 */ -#define LEDS_GREEN 128 /**< LED3 (Green) -> PC7 */ -#define LEDS_ORANGE 32 /**< LED4 (Orange) -> PC5 */ -#define LEDS_CONF_ALL 240 +#define LEDS_ARCH_L1_PORT GPIO_C_NUM +#define LEDS_ARCH_L1_PIN 4 +#define LEDS_ARCH_L2_PORT GPIO_C_NUM +#define LEDS_ARCH_L2_PIN 6 +#define LEDS_ARCH_L3_PORT GPIO_C_NUM +#define LEDS_ARCH_L3_PIN 7 +#define LEDS_ARCH_L4_PORT GPIO_C_NUM +#define LEDS_ARCH_L4_PIN 5 -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 +#define LEDS_CONF_GREEN 4 +#define LEDS_CONF_ORANGE 8 + +#define LEDS_CONF_COUNT 4 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/openmote-cc2538/contiki-conf.h b/arch/platform/openmote-cc2538/contiki-conf.h index d9f0b047e..daa203065 100644 --- a/arch/platform/openmote-cc2538/contiki-conf.h +++ b/arch/platform/openmote-cc2538/contiki-conf.h @@ -50,6 +50,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH diff --git a/arch/platform/openmote-cc2538/dev/button-sensor.c b/arch/platform/openmote-cc2538/dev/button-sensor.c index 9c6a7d6c8..a6c5fe2d8 100644 --- a/arch/platform/openmote-cc2538/dev/button-sensor.c +++ b/arch/platform/openmote-cc2538/dev/button-sensor.c @@ -95,15 +95,8 @@ value(int type) return 0; } /*---------------------------------------------------------------------------*/ -/** - * \brief Callback registered with the GPIO module. Gets fired with a button - * port/pin generates an interrupt - * \param port The port number that generated the interrupt - * \param pin The pin number that generated the interrupt. This is the pin - * absolute number (i.e. 0, 1, ..., 7), not a mask - */ static void -btn_callback(uint8_t port, uint8_t pin) +button_press_handler(gpio_hal_pin_mask_t pin_mask) { if(!timer_expired(&debouncetimer)) { return; @@ -124,6 +117,12 @@ btn_callback(uint8_t port, uint8_t pin) sensors_changed(&button_sensor); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t press_handler = { + .next = NULL, + .handler = button_press_handler, + .pin_mask = gpio_hal_pin_to_mask(BUTTON_USER_PIN) << (BUTTON_USER_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ /** * \brief Init function for the User button. * \param type SENSORS_ACTIVE: Activate / Deactivate the sensor (value == 1 @@ -153,7 +152,7 @@ config_user(int type, int value) ioc_set_over(BUTTON_USER_PORT, BUTTON_USER_PIN, IOC_OVERRIDE_PUE); - gpio_register_callback(btn_callback, BUTTON_USER_PORT, BUTTON_USER_PIN); + gpio_hal_register_handler(&press_handler); break; case SENSORS_ACTIVE: if(value) { diff --git a/arch/platform/openmote-cc2538/dev/leds-arch.c b/arch/platform/openmote-cc2538/dev/leds-arch.c index 28454dacf..2bc13bed8 100644 --- a/arch/platform/openmote-cc2538/dev/leds-arch.c +++ b/arch/platform/openmote-cc2538/dev/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * 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 @@ -26,48 +27,32 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup openmote-cc2538 - * @{ - * - * \defgroup openmote-leds OpenMote-CC2538 LED driver - * @{ - * - * \file - * LED driver implementation for the OpenMote-CC2538 platform */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "reg.h" #include "dev/leds.h" -#include "dev/gpio.h" +#include "dev/gpio-hal.h" + +#include /*---------------------------------------------------------------------------*/ -#define LEDS_GPIO_PIN_MASK LEDS_ALL +const leds_t leds_arch_leds[] = { + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L4_PORT, LEDS_ARCH_L4_PIN), + .negative_logic = false + }, +}; /*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - GPIO_SET_OUTPUT(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return GPIO_READ_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - GPIO_WRITE_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK, leds); -} -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ + + diff --git a/arch/platform/openmote-cc2538/platform.c b/arch/platform/openmote-cc2538/platform.c index df1d74a47..4b390e51b 100644 --- a/arch/platform/openmote-cc2538/platform.c +++ b/arch/platform/openmote-cc2538/platform.c @@ -82,7 +82,7 @@ void board_init(void); /*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; diff --git a/arch/platform/sky/Makefile.sky b/arch/platform/sky/Makefile.sky index 9f86b6499..0398486b0 100644 --- a/arch/platform/sky/Makefile.sky +++ b/arch/platform/sky/Makefile.sky @@ -6,6 +6,4 @@ CONTIKI_TARGET_SOURCEFILES += contiki-sky-platform.c \ include $(CONTIKI)/arch/platform/sky/Makefile.common -MODULES += os/net/mac os/net/mac/framer os/net \ - arch/dev/cc2420 arch/dev/sht11 arch/dev/ds2411 \ - os/storage/cfs +MODULES += arch/dev/cc2420 arch/dev/sht11 arch/dev/ds2411 os/storage/cfs diff --git a/arch/platform/sky/sky-def.h b/arch/platform/sky/sky-def.h index 8640892af..edab43ee7 100644 --- a/arch/platform/sky/sky-def.h +++ b/arch/platform/sky/sky-def.h @@ -52,6 +52,9 @@ /* Delay between the SFD finishes arriving and it is detected in software */ #define RADIO_DELAY_BEFORE_DETECT 0 +/* Disable TSCH frame filtering */ +#define TSCH_CONF_HW_FRAME_FILTERING 0 + #define PLATFORM_HAS_LEDS 1 #define PLATFORM_HAS_BUTTON 1 #define PLATFORM_HAS_LIGHT 1 @@ -72,6 +75,8 @@ #define LEDS_CONF_GREEN 0x20 #define LEDS_CONF_YELLOW 0x40 +#define LEDS_CONF_LEGACY_API 1 + /* DCO speed resynchronization for more robust UART, etc. */ #ifndef DCOSYNCH_CONF_ENABLED #define DCOSYNCH_CONF_ENABLED (!(MAC_CONF_WITH_TSCH)) /* TSCH needs timerB diff --git a/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx b/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx index 393cb6286..7bead9fff 100644 --- a/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx +++ b/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx @@ -6,7 +6,7 @@ endif ### Board and BSP selection BOARD ?= srf06/cc26xx -BOARDS = srf06/cc26xx srf06/cc13xx launchpad/cc26xx launchpad/cc13xx sensortag/cc26xx sensortag/cc13xx +BOARDS = srf06/cc26xx srf06/cc13xx launchpad/cc2650 launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350 CONTIKI_TARGET_DIRS += . @@ -14,8 +14,7 @@ CONTIKI_TARGET_DIRS += . PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET) -include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(notdir $(BOARD)) -CONTIKI_TARGET_SOURCEFILES += platform.c -CONTIKI_TARGET_SOURCEFILES += sensors.c leds.c +CONTIKI_TARGET_SOURCEFILES += platform.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += $(BOARD_SOURCEFILES) CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) @@ -30,5 +29,3 @@ SMALL ?= 0 ### Makefile.cc26xx or Makefile.cc13xx CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc26xx-cc13xx include $(CONTIKI_CPU)/Makefile.$(CPU_FAMILY) - -MODULES += os/net os/net/mac os/net/mac/framer diff --git a/arch/platform/srf06-cc26xx/cfs-coffee-arch.h b/arch/platform/srf06-cc26xx/cfs-coffee-arch.h new file mode 100644 index 000000000..33cc5123b --- /dev/null +++ b/arch/platform/srf06-cc26xx/cfs-coffee-arch.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2008, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Coffee architecture-dependent header for the srf06-cc2650 sensortag platform. + * \author + * Dongda Lee + */ + +#ifndef CFS_COFFEE_ARCH_H +#define CFS_COFFEE_ARCH_H + +#include "contiki-conf.h" +#include "dev/xmem.h" + +/*** MX25R8035F Memory Organization +The memory is organized as: +8Mbit = 1048576 bytes (8 bits each) +256 sectors (32 Kbits, 4096 bytes each) +4096 pages (256 bytes each). +Each page can be individually programmed (bits are programmed from 1 to 0). The device is +sector or bulk erasable (bits are erased from 0 to 1) but not page erasable +*/ +#define COFFEE_XMEM_TOTAL_SIZE_KB 1024UL //Total size of the External Flash Memory in the Z1 + +/* Coffee configuration parameters. */ +#define COFFEE_SECTOR_SIZE 4096UL +#define COFFEE_PAGE_SIZE 256UL +#define COFFEE_START 0UL //COFFEE_SECTOR_SIZE +#define COFFEE_SIZE (COFFEE_XMEM_TOTAL_SIZE_KB * 1024UL - COFFEE_START) +#define COFFEE_NAME_LENGTH 16 +#define COFFEE_MAX_OPEN_FILES 6 +#define COFFEE_FD_SET_SIZE 8 +#define COFFEE_LOG_TABLE_LIMIT 256 +#define COFFEE_DYN_SIZE 2*1024 +#define COFFEE_LOG_SIZE 1024 + +#define COFFEE_MICRO_LOGS 1 + + + + + + +/* Flash operations. */ +#define COFFEE_WRITE(buf, size, offset) \ + xmem_pwrite((char *)(buf), (size), COFFEE_START + (offset)) + +#define COFFEE_READ(buf, size, offset) \ + xmem_pread((char *)(buf), (size), COFFEE_START + (offset)) + +#define COFFEE_ERASE(sector) \ + xmem_erase(COFFEE_SECTOR_SIZE, COFFEE_START + (sector) * COFFEE_SECTOR_SIZE) + +/* Coffee types. */ +typedef int16_t coffee_page_t; + +#endif /* !COFFEE_ARCH_H */ diff --git a/arch/platform/srf06-cc26xx/common/xmem.c b/arch/platform/srf06-cc26xx/common/xmem.c new file mode 100644 index 000000000..5a79be6c1 --- /dev/null +++ b/arch/platform/srf06-cc26xx/common/xmem.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * Device driver for the MX25R8035F 1Mbyte external memory. + * \author + * Dongda Lee + * + * Data is written bit inverted (~-operator) to flash so that + * unwritten data will read as zeros (UNIX style). + */ + +#include "contiki.h" +#include "ext-flash.h" +#include "dev/xmem.h" +#include "dev/watchdog.h" +#include "cfs-coffee-arch.h" +#include /* For PRINTF() */ + +#define EXT_ERASE_UNIT_SIZE 4096UL + +#define XMEM_BUFF_LENGHT 128 + + +#if 0 +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) do {} while (0) +#endif + + +void +xmem_init(void) +{ + ext_flash_open(); +} + + +int +xmem_pread(void *_p, int size, unsigned long addr) +{ + int rv; + uint8_t x; + int i; + + rv = ext_flash_open(); + + if(!rv) { + PRINTF("Could not open flash to save config\n"); + ext_flash_close(); + return -1; + } + + rv = ext_flash_read(addr, size, _p); + for (i = 0; i < size; i++){ + x = ~*((uint8_t *)_p + i); + *((uint8_t *)_p+i) = x; + } + + ext_flash_close(); + + if(rv) + return size; + + PRINTF("Could not read flash memory!\n"); + return -1; +} + + +int +xmem_pwrite(const void *_buf, int size, unsigned long addr) +{ + int rv; + int i, j; + int remain; + + uint8_t tmp_buf[XMEM_BUFF_LENGHT]; + + rv = ext_flash_open(); + + if(!rv) { + PRINTF("Could not open flash to save config!\n"); + ext_flash_close(); + return -1; + } + + for (remain = size, j = 0; remain > 0; remain -= XMEM_BUFF_LENGHT, j += XMEM_BUFF_LENGHT) { + int to_write = MIN(XMEM_BUFF_LENGHT, remain); + for (i = 0; i < to_write; i++) { + tmp_buf[i] = ~*((uint8_t *)_buf + j + i); + } + rv = ext_flash_write(addr + j, to_write, tmp_buf); + if (!rv) { + PRINTF("Could not write flash memory!\n"); + return size - remain; + } + } + + ext_flash_close(); + + return size; +} + + +int +xmem_erase(long size, unsigned long addr) +{ + int rv; + + rv = ext_flash_open(); + + + if(!rv) { + PRINTF("Could not open flash to save config\n"); + ext_flash_close(); + return -1; + } + + if(size % EXT_ERASE_UNIT_SIZE != 0) { + PRINTF("xmem_erase: bad size\n"); + return -1; + } + + if(addr % EXT_ERASE_UNIT_SIZE != 0) { + PRINTF("xmem_erase: bad offset\n"); + return -1; + } + + rv = ext_flash_erase(addr, size); + + ext_flash_close(); + + watchdog_periodic(); + + if(rv) + return size; + + PRINTF("Could not erase flash memory\n"); + return -1; +} diff --git a/arch/platform/srf06-cc26xx/contiki-conf.h b/arch/platform/srf06-cc26xx/contiki-conf.h index 718efc3f6..d0e10f5db 100644 --- a/arch/platform/srf06-cc26xx/contiki-conf.h +++ b/arch/platform/srf06-cc26xx/contiki-conf.h @@ -38,6 +38,7 @@ #define CONTIKI_CONF_H #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH diff --git a/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad b/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad index 54bd81ced..224f0c2c5 100644 --- a/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad +++ b/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad @@ -2,7 +2,7 @@ CFLAGS += -DBOARD_LAUNCHPAD=1 CONTIKI_TARGET_DIRS += launchpad common -BOARD_SOURCEFILES += board.c launchpad-sensors.c leds-arch.c button-sensor.c +BOARD_SOURCEFILES += board.c launchpad-sensors.c button-sensor.c xmem.c BOARD_SOURCEFILES += ext-flash.c board-spi.c ### Signal that we can be programmed with cc2538-bsl diff --git a/arch/platform/srf06-cc26xx/launchpad/button-sensor.c b/arch/platform/srf06-cc26xx/launchpad/button-sensor.c index eb8bd3033..43d07ad9c 100644 --- a/arch/platform/srf06-cc26xx/launchpad/button-sensor.c +++ b/arch/platform/srf06-cc26xx/launchpad/button-sensor.c @@ -39,7 +39,7 @@ #include "contiki.h" #include "lib/sensors.h" #include "launchpad/button-sensor.h" -#include "gpio-interrupt.h" +#include "gpio-hal.h" #include "sys/timer.h" #include "lpm.h" @@ -70,9 +70,9 @@ struct btn_timer { static struct btn_timer left_timer, right_timer; /*---------------------------------------------------------------------------*/ static void -button_press_handler(uint8_t ioid) +button_press_handler(gpio_hal_pin_mask_t pin_mask) { - if(ioid == BOARD_IOID_KEY_LEFT) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_LEFT)) { if(!timer_expired(&left_timer.debounce)) { return; } @@ -92,7 +92,7 @@ button_press_handler(uint8_t ioid) } } - if(ioid == BOARD_IOID_KEY_RIGHT) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_RIGHT)) { if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { if(!timer_expired(&right_timer.debounce)) { return; @@ -117,6 +117,12 @@ button_press_handler(uint8_t ioid) } } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t press_handler = { + .next = NULL, + .handler = button_press_handler, + .pin_mask = 0, +}; +/*---------------------------------------------------------------------------*/ static void config_buttons(int type, int c, uint32_t key) { @@ -125,7 +131,8 @@ config_buttons(int type, int c, uint32_t key) ti_lib_gpio_clear_event_dio(key); ti_lib_rom_ioc_pin_type_gpio_input(key); ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - gpio_interrupt_register_handler(key, button_press_handler); + press_handler.pin_mask |= gpio_hal_pin_to_mask(key); + gpio_hal_register_handler(&press_handler); break; case SENSORS_ACTIVE: if(c) { diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h b/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h index 1d56d776a..d8a87e53a 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h @@ -55,20 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -79,9 +73,6 @@ */ #define BOARD_IOID_LED_1 IOID_6 #define BOARD_IOID_LED_2 IOID_7 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h b/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h index 9b5019179..c80fb1326 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h @@ -55,20 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -79,9 +73,6 @@ */ #define BOARD_IOID_LED_1 IOID_6 #define BOARD_IOID_LED_2 IOID_7 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h b/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h index 65a5bb766..1ea40957a 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h @@ -55,20 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -79,9 +73,6 @@ */ #define BOARD_IOID_LED_1 IOID_6 #define BOARD_IOID_LED_2 IOID_7 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/launchpad/leds-arch.c b/arch/platform/srf06-cc26xx/launchpad/leds-arch.c index 0d8385ad6..5d70dea40 100644 --- a/arch/platform/srf06-cc26xx/launchpad/leds-arch.c +++ b/arch/platform/srf06-cc26xx/launchpad/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * 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 @@ -28,54 +29,17 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup launchpad-peripherals - * @{ - * - * \file - * Driver for LaunchPad LEDs - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" - +#include "dev/gpio-hal.h" #include "ti-lib.h" -/*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); +#include +/*---------------------------------------------------------------------------*/ +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, +}; +/*---------------------------------------------------------------------------*/ - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } - if((leds & LEDS_YELLOW) == LEDS_YELLOW) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_2); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/platform.c b/arch/platform/srf06-cc26xx/platform.c index 0d24e6f2c..ccb97894f 100644 --- a/arch/platform/srf06-cc26xx/platform.c +++ b/arch/platform/srf06-cc26xx/platform.c @@ -47,15 +47,16 @@ #include "ti-lib.h" #include "contiki.h" #include "contiki-net.h" -#include "leds.h" #include "lpm.h" -#include "gpio-interrupt.h" +#include "dev/leds.h" +#include "dev/gpio-hal.h" #include "dev/oscillators.h" #include "ieee-addr.h" #include "ble-addr.h" #include "vims.h" #include "dev/cc26xx-uart.h" #include "dev/soc-rtc.h" +#include "dev/serial-line.h" #include "rf-core/rf-core.h" #include "sys_ctrl.h" #include "uart.h" @@ -84,7 +85,7 @@ unsigned short node_id = 0; void board_init(void); /*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; @@ -143,7 +144,7 @@ platform_init_stage_one() board_init(); - gpio_interrupt_init(); + gpio_hal_init(); leds_init(); fade(LEDS_RED); @@ -156,6 +157,7 @@ platform_init_stage_one() */ ti_lib_pwr_ctrl_io_freeze_disable(); + ti_lib_rom_int_enable(INT_AON_GPIO_EDGE); ti_lib_int_master_enable(); soc_rtc_init(); @@ -174,6 +176,10 @@ platform_init_stage_two() serial_line_init(); +#if BUILD_WITH_SHELL + cc26xx_uart_set_input(serial_line_input_byte); +#endif + /* Populate linkaddr_node_addr */ #if MAKE_MAC == MAKE_MAC_BLE uint8_t ext_addr[8]; diff --git a/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag b/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag index 68e4b007f..1862f59fa 100644 --- a/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag +++ b/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag @@ -5,6 +5,6 @@ CONTIKI_TARGET_DIRS += sensortag common BOARD_SOURCEFILES += sensortag-sensors.c sensor-common.c BOARD_SOURCEFILES += bmp-280-sensor.c tmp-007-sensor.c opt-3001-sensor.c -BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c button-sensor.c +BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c button-sensor.c xmem.c BOARD_SOURCEFILES += reed-relay.c ext-flash.c buzzer.c BOARD_SOURCEFILES += board.c board-spi.c board-i2c.c diff --git a/arch/platform/srf06-cc26xx/sensortag/button-sensor.c b/arch/platform/srf06-cc26xx/sensortag/button-sensor.c index 7ec0a5a18..f19704f81 100644 --- a/arch/platform/srf06-cc26xx/sensortag/button-sensor.c +++ b/arch/platform/srf06-cc26xx/sensortag/button-sensor.c @@ -39,7 +39,7 @@ #include "contiki.h" #include "lib/sensors.h" #include "sensortag/button-sensor.h" -#include "gpio-interrupt.h" +#include "gpio-hal.h" #include "sys/timer.h" #include "lpm.h" @@ -73,9 +73,9 @@ static struct btn_timer left_timer, right_timer; * \brief Handler for Sensortag-CC26XX button presses */ static void -button_press_handler(uint8_t ioid) +button_press_handler(gpio_hal_pin_mask_t pin_mask) { - if(ioid == BOARD_IOID_KEY_LEFT) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_LEFT)) { if(!timer_expired(&left_timer.debounce)) { return; } @@ -95,7 +95,7 @@ button_press_handler(uint8_t ioid) } } - if(ioid == BOARD_IOID_KEY_RIGHT) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_RIGHT)) { if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { if(!timer_expired(&right_timer.debounce)) { return; @@ -120,6 +120,12 @@ button_press_handler(uint8_t ioid) } } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t press_handler = { + .next = NULL, + .handler = button_press_handler, + .pin_mask = 0, +}; +/*---------------------------------------------------------------------------*/ /** * \brief Configuration function for the button sensor for all buttons. * @@ -135,7 +141,8 @@ config_buttons(int type, int c, uint32_t key) ti_lib_gpio_clear_event_dio(key); ti_lib_rom_ioc_pin_type_gpio_input(key); ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - gpio_interrupt_register_handler(key, button_press_handler); + press_handler.pin_mask |= gpio_hal_pin_to_mask(key); + gpio_hal_register_handler(&press_handler); break; case SENSORS_ACTIVE: if(c) { diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 b/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 index 3cacec197..cdae4c2b1 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 +++ b/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 @@ -1,6 +1,3 @@ -### Add to the source list -BOARD_SOURCEFILES += leds-arch.c - ### Will allow the inclusion of the correct CPU makefile CPU_FAMILY = cc13xx diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h b/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h index dbd64e538..d9269c8ff 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h +++ b/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h @@ -58,20 +58,13 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#define LEDS_RED 1 -#define LEDS_GREEN LEDS_RED -#define LEDS_YELLOW LEDS_RED -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 1 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 1 +#define LEDS_CONF_RED 1 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -81,8 +74,6 @@ * @{ */ #define BOARD_IOID_LED_1 IOID_10 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_ALL BOARD_LED_1 /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c b/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c index f4214628e..21b8cf968 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c +++ b/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * 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 @@ -28,50 +29,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc13xx-peripherals - * @{ - * - * \file - * Driver for the Sensortag-CC1350 LEDs - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" +#include "dev/gpio-hal.h" -#include "ti-lib.h" +#include /*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - ti_lib_gpio_clear_dio(BOARD_IOID_LED_1); - - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 b/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 index 5b7cdadd9..e91cabda4 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 @@ -1,6 +1,3 @@ -### Add to the source list -BOARD_SOURCEFILES += leds-arch.c - ### Will allow the inclusion of the correct CPU makefile CPU_FAMILY = cc26xx diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h b/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h index 977712ef2..2794e633e 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h @@ -58,20 +58,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -82,9 +76,6 @@ */ #define BOARD_IOID_LED_1 IOID_10 #define BOARD_IOID_LED_2 IOID_15 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c b/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c index c36959063..cab4888b7 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * 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 @@ -28,54 +29,16 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc26xx-peripherals - * @{ - * - * \file - * Driver for the Sensortag-CC26XX LEDs - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" +#include "dev/gpio-hal.h" -#include "ti-lib.h" +#include /*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); - - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } - if((leds & LEDS_YELLOW) == LEDS_YELLOW) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_2); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/reed-relay.c b/arch/platform/srf06-cc26xx/sensortag/reed-relay.c index 736b2170a..6cfb186ab 100644 --- a/arch/platform/srf06-cc26xx/sensortag/reed-relay.c +++ b/arch/platform/srf06-cc26xx/sensortag/reed-relay.c @@ -39,9 +39,9 @@ #include "contiki.h" #include "sys/clock.h" #include "sys/timer.h" +#include "dev/gpio-hal.h" #include "lib/sensors.h" #include "sensortag/reed-relay.h" -#include "gpio-interrupt.h" #include "sys/timer.h" #include "ti-lib.h" @@ -60,7 +60,7 @@ static struct timer debouncetimer; * \brief Handler for Sensortag-CC26XX reed interrupts */ static void -reed_interrupt_handler(uint8_t ioid) +reed_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { if(!timer_expired(&debouncetimer)) { return; @@ -76,6 +76,12 @@ value(int type) return (int)ti_lib_gpio_read_dio(BOARD_IOID_REED_RELAY); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t event_handler = { + .next = NULL, + .handler = reed_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(BOARD_IOID_REED_RELAY), +}; +/*---------------------------------------------------------------------------*/ /** * \brief Configuration function for the button sensor for all buttons. * @@ -99,8 +105,7 @@ configure(int type, int value) ti_lib_ioc_port_configure_set(BOARD_IOID_REED_RELAY, IOC_PORT_GPIO, REED_IO_CFG); - gpio_interrupt_register_handler(BOARD_IOID_REED_RELAY, - reed_interrupt_handler); + gpio_hal_register_handler(&event_handler); break; case SENSORS_ACTIVE: if(value) { diff --git a/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 b/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 index 44d115ec8..bcfe21bca 100644 --- a/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 +++ b/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -2,7 +2,7 @@ CFLAGS += -DBOARD_SMARTRF06EB=1 CONTIKI_TARGET_DIRS += srf06 -BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c +BOARD_SOURCEFILES += srf06-sensors.c button-sensor.c board.c BOARD_SOURCEFILES += als-sensor.c ### Signal that we can be programmed with cc2538-bsl diff --git a/arch/platform/srf06-cc26xx/srf06/button-sensor.c b/arch/platform/srf06-cc26xx/srf06/button-sensor.c index 23f668355..1f4a2db3b 100644 --- a/arch/platform/srf06-cc26xx/srf06/button-sensor.c +++ b/arch/platform/srf06-cc26xx/srf06/button-sensor.c @@ -39,7 +39,7 @@ #include "contiki.h" #include "lib/sensors.h" #include "srf06/button-sensor.h" -#include "gpio-interrupt.h" +#include "gpio-hal.h" #include "sys/timer.h" #include "lpm.h" @@ -74,9 +74,9 @@ static struct btn_timer sel_timer, left_timer, right_timer, up_timer, * \brief Handler for SmartRF button presses */ static void -button_press_handler(uint8_t ioid) +button_press_handler(gpio_hal_pin_mask_t pin_mask) { - if(ioid == BOARD_IOID_KEY_SELECT) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_SELECT)) { if(!timer_expired(&sel_timer.debounce)) { return; } @@ -96,7 +96,7 @@ button_press_handler(uint8_t ioid) } } - if(ioid == BOARD_IOID_KEY_LEFT) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_LEFT)) { if(!timer_expired(&left_timer.debounce)) { return; } @@ -116,7 +116,7 @@ button_press_handler(uint8_t ioid) } } - if(ioid == BOARD_IOID_KEY_RIGHT) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_RIGHT)) { if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { if(!timer_expired(&right_timer.debounce)) { return; @@ -140,7 +140,7 @@ button_press_handler(uint8_t ioid) } } - if(ioid == BOARD_IOID_KEY_UP) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_UP)) { if(!timer_expired(&up_timer.debounce)) { return; } @@ -160,7 +160,7 @@ button_press_handler(uint8_t ioid) } } - if(ioid == BOARD_IOID_KEY_DOWN) { + if(pin_mask & gpio_hal_pin_to_mask(BOARD_IOID_KEY_DOWN)) { if(!timer_expired(&down_timer.debounce)) { return; } @@ -181,6 +181,12 @@ button_press_handler(uint8_t ioid) } } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t press_handler = { + .next = NULL, + .handler = button_press_handler, + .pin_mask = 0, +}; +/*---------------------------------------------------------------------------*/ /** * \brief Configuration function for the button sensor for all buttons. * @@ -196,7 +202,8 @@ config_buttons(int type, int c, uint32_t key) ti_lib_gpio_clear_event_dio(key); ti_lib_rom_ioc_pin_type_gpio_input(key); ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - gpio_interrupt_register_handler(key, button_press_handler); + press_handler.pin_mask |= gpio_hal_pin_to_mask(key); + gpio_hal_register_handler(&press_handler); break; case SENSORS_ACTIVE: if(c) { diff --git a/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h b/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h index e210d82d8..bf12b2b09 100644 --- a/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h +++ b/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h @@ -58,20 +58,16 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#define LEDS_RED 1 /**< LED1 (Red) */ -#define LEDS_YELLOW 2 /**< LED2 (Yellow) */ -#define LEDS_GREEN 4 /**< LED3 (Green) */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) */ - -#define LEDS_CONF_ALL 15 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 4 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 +#define LEDS_CONF_GREEN 4 +#define LEDS_CONF_ORANGE 8 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -84,12 +80,6 @@ #define BOARD_IOID_LED_2 IOID_27 #define BOARD_IOID_LED_3 IOID_7 #define BOARD_IOID_LED_4 IOID_6 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_3 (1 << BOARD_IOID_LED_3) -#define BOARD_LED_4 (1 << BOARD_IOID_LED_4) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2 | BOARD_LED_3 | \ - BOARD_LED_4) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h b/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h index 99f97fbf2..44080f474 100644 --- a/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h +++ b/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h @@ -58,20 +58,16 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#define LEDS_RED 1 /**< LED1 (Red) */ -#define LEDS_YELLOW 2 /**< LED2 (Yellow) */ -#define LEDS_GREEN 4 /**< LED3 (Green) */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) */ - -#define LEDS_CONF_ALL 15 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 4 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 +#define LEDS_CONF_GREEN 4 +#define LEDS_CONF_ORANGE 8 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -84,12 +80,6 @@ #define BOARD_IOID_LED_2 IOID_27 #define BOARD_IOID_LED_3 IOID_7 #define BOARD_IOID_LED_4 IOID_6 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_3 (1 << BOARD_IOID_LED_3) -#define BOARD_LED_4 (1 << BOARD_IOID_LED_4) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2 | BOARD_LED_3 | \ - BOARD_LED_4) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/srf06/leds-arch.c b/arch/platform/srf06-cc26xx/srf06/leds-arch.c index 2a1627005..fba996b39 100644 --- a/arch/platform/srf06-cc26xx/srf06/leds-arch.c +++ b/arch/platform/srf06-cc26xx/srf06/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * 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 @@ -28,63 +29,18 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup srf06-common-peripherals - * @{ - * - * \file - * Driver for the SmartRF06EB LEDs when a CC13xx/CC26xx EM is mounted on it - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" -#include "ti-lib.h" -/*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; +#include "dev/gpio-hal.h" - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_3); - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_4); - - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} +#include /*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, + { .pin = BOARD_IOID_LED_3, .negative_logic = false }, + { .pin = BOARD_IOID_LED_4, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - /* Clear everything */ - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } - if((leds & LEDS_YELLOW) == LEDS_YELLOW) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_2); - } - if((leds & LEDS_GREEN) == LEDS_GREEN) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_3); - } - if((leds & LEDS_ORANGE) == LEDS_ORANGE) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_4); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/zoul/Makefile.zoul b/arch/platform/zoul/Makefile.zoul index 9e25275a4..5f6bfba42 100644 --- a/arch/platform/zoul/Makefile.zoul +++ b/arch/platform/zoul/Makefile.zoul @@ -31,7 +31,7 @@ PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET) -include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(BOARD) ### Include -CONTIKI_TARGET_SOURCEFILES += platform.c +CONTIKI_TARGET_SOURCEFILES += platform.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += leds.c cc1200-zoul-arch.c CONTIKI_TARGET_SOURCEFILES += adc-zoul.c button-sensor.c zoul-sensors.c CONTIKI_TARGET_SOURCEFILES += $(BOARD_SOURCEFILES) @@ -44,9 +44,7 @@ CLEAN += *.zoul CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538 include $(CONTIKI_CPU)/Makefile.cc2538 -MODULES += os/net os/net/mac os/net/mac/framer \ - arch/dev/cc1200 \ - os/storage/cfs +MODULES += arch/dev/cc1200 arch/dev/rgb-led os/storage/cfs BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py diff --git a/arch/platform/zoul/contiki-conf.h b/arch/platform/zoul/contiki-conf.h index cfca8f9f1..b1f1664b9 100644 --- a/arch/platform/zoul/contiki-conf.h +++ b/arch/platform/zoul/contiki-conf.h @@ -47,6 +47,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH diff --git a/arch/platform/zoul/dev/ac-dimmer.c b/arch/platform/zoul/dev/ac-dimmer.c index 5c27c2ffc..e5bb9b1f4 100644 --- a/arch/platform/zoul/dev/ac-dimmer.c +++ b/arch/platform/zoul/dev/ac-dimmer.c @@ -40,6 +40,7 @@ #include "contiki.h" #include "ac-dimmer.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "lib/sensors.h" #include "dev/ioc.h" /*---------------------------------------------------------------------------*/ @@ -76,13 +77,17 @@ PROCESS_THREAD(ac_dimmer_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -dimmer_zero_cross_int_handler(uint8_t port, uint8_t pin) +dimmer_zero_cross_int_handler(gpio_hal_pin_mask_t pin_mask) { - if((port == DIMMER_SYNC_PORT) && (pin == DIMMER_SYNC_PIN)) { - process_poll(&ac_dimmer_int_process); - } + process_poll(&ac_dimmer_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t dimmer_handler = { + .next = NULL, + .handler = dimmer_zero_cross_int_handler, + .pin_mask = gpio_hal_pin_to_mask(DIMMER_SYNC_PIN) << (DIMMER_SYNC_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int status(int type) { @@ -128,8 +133,7 @@ configure(int type, int value) GPIO_DETECT_EDGE(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK); GPIO_DETECT_RISING(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK); - gpio_register_callback(dimmer_zero_cross_int_handler, DIMMER_SYNC_PORT, - DIMMER_SYNC_PIN); + gpio_hal_register_handler(&dimmer_handler); /* Spin process until an interrupt is received */ process_start(&ac_dimmer_int_process, NULL); diff --git a/arch/platform/zoul/dev/button-sensor.c b/arch/platform/zoul/dev/button-sensor.c index 80c7b75cb..9b410cdbf 100644 --- a/arch/platform/zoul/dev/button-sensor.c +++ b/arch/platform/zoul/dev/button-sensor.c @@ -43,6 +43,7 @@ #include "dev/nvic.h" #include "dev/ioc.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "dev/button-sensor.h" #include "sys/timer.h" #include "sys/ctimer.h" @@ -94,15 +95,8 @@ value(int type) return 0; } /*---------------------------------------------------------------------------*/ -/** - * \brief Callback registered with the GPIO module. Gets fired with a button - * port/pin generates an interrupt - * \param port The port number that generated the interrupt - * \param pin The pin number that generated the interrupt. This is the pin - * absolute number (i.e. 0, 1, ..., 7), not a mask - */ static void -btn_callback(uint8_t port, uint8_t pin) +button_press_handler(gpio_hal_pin_mask_t pin_mask) { if(!timer_expired(&debouncetimer)) { return; @@ -123,6 +117,12 @@ btn_callback(uint8_t port, uint8_t pin) sensors_changed(&button_sensor); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t press_handler = { + .next = NULL, + .handler = button_press_handler, + .pin_mask = gpio_hal_pin_to_mask(BUTTON_USER_PIN) << (BUTTON_USER_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ /** * \brief Init function for the User button. * \param type SENSORS_ACTIVE: Activate / Deactivate the sensor (value == 1 @@ -152,7 +152,7 @@ config_user(int type, int value) ioc_set_over(BUTTON_USER_PORT, BUTTON_USER_PIN, IOC_OVERRIDE_PUE); - gpio_register_callback(btn_callback, BUTTON_USER_PORT, BUTTON_USER_PIN); + gpio_hal_register_handler(&press_handler); break; case SENSORS_ACTIVE: if(value) { diff --git a/arch/platform/zoul/dev/cc1200-zoul-arch.c b/arch/platform/zoul/dev/cc1200-zoul-arch.c index 92e686a4e..1aff2ef40 100644 --- a/arch/platform/zoul/dev/cc1200-zoul-arch.c +++ b/arch/platform/zoul/dev/cc1200-zoul-arch.c @@ -52,6 +52,7 @@ #include "dev/spi.h" #include "dev/ssi.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include /*---------------------------------------------------------------------------*/ #define CC1200_SPI_CLK_PORT_BASE GPIO_PORT_TO_BASE(SPI0_CLK_PORT) @@ -92,7 +93,7 @@ extern int cc1200_rx_interrupt(void); /*---------------------------------------------------------------------------*/ void -cc1200_int_handler(uint8_t port, uint8_t pin) +cc1200_int_handler(gpio_hal_pin_mask_t pin_mask) { /* To keep the gpio_register_callback happy */ cc1200_rx_interrupt(); @@ -166,6 +167,14 @@ cc1200_arch_spi_rw(uint8_t *inbuf, const uint8_t *write_buf, uint16_t len) return 0; } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t interrupt_handler = { + .next = NULL, + .handler = cc1200_int_handler, + .pin_mask = + (gpio_hal_pin_to_mask(CC1200_GDO0_PIN) << (CC1200_GDO0_PORT << 3)) | + (gpio_hal_pin_to_mask(CC1200_GDO2_PIN) << (CC1200_GDO2_PORT << 3)) +}; +/*---------------------------------------------------------------------------*/ void cc1200_arch_gpio0_setup_irq(int rising) { @@ -184,8 +193,7 @@ cc1200_arch_gpio0_setup_irq(int rising) GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK); ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE); NVIC_EnableIRQ(CC1200_GPIOx_VECTOR); - gpio_register_callback(cc1200_int_handler, CC1200_GDO0_PORT, - CC1200_GDO0_PIN); + gpio_hal_register_handler(&interrupt_handler); } /*---------------------------------------------------------------------------*/ void @@ -206,8 +214,7 @@ cc1200_arch_gpio2_setup_irq(int rising) GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK); ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE); NVIC_EnableIRQ(CC1200_GPIOx_VECTOR); - gpio_register_callback(cc1200_int_handler, CC1200_GDO2_PORT, - CC1200_GDO2_PIN); + gpio_hal_register_handler(&interrupt_handler); } /*---------------------------------------------------------------------------*/ void diff --git a/arch/platform/zoul/dev/grove-gyro.c b/arch/platform/zoul/dev/grove-gyro.c index ce316a207..1ef9d6036 100644 --- a/arch/platform/zoul/dev/grove-gyro.c +++ b/arch/platform/zoul/dev/grove-gyro.c @@ -44,6 +44,7 @@ #include "contiki.h" #include "dev/i2c.h" #include "dev/grove-gyro.h" +#include "dev/gpio-hal.h" #include "lib/sensors.h" #include "dev/watchdog.h" /*---------------------------------------------------------------------------*/ @@ -458,11 +459,17 @@ PROCESS_THREAD(grove_gyro_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -grove_gyro_interrupt_handler(uint8_t port, uint8_t pin) +grove_gyro_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { process_poll(&grove_gyro_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t gyro_handler = { + .next = NULL, + .handler = grove_gyro_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(I2C_INT_PIN) << (I2C_INT_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int value(int type) { @@ -593,8 +600,7 @@ configure(int type, int value) GPIO_DETECT_EDGE(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK); GPIO_DETECT_FALLING(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK); - gpio_register_callback(grove_gyro_interrupt_handler, I2C_INT_PORT, - I2C_INT_PIN); + gpio_hal_register_handler(&gyro_handler); /* Spin process until an interrupt is received */ process_start(&grove_gyro_int_process, NULL); diff --git a/arch/platform/zoul/dev/leds-arch.c b/arch/platform/zoul/dev/leds-arch.c index f09ed645c..eea4187c0 100644 --- a/arch/platform/zoul/dev/leds-arch.c +++ b/arch/platform/zoul/dev/leds-arch.c @@ -1,17 +1,16 @@ /* - * Copyright (c) 2015, Zolertia - http://www.zolertia.com - * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * 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. @@ -29,45 +28,27 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup zoul - * @{ - * - * \defgroup zoul-leds Zoul LED driver - * - * LED driver implementation for the Zoul-based platforms - * @{ - * - * \file - * LED driver implementation for the Zoul-based platforms - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "reg.h" #include "dev/leds.h" -#include "dev/gpio.h" +#include "dev/gpio-hal.h" + +#include /*---------------------------------------------------------------------------*/ -#define LEDS_GPIO_PIN_MASK LEDS_ALL -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - GPIO_SET_OUTPUT(GPIO_D_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return GPIO_READ_PIN(GPIO_D_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - GPIO_WRITE_PIN(GPIO_D_BASE, LEDS_GPIO_PIN_MASK, leds); -} +const leds_t leds_arch_leds[] = { + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), + .negative_logic = false + }, +}; /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ + diff --git a/arch/platform/zoul/dev/motion-sensor.c b/arch/platform/zoul/dev/motion-sensor.c index ce31c3c46..a44462d69 100644 --- a/arch/platform/zoul/dev/motion-sensor.c +++ b/arch/platform/zoul/dev/motion-sensor.c @@ -47,6 +47,7 @@ #include "lib/sensors.h" #include "dev/sys-ctrl.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "dev/ioc.h" /*---------------------------------------------------------------------------*/ #define DEBUG 0 @@ -76,11 +77,17 @@ PROCESS_THREAD(motion_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -motion_interrupt_handler(uint8_t port, uint8_t pin) +motion_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { process_poll(&motion_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t motion_handler = { + .next = NULL, + .handler = motion_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(MOTION_SENSOR_PIN) << (MOTION_SENSOR_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int status(int type) { @@ -113,8 +120,7 @@ configure(int type, int value) GPIO_DETECT_RISING(MOTION_SENSOR_PORT_BASE, MOTION_SENSOR_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(MOTION_SENSOR_PORT_BASE, MOTION_SENSOR_PIN_MASK); ioc_set_over(MOTION_SENSOR_PORT, MOTION_SENSOR_PIN, IOC_OVERRIDE_DIS); - gpio_register_callback(motion_interrupt_handler, MOTION_SENSOR_PORT, - MOTION_SENSOR_PIN); + gpio_hal_register_handler(&motion_handler); process_start(&motion_int_process, NULL); diff --git a/arch/platform/zoul/dev/rtcc.c b/arch/platform/zoul/dev/rtcc.c index b5cb116c3..d03413d5b 100644 --- a/arch/platform/zoul/dev/rtcc.c +++ b/arch/platform/zoul/dev/rtcc.c @@ -735,7 +735,7 @@ rtcc_print(uint8_t value) } /*---------------------------------------------------------------------------*/ static void -rtcc_interrupt_handler(uint8_t port, uint8_t pin) +rtcc_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { process_poll(&rtcc_int_process); } @@ -912,6 +912,12 @@ rtcc_set_calibration(uint8_t mode, int32_t adjust) return AB08_SUCCESS; } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t rtcc_handler = { + .next = NULL, + .handler = rtcc_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(RTC_INT1_PIN) << (RTC_INT1_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ int8_t rtcc_init(void) { @@ -937,7 +943,7 @@ rtcc_init(void) GPIO_DETECT_EDGE(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK); GPIO_DETECT_FALLING(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK); - gpio_register_callback(rtcc_interrupt_handler, RTC_INT1_PORT, RTC_INT1_PIN); + gpio_hal_register_handler(&rtcc_handler); /* Spin process until an interrupt is received */ process_start(&rtcc_int_process, NULL); diff --git a/arch/platform/zoul/dev/tsl256x.c b/arch/platform/zoul/dev/tsl256x.c index 3f6870547..ffcf2e218 100644 --- a/arch/platform/zoul/dev/tsl256x.c +++ b/arch/platform/zoul/dev/tsl256x.c @@ -43,6 +43,7 @@ #include "contiki.h" #include "dev/i2c.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "dev/zoul-sensors.h" #include "lib/sensors.h" #include "tsl256x.h" @@ -255,7 +256,7 @@ PROCESS_THREAD(tsl256x_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -tsl256x_interrupt_handler(uint8_t port, uint8_t pin) +tsl256x_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { /* There's no alert/interruption flag to check, clear the interruption by * writting to the CLEAR bit in the COMMAND register @@ -263,6 +264,12 @@ tsl256x_interrupt_handler(uint8_t port, uint8_t pin) process_poll(&tsl256x_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t tsl256x_handler = { + .next = NULL, + .handler = tsl256x_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(I2C_INT_PIN) << (I2C_INT_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int configure(int type, int value) { @@ -440,7 +447,7 @@ configure(int type, int value) GPIO_DETECT_EDGE(TSL256X_INT_PORT_BASE, TSL256X_INT_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(TSL256X_INT_PORT_BASE, TSL256X_INT_PIN_MASK); GPIO_DETECT_FALLING(TSL256X_INT_PORT_BASE, TSL256X_INT_PIN_MASK); - gpio_register_callback(tsl256x_interrupt_handler, I2C_INT_PORT, I2C_INT_PIN); + gpio_hal_register_handler(&tsl256x_handler); /* Spin process until an interrupt is received */ process_start(&tsl256x_int_process, NULL); diff --git a/arch/platform/zoul/dev/weather-meter.c b/arch/platform/zoul/dev/weather-meter.c index 357c37d4b..cc78f9654 100644 --- a/arch/platform/zoul/dev/weather-meter.c +++ b/arch/platform/zoul/dev/weather-meter.c @@ -51,6 +51,7 @@ #include "lib/sensors.h" #include "dev/sys-ctrl.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "dev/ioc.h" #include "sys/timer.h" #include "sys/ctimer.h" @@ -292,8 +293,22 @@ PROCESS_THREAD(weather_meter_int_process, ev, data) PROCESS_END(); } /*---------------------------------------------------------------------------*/ +static void weather_meter_interrupt_handler(gpio_hal_pin_mask_t pin_mask); +/*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t rain_handler = { + .next = NULL, + .handler = weather_meter_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(RAIN_GAUGE_SENSOR_PIN) << (RAIN_GAUGE_SENSOR_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t anemometer_handler = { + .next = NULL, + .handler = weather_meter_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(ANEMOMETER_SENSOR_PIN) << (ANEMOMETER_SENSOR_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static void -weather_meter_interrupt_handler(uint8_t port, uint8_t pin) +weather_meter_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { uint32_t aux; @@ -308,10 +323,10 @@ weather_meter_interrupt_handler(uint8_t port, uint8_t pin) * value */ - if((port == ANEMOMETER_SENSOR_PORT) && (pin == ANEMOMETER_SENSOR_PIN)) { + if(pin_mask == rain_handler.pin_mask) { weather_sensors.anemometer.ticks++; process_post(&weather_meter_int_process, anemometer_int_event, NULL); - } else if((port == RAIN_GAUGE_SENSOR_PORT) && (pin == RAIN_GAUGE_SENSOR_PIN)) { + } else if(pin_mask == anemometer_handler.pin_mask) { weather_sensors.rain_gauge.ticks++; aux = weather_sensors.rain_gauge.ticks * WEATHER_METER_AUX_RAIN_MM; aux /= 1000; @@ -427,8 +442,7 @@ configure(int type, int value) GPIO_TRIGGER_SINGLE_EDGE(ANEMOMETER_SENSOR_PORT_BASE, ANEMOMETER_SENSOR_PIN_MASK); ioc_set_over(ANEMOMETER_SENSOR_PORT, ANEMOMETER_SENSOR_PIN, IOC_OVERRIDE_DIS); - gpio_register_callback(weather_meter_interrupt_handler, ANEMOMETER_SENSOR_PORT, - ANEMOMETER_SENSOR_PIN); + gpio_hal_register_handler(&anemometer_handler); /* Configure rain gauge interruption */ GPIO_SOFTWARE_CONTROL(RAIN_GAUGE_SENSOR_PORT_BASE, RAIN_GAUGE_SENSOR_PIN_MASK); @@ -437,8 +451,7 @@ configure(int type, int value) GPIO_TRIGGER_SINGLE_EDGE(RAIN_GAUGE_SENSOR_PORT_BASE, RAIN_GAUGE_SENSOR_PIN_MASK); ioc_set_over(RAIN_GAUGE_SENSOR_PORT, RAIN_GAUGE_SENSOR_PIN, IOC_OVERRIDE_DIS); - gpio_register_callback(weather_meter_interrupt_handler, RAIN_GAUGE_SENSOR_PORT, - RAIN_GAUGE_SENSOR_PIN); + gpio_hal_register_handler(&rain_handler); process_start(&weather_meter_int_process, NULL); diff --git a/arch/platform/zoul/firefly-reva/Makefile.firefly-reva b/arch/platform/zoul/firefly-reva/Makefile.firefly-reva index 50cb71997..afecf9fa5 100644 --- a/arch/platform/zoul/firefly-reva/Makefile.firefly-reva +++ b/arch/platform/zoul/firefly-reva/Makefile.firefly-reva @@ -1,2 +1,2 @@ MOTELIST_ZOLERTIA = firefly -BOARD_SOURCEFILES += board.c leds-arch.c +BOARD_SOURCEFILES += board.c diff --git a/arch/platform/zoul/firefly-reva/board.h b/arch/platform/zoul/firefly-reva/board.h index bea1fc746..784f9e902 100644 --- a/arch/platform/zoul/firefly-reva/board.h +++ b/arch/platform/zoul/firefly-reva/board.h @@ -98,20 +98,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/firefly/Makefile.firefly b/arch/platform/zoul/firefly/Makefile.firefly index 50cb71997..afecf9fa5 100644 --- a/arch/platform/zoul/firefly/Makefile.firefly +++ b/arch/platform/zoul/firefly/Makefile.firefly @@ -1,2 +1,2 @@ MOTELIST_ZOLERTIA = firefly -BOARD_SOURCEFILES += board.c leds-arch.c +BOARD_SOURCEFILES += board.c diff --git a/arch/platform/zoul/firefly/board.h b/arch/platform/zoul/firefly/board.h index 4a58fc0cc..0367ea8df 100644 --- a/arch/platform/zoul/firefly/board.h +++ b/arch/platform/zoul/firefly/board.h @@ -98,20 +98,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/orion/Makefile.orion b/arch/platform/zoul/orion/Makefile.orion index 7c5804d39..e3ecb601b 100644 --- a/arch/platform/zoul/orion/Makefile.orion +++ b/arch/platform/zoul/orion/Makefile.orion @@ -3,4 +3,4 @@ MODULES += arch/dev/enc28j60 CC2538_ENC28J60_ARCH ?= gpio WITH_IP64 ?= 1 CFLAGS += -DUIP_FALLBACK_INTERFACE=ip64_uip_fallback_interface -BOARD_SOURCEFILES += board.c enc28j60-arch-$(CC2538_ENC28J60_ARCH).c leds-arch.c +BOARD_SOURCEFILES += board.c enc28j60-arch-$(CC2538_ENC28J60_ARCH).c diff --git a/arch/platform/zoul/orion/board.h b/arch/platform/zoul/orion/board.h index 494d79372..ee80cc709 100644 --- a/arch/platform/zoul/orion/board.h +++ b/arch/platform/zoul/orion/board.h @@ -67,20 +67,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/platform.c b/arch/platform/zoul/platform.c index f71c9e46a..2b0a394b1 100644 --- a/arch/platform/zoul/platform.c +++ b/arch/platform/zoul/platform.c @@ -69,6 +69,7 @@ #include #include #include +#include /*---------------------------------------------------------------------------*/ /* Log configuration */ #include "sys/log.h" @@ -81,7 +82,7 @@ void board_init(void); /*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; @@ -124,7 +125,7 @@ rtc_init(void) */ /* Get the system date in the following format: wd dd mm yy hh mm ss */ - PRINTF("Setting RTC from system date: %s\n", DATE); + LOG_INFO("Setting RTC from system date: %s\n", DATE); /* Configure the RTC with the current values */ td.weekdays = (uint8_t)strtol(DATE, &next, 10); @@ -149,7 +150,7 @@ rtc_init(void) /* Set the time and date */ if(rtcc_set_time_date(&td) == AB08_ERROR) { - PRINTF("Failed to set time and date\n"); + LOG_ERR("Failed to set time and date\n"); } #endif #endif diff --git a/arch/platform/zoul/remote-reva/Makefile.remote-reva b/arch/platform/zoul/remote-reva/Makefile.remote-reva index 6b4a80e75..fcccdf0f4 100644 --- a/arch/platform/zoul/remote-reva/Makefile.remote-reva +++ b/arch/platform/zoul/remote-reva/Makefile.remote-reva @@ -1,4 +1,4 @@ MOTELIST_ZOLERTIA = remote -BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c power-mgmt.c leds-arch.c +BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c power-mgmt.c MODULES += os/lib/fs/fat os/lib/fs/fat/option arch/platform/zoul/fs/fat arch/dev/disk/mmc diff --git a/arch/platform/zoul/remote-reva/board.h b/arch/platform/zoul/remote-reva/board.h index 70a8ffdab..23722badd 100644 --- a/arch/platform/zoul/remote-reva/board.h +++ b/arch/platform/zoul/remote-reva/board.h @@ -102,20 +102,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/remote-revb/Makefile.remote-revb b/arch/platform/zoul/remote-revb/Makefile.remote-revb index d23362c32..fcccdf0f4 100644 --- a/arch/platform/zoul/remote-revb/Makefile.remote-revb +++ b/arch/platform/zoul/remote-revb/Makefile.remote-revb @@ -1,4 +1,4 @@ MOTELIST_ZOLERTIA = remote -BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c leds-res-arch.c power-mgmt.c +BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c power-mgmt.c MODULES += os/lib/fs/fat os/lib/fs/fat/option arch/platform/zoul/fs/fat arch/dev/disk/mmc diff --git a/arch/platform/zoul/remote-revb/board.h b/arch/platform/zoul/remote-revb/board.h index 432b4b062..244489562 100644 --- a/arch/platform/zoul/remote-revb/board.h +++ b/arch/platform/zoul/remote-revb/board.h @@ -105,26 +105,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -#define LEDS_RED 1 /**< LED1 (Red) -> PD4 */ -#define LEDS_RED_PIN_MASK (1 << 4) -#define LEDS_RED_PORT_BASE GPIO_D_BASE +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 4 +#define LEDS_ARCH_L2_PORT GPIO_B_NUM +#define LEDS_ARCH_L2_PIN 7 +#define LEDS_ARCH_L3_PORT GPIO_B_NUM +#define LEDS_ARCH_L3_PIN 6 -#define LEDS_GREEN 2 /**< LED2 (Green) -> PB7 */ -#define LEDS_GREEN_PIN_MASK (1 << 7) -#define LEDS_GREEN_PORT_BASE GPIO_B_BASE +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_BLUE 4 /**< LED3 (Blue) -> PB6 */ -#define LEDS_BLUE_PIN_MASK (1 << 6) -#define LEDS_BLUE_PORT_BASE GPIO_B_BASE - -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) /* 7 */ -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /* 6 */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /* 3 */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /* 5 */ -#define LEDS_WHITE LEDS_ALL /* 7 */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/examples/6tisch/6p-packet/6p-packet.csc b/examples/6tisch/6p-packet/6p-packet.csc index 9f1bfe534..e25b08ef8 100644 --- a/examples/6tisch/6p-packet/6p-packet.csc +++ b/examples/6tisch/6p-packet/6p-packet.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/examples/6tisch/6p-packet/Makefile b/examples/6tisch/6p-packet/Makefile index 1ae6e34b5..7e154f9d3 100644 --- a/examples/6tisch/6p-packet/Makefile +++ b/examples/6tisch/6p-packet/Makefile @@ -4,7 +4,7 @@ PROJECT_SOURCEFILES += test-sf.c CONTIKI = ../../../ MAKE_MAC = MAKE_MAC_TSCH -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MODULES += os/net/mac/tsch/sixtop include $(CONTIKI)/Makefile.include diff --git a/examples/6tisch/6p-packet/sixp-node.c b/examples/6tisch/6p-packet/sixp-node.c index d911701bc..43cabbe29 100644 --- a/examples/6tisch/6p-packet/sixp-node.c +++ b/examples/6tisch/6p-packet/sixp-node.c @@ -30,11 +30,13 @@ #include #include -#include #include #include #include +/* Hard-coded MAC address of the TSCH coordinator */ +static linkaddr_t coordinator_addr = {{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}; + extern const sixtop_sf_t test_sf; extern int test_sf_start(const linkaddr_t *addr); @@ -49,7 +51,7 @@ PROCESS_THREAD(sixp_node_process, ev, data) sixtop_add_sf(&test_sf); - if(node_id == COORDINATOR_NODE_ID) { + if(linkaddr_cmp(&coordinator_addr, &linkaddr_node_addr)) { tsch_set_coordinator(1); assert(test_sf_start(NULL) == 0); } else { diff --git a/examples/6tisch/etsi-plugtest-2017/node.c b/examples/6tisch/etsi-plugtest-2017/node.c index 578727d1f..3e16666dd 100644 --- a/examples/6tisch/etsi-plugtest-2017/node.c +++ b/examples/6tisch/etsi-plugtest-2017/node.c @@ -38,15 +38,11 @@ #include "contiki.h" #include "node-id.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" #include "net/mac/tsch/tsch-log.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "serial-shell.h" #include "sf-plugtest.h" #if CONTIKI_TARGET_SRF06_CC26XX @@ -81,7 +77,7 @@ PROCESS_THREAD(node_process, ev, data) #endif if(is_coordinator) { - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); } NETSTACK_MAC.on(); diff --git a/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c b/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c index 8c6628f3f..f4f54e6ac 100644 --- a/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c +++ b/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c @@ -314,7 +314,7 @@ add_req_handler(const linkaddr_t *peer_addr, sizeof(sixp_pkt_cell_options_t) + sizeof(sixp_pkt_num_cells_t) + sizeof(sf_plugtest_cell_t))) { - LOG_ERR("invalid Add Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Add Request length: %lu\n", (unsigned long)body_len); } assert( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_REQUEST, @@ -359,7 +359,7 @@ add_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, struct tsch_slotframe *slotframe; if(body_len != 4) { - LOG_ERR("invalid Add Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Add Response length: %lu\n", (unsigned long)body_len); return; } @@ -399,7 +399,7 @@ delete_req_handler(const linkaddr_t *peer_addr, sizeof(sixp_pkt_cell_options_t) + sizeof(sixp_pkt_num_cells_t) + sizeof(sf_plugtest_cell_t))) { - LOG_ERR("invalid Delete Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Delete Request length: %lu\n", (unsigned long)body_len); } assert( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_REQUEST, @@ -446,7 +446,7 @@ delete_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, uint16_t timeslot; if(body_len != 4) { - LOG_ERR("invalid Delete Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Delete Response length: %lu\n", (unsigned long)body_len); return; } @@ -489,7 +489,7 @@ count_req_handler(const linkaddr_t *peer_addr, assert(peer_addr != NULL && body != NULL); if(body_len != (sizeof(sixp_pkt_metadata_t) + sizeof(sixp_pkt_cell_options_t))) { - LOG_ERR("invalid Count Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Count Request length: %lu\n", (unsigned long)body_len); } assert( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_REQUEST, @@ -534,7 +534,7 @@ count_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, sixp_pkt_total_num_cells_t total_num_cells; if(body_len != 2) { - LOG_ERR("invalid Count Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Count Response length: %lu\n", (unsigned long)body_len); return; } @@ -570,7 +570,7 @@ list_req_handler(const linkaddr_t *peer_addr, sizeof(sixp_pkt_reserved_t) + sizeof(sixp_pkt_offset_t) + sizeof(sixp_pkt_max_num_cells_t))) { - LOG_ERR("invalid List Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid List Request length: %lu\n", (unsigned long)body_len); } assert( @@ -679,7 +679,7 @@ clear_req_handler(const linkaddr_t *peer_addr, assert(peer_addr != NULL && body != NULL); if(body_len != sizeof(sixp_pkt_metadata_t)) { - LOG_ERR("invalid Clear Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Clear Request length: %lu\n", (unsigned long)body_len); } if((slotframe = tsch_schedule_get_slotframe_by_handle(0)) == NULL) { @@ -717,7 +717,7 @@ clear_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, } if(body_len != 0) { - LOG_ERR("invalid Clear Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Clear Response length: %lu\n", (unsigned long)body_len); return; } diff --git a/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc b/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc index fda05987f..e1102b2fa 100644 --- a/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc +++ b/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/examples/6tisch/simple-node/Makefile b/examples/6tisch/simple-node/Makefile index e6cb76944..fbdeb804a 100644 --- a/examples/6tisch/simple-node/Makefile +++ b/examples/6tisch/simple-node/Makefile @@ -3,9 +3,12 @@ all: $(CONTIKI_PROJECT) CONTIKI=../../.. -MAKE_WITH_ORCHESTRA ?= 0 # force Orchestra from command line -MAKE_WITH_SECURITY ?= 0 # force Security from command line -MAKE_WITH_PERIODIC_ROUTES_PRINT ?= 0 # print #routes periodically, used for regression tests + # force Orchestra from command line +MAKE_WITH_ORCHESTRA ?= 0 +# force Security from command line +MAKE_WITH_SECURITY ?= 0 + # print #routes periodically, used for regression tests +MAKE_WITH_PERIODIC_ROUTES_PRINT ?= 0 MAKE_MAC = MAKE_MAC_TSCH MODULES += os/services/shell diff --git a/examples/6tisch/simple-node/node.c b/examples/6tisch/simple-node/node.c index 9884b4e0e..4fa416290 100644 --- a/examples/6tisch/simple-node/node.c +++ b/examples/6tisch/simple-node/node.c @@ -38,15 +38,12 @@ #include "contiki.h" #include "node-id.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" +#include "net/ipv6/uip-sr.h" #include "net/mac/tsch/tsch.h" #include "net/mac/tsch/tsch-log.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" @@ -69,7 +66,7 @@ PROCESS_THREAD(node_process, ev, data) #endif if(is_coordinator) { - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); } NETSTACK_MAC.on(); @@ -80,11 +77,11 @@ PROCESS_THREAD(node_process, ev, data) etimer_set(&et, CLOCK_SECOND * 60); while(1) { /* Used for non-regression testing */ - #if RPL_WITH_STORING + #if (UIP_MAX_ROUTES != 0) PRINTF("Routing entries: %u\n", uip_ds6_route_num_routes()); #endif - #if RPL_WITH_NON_STORING - PRINTF("Routing links: %u\n", rpl_ns_num_nodes()); + #if (UIP_SR_LINK_NUM != 0) + PRINTF("Routing links: %u\n", uip_sr_num_nodes()); #endif PROCESS_YIELD_UNTIL(etimer_expired(&et)); etimer_reset(&et); diff --git a/examples/6tisch/simple-node/rpl-tsch-cooja.csc b/examples/6tisch/simple-node/rpl-tsch-cooja.csc index 276192cdd..bd5557214 100644 --- a/examples/6tisch/simple-node/rpl-tsch-cooja.csc +++ b/examples/6tisch/simple-node/rpl-tsch-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/examples/6tisch/sixtop/node-sixtop.c b/examples/6tisch/sixtop/node-sixtop.c index 4c60db3a7..73e9fab2e 100755 --- a/examples/6tisch/sixtop/node-sixtop.c +++ b/examples/6tisch/sixtop/node-sixtop.c @@ -39,17 +39,13 @@ #include "contiki.h" #include "node-id.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" #include "net/mac/tsch/tsch-log.h" #include "net/mac/tsch/tsch-schedule.h" #include "net/mac/tsch/sixtop/sixtop.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "sf-simple.h" @@ -77,7 +73,7 @@ PROCESS_THREAD(node_process, ev, data) #endif if(is_coordinator) { - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); } NETSTACK_MAC.on(); diff --git a/examples/6tisch/sixtop/project-conf.h b/examples/6tisch/sixtop/project-conf.h index 45e0a2fd1..7f416342e 100755 --- a/examples/6tisch/sixtop/project-conf.h +++ b/examples/6tisch/sixtop/project-conf.h @@ -82,7 +82,7 @@ /* Save some space to fit the limited RAM of the z1 */ #define UIP_CONF_TCP 0 #define QUEUEBUF_CONF_NUM 2 -#define RPL_NS_CONF_LINK_NUM 2 +#define NETSTACK_MAX_ROUTE_ENTRIES 2 #define NBR_TABLE_CONF_MAX_NEIGHBORS 2 #define UIP_CONF_ND6_SEND_NA 0 #define SICSLOWPAN_CONF_FRAG 0 diff --git a/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc b/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc index c0646919d..4ef875924 100644 --- a/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc +++ b/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker sixtop example diff --git a/examples/coap/Makefile b/examples/coap/Makefile index 379ffb104..e2c6e4a5d 100644 --- a/examples/coap/Makefile +++ b/examples/coap/Makefile @@ -9,24 +9,13 @@ ifeq ($(TARGET),native) MODULES_REL += ./resources-plugtest endif MODULES_REL += ./resources +MODULES_REL += $(TARGET) # Include the CoAP implementation MODULES += os/net/app-layer/coap -# optional rules to get assembly -#CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 -#CUSTOM_RULE_S_TO_OBJECTDIR_O = 1 - include $(CONTIKI)/Makefile.include -# optional rules to get assembly -#$(OBJECTDIR)/%.o: asmdir/%.S -# $(CC) $(CFLAGS) -MMD -c $< -o $@ -# @$(FINALIZE_DEPENDENCY) -# -#asmdir/%.S: %.c -# $(CC) $(CFLAGS) -MMD -S $< -o $@ - # border router rules $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -37,8 +26,8 @@ connect-router: $(CONTIKI)/tools/tunslip6 connect-router-cooja: $(CONTIKI)/tools/tunslip6 sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 fd00::1/64 -connect-router-native: $(CONTIKI)/examples/native-border-router/border-router.native - sudo $(CONTIKI)/examples/native-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64 +connect-router-native: $(CONTIKI)/examples/rpl-border-router/border-router.native + sudo $(CONTIKI)/examples/rpl-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64 -connect-minimal: - sudo ip address add fdfd::1/64 dev tap0 +connect-native: + sudo ip address add fdfd::1/64 dev tun0 diff --git a/examples/coap/README.md b/examples/coap/README.md index f74ddfb9e..67ba38f26 100644 --- a/examples/coap/README.md +++ b/examples/coap/README.md @@ -1,109 +1,44 @@ -A Quick Introduction to the Erbium (Er) REST Engine +A Quick Introduction to the Erbium (Er) CoAP Engine =================================================== EXAMPLE FILES ------------- -- coap-example-server.c: A RESTful server example showing how to use the REST - layer to develop server-side applications (at the moment only CoAP is - implemented for the REST Engine). +- coap-example-server.c: A CoAP server example showing how to use the CoAP + layer to develop server-side applications. - coap-example-client.c: A CoAP client that polls the /actuators/toggle resource every 10 seconds and cycles through 4 resources on button press (target address is hard-coded). - plugtest-server.c: The server used for draft compliance testing at ETSI IoT CoAP Plugtests. Erbium (Er) participated in Paris, France, March 2012 and - Sophia-Antipolis, France, November 2012 (configured for minimal-net). + Sophia-Antipolis, France, November 2012 (configured for native). PRELIMINARIES ------------- -- Make sure rpl-border-router has the same stack and fits into mote memory: - You can disable RDC in border-router project-conf.h (not really required as BR keeps radio turned on). - #define NETSTACK_CONF_RDC nullrdc_driver -- Alternatively, you can use the native-border-router together with the slip-radio. -- For convenience, define the Cooja addresses in /etc/hosts - fd00::0212:7401:0001:0101 cooja1 - fd00::0212:7402:0002:0202 cooja2 - ... - Get the Copper (Cu) CoAP user-agent from [https://addons.mozilla.org/en-US/firefox/addon/copper-270430](https://addons.mozilla.org/en-US/firefox/addon/copper-270430) -- Optional: Save your target as default target - make TARGET=sky savetarget -COOJA HOWTO ------------ +TMOTE SKY HOWTO +--------------- -###Server only: +The CoAP example no longer fits in the limited ROM of the Tmote Sky. +Please use a platform with larger ROM instead. - make TARGET=cooja server-only.csc - -Open new terminal - - make connect-router-cooja - -- Start Copper and discover resources at coap://cooja2:5683/ -- Choose "Click button on Sky 2" from the context menu of mote 2 (server) after - requesting /test/separate -- Do the same when observing /test/event - -###With client: - - make TARGET=cooja server-client.csc - -Open new terminal - - make connect-router-cooja - -- Wait until red LED toggles on mote 2 (server) -- Choose "Click button on Sky 3" from the context menu of mote 3 (client) and - watch serial output - -TMOTES HOWTO +NATIVE HOWTO ------------ -###Server: - -1. Connect two Tmote Skys (check with $ make TARGET=sky sky-motelist) - - make TARGET=sky coap-example-server.upload MOTE=2 - make TARGET=sky login MOTE=2 - -2. Press reset button, get address, abort with Ctrl+C: - Line: "Tentative link-local IPv6 address fe80:0000:0000:0000:____:____:____:____" - - cd ../rpl-border-router/ - make TARGET=sky border-router.upload MOTE=1 - make connect-router - - For a BR tty other than USB0: - - make connect-router-port PORT=X - -3. Start Copper and discover resources at: - - coap://[fd00::____:____:____:____]:5683/ - -### Add a client: - -1. Change the hard-coded server address in coap-example-client.c to fd00::____:____:____:____ -2. Connect a third Tmote Sky - - make TARGET=sky coap-example-client.upload MOTE=3 - -MINIMAL-NET HOWTO ------------------ - -With the target minimal-net you can test your CoAP applications without +With the target native you can test your CoAP applications without constraints, i.e., with large buffers, debug output, memory protection, etc. -The plugtest-server is thought for the minimal-net platform, as it requires +The plugtest-server is thought for the native platform, as it requires an 1280-byte IP buffer and 1024-byte blocks. - make TARGET=minimal-net plugtest-server - sudo ./plugtest-server.minimal-net + make TARGET=native plugtest-server + sudo ./plugtest-server.native Open new terminal - make connect-minimal + make connect-native - Start Copper and discover resources at coap://[fdfd::ff:fe00:10]:5683/ - You can enable the ETSI Plugtest menu in Copper's preferences @@ -130,12 +65,12 @@ in coap-example-server.c. In general, coap supports: - All draft-18 header options - CON Retransmissions (note COAP_MAX_OPEN_TRANSACTIONS) -- Blockwise Transfers (note REST_MAX_CHUNK_SIZE, see plugtest-server.c for +- Blockwise Transfers (note COAP_MAX_CHUNK_SIZE, see plugtest-server.c for Block1 uploads) - Separate Responses (no rest_set_pre_handler() required anymore, note coap_separate_accept(), _reject(), and _resume()) - Resource Discovery -- Observing Resources (see EVENT_ and PRERIODIC_RESOURCE, note +- Observing Resources (see EVENT_ and PERIODIC_RESOURCE, note COAP_MAX_OBSERVERS) TODOs diff --git a/examples/coap/coap-example-client.c b/examples/coap/coap-example-client.c index 5ef8f4fce..e17a0ffde 100644 --- a/examples/coap/coap-example-client.c +++ b/examples/coap/coap-example-client.c @@ -42,33 +42,22 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" +#include "coap-blocking-api.h" #include "dev/button-sensor.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "client" +#define LOG_LEVEL LOG_LEVEL_COAP /* FIXME: This server address is hard-coded for Cooja and link-local for unconnected border router. */ -#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */ -/* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1) */ - -#define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT + 1) -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define SERVER_EP "coap://[fe80::212:7402:0002:0202]" #define TOGGLE_INTERVAL 10 PROCESS(er_example_client, "Erbium Example Client"); AUTOSTART_PROCESSES(&er_example_client); -uip_ipaddr_t server_ipaddr; static struct etimer et; /* Example URIs that can be queried. */ @@ -82,7 +71,7 @@ static int uri_switch = 0; /* This function is will be passed to COAP_BLOCKING_REQUEST() to handle responses. */ void -client_chunk_handler(void *response) +client_chunk_handler(coap_message_t *response) { const uint8_t *chunk; @@ -92,14 +81,15 @@ client_chunk_handler(void *response) } PROCESS_THREAD(er_example_client, ev, data) { + static coap_endpoint_t server_ep; PROCESS_BEGIN(); - static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ + static coap_message_t request[1]; /* This way the packet can be treated as pointer as usual. */ - SERVER_NODE(&server_ipaddr); + coap_endpoint_parse(SERVER_EP, strlen(SERVER_EP), &server_ep); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND); @@ -122,11 +112,10 @@ PROCESS_THREAD(er_example_client, ev, data) coap_set_payload(request, (uint8_t *)msg, sizeof(msg) - 1); - PRINT6ADDR(&server_ipaddr); - PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); + LOG_INFO_COAP_EP(&server_ep); + LOG_INFO_("\n"); - COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, - client_chunk_handler); + COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); printf("\n--Done--\n"); @@ -142,10 +131,10 @@ PROCESS_THREAD(er_example_client, ev, data) printf("--Requesting %s--\n", service_urls[uri_switch]); - PRINT6ADDR(&server_ipaddr); - PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); + LOG_INFO_COAP_EP(&server_ep); + LOG_INFO_("\n"); - COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); printf("\n--Done--\n"); diff --git a/examples/coap/coap-example-observe-client.c b/examples/coap/coap-example-observe-client.c index 6d6b0c5cb..611658e69 100644 --- a/examples/coap/coap-example-observe-client.c +++ b/examples/coap/coap-example-observe-client.c @@ -49,19 +49,8 @@ #if DEBUG #define PRINTF(...) printf(__VA_ARGS__) #define PRINTFLN(format, ...) printf(format "\n", ##__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \ - "%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \ - ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \ - ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \ - ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \ - ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \ - ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \ - ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \ - ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \ - ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) #else #define PRINTF(...) -#define PRINT6ADDR(addr) #define PRINTFLN(...) #endif diff --git a/examples/coap/coap-example-server.c b/examples/coap/coap-example-server.c index 79c25d501..3cbcbc746 100644 --- a/examples/coap/coap-example-server.c +++ b/examples/coap/coap-example-server.c @@ -31,7 +31,7 @@ /** * \file - * Erbium (Er) REST Engine example. + * Erbium (Er) CoAP Engine example. * \author * Matthias Kovatsch */ @@ -40,8 +40,7 @@ #include #include #include "contiki.h" -#include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #if PLATFORM_HAS_BUTTON #include "dev/button-sensor.h" @@ -51,19 +50,15 @@ #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) #else #define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) #endif /* * Resources to be activated need to be imported through the extern keyword. * The build system automatically compiles the resources in the corresponding sub-directory. */ -extern resource_t +extern coap_resource_t res_hello, res_mirror, res_chunks, @@ -73,29 +68,29 @@ extern resource_t res_sub, res_b1_sep_b2; #if PLATFORM_HAS_LEDS -extern resource_t res_leds, res_toggle; +extern coap_resource_t res_leds, res_toggle; #endif #if PLATFORM_HAS_LIGHT #include "dev/light-sensor.h" -extern resource_t res_light; +extern coap_resource_t res_light; #endif #if PLATFORM_HAS_BATTERY #include "dev/battery-sensor.h" -extern resource_t res_battery; +extern coap_resource_t res_battery; #endif #if PLATFORM_HAS_TEMPERATURE #include "dev/temperature-sensor.h" -extern resource_t res_temperature; +extern coap_resource_t res_temperature; #endif /* -extern resource_t res_battery; +extern coap_resource_t res_battery; #endif #if PLATFORM_HAS_RADIO -extern resource_t res_radio; +extern coap_resource_t res_radio; #endif #if PLATFORM_HAS_SHT11 #include "dev/sht11/sht11-sensor.h" -extern resource_t res_sht11; +extern coap_resource_t res_sht11; #endif */ @@ -120,47 +115,49 @@ PROCESS_THREAD(er_example_server, ev, data) PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); PRINTF("LL header: %u\n", UIP_LLH_LEN); PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); - PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + PRINTF("CoAP max chunk: %u\n", COAP_MAX_CHUNK_SIZE); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); /* * Bind the resources to their Uri-Path. * WARNING: Activating twice only means alternate path, not two instances! * All static variables are the same for each URI path. */ - rest_activate_resource(&res_hello, "test/hello"); -/* rest_activate_resource(&res_mirror, "debug/mirror"); */ -/* rest_activate_resource(&res_chunks, "test/chunks"); */ -/* rest_activate_resource(&res_separate, "test/separate"); */ - rest_activate_resource(&res_push, "test/push"); -/* rest_activate_resource(&res_event, "sensors/button"); */ -/* rest_activate_resource(&res_sub, "test/sub"); */ -/* rest_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */ + coap_activate_resource(&res_hello, "test/hello"); + coap_activate_resource(&res_mirror, "debug/mirror"); + coap_activate_resource(&res_chunks, "test/chunks"); + coap_activate_resource(&res_separate, "test/separate"); + coap_activate_resource(&res_push, "test/push"); +#if PLATFORM_HAS_BUTTON + coap_activate_resource(&res_event, "sensors/button"); +#endif /* PLATFORM_HAS_BUTTON */ + coap_activate_resource(&res_sub, "test/sub"); + coap_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); #if PLATFORM_HAS_LEDS -/* rest_activate_resource(&res_leds, "actuators/leds"); */ - rest_activate_resource(&res_toggle, "actuators/toggle"); +/* coap_activate_resource(&res_leds, "actuators/leds"); */ + coap_activate_resource(&res_toggle, "actuators/toggle"); #endif #if PLATFORM_HAS_LIGHT - rest_activate_resource(&res_light, "sensors/light"); - SENSORS_ACTIVATE(light_sensor); + coap_activate_resource(&res_light, "sensors/light"); + SENSORS_ACTIVATE(light_sensor); #endif #if PLATFORM_HAS_BATTERY - rest_activate_resource(&res_battery, "sensors/battery"); - SENSORS_ACTIVATE(battery_sensor); + coap_activate_resource(&res_battery, "sensors/battery"); + SENSORS_ACTIVATE(battery_sensor); #endif #if PLATFORM_HAS_TEMPERATURE - rest_activate_resource(&res_temperature, "sensors/temperature"); - SENSORS_ACTIVATE(temperature_sensor); + coap_activate_resource(&res_temperature, "sensors/temperature"); + SENSORS_ACTIVATE(temperature_sensor); #endif /* #if PLATFORM_HAS_RADIO - rest_activate_resource(&res_radio, "sensors/radio"); + coap_activate_resource(&res_radio, "sensors/radio"); #endif #if PLATFORM_HAS_SHT11 - rest_activate_resource(&res_sht11, "sensors/sht11"); - SENSORS_ACTIVATE(sht11_sensor); + coap_activate_resource(&res_sht11, "sensors/sht11"); + SENSORS_ACTIVATE(sht11_sensor); #endif */ diff --git a/examples/coap/in6addr.patch b/examples/coap/in6addr.patch deleted file mode 100644 index 92ca106cf..000000000 --- a/examples/coap/in6addr.patch +++ /dev/null @@ -1,10 +0,0 @@ -21,23c21 -< #ifdef __INSIDE_CYGWIN__ -< uint32_t __s6_addr32[4]; -< #endif ---- -> u_int __s6_addr32[4]; -36d33 -< #ifdef __INSIDE_CYGWIN__ -39d35 -< #endif diff --git a/examples/coap/plugtest-server.c b/examples/coap/plugtest-server.c index c6c0e534f..7ca53bc2d 100644 --- a/examples/coap/plugtest-server.c +++ b/examples/coap/plugtest-server.c @@ -44,7 +44,7 @@ #include "coap.h" #include "coap-transactions.h" #include "coap-separate.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "plugtest.h" /* @@ -52,7 +52,7 @@ * The build system automatically compiles the resources in the corresponding * sub-directory. */ -extern resource_t +extern coap_resource_t res_plugtest_test, res_plugtest_validate, res_plugtest_create1, @@ -95,29 +95,29 @@ PROCESS_THREAD(plugtest_server, ev, data) PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); /* Activate the application-specific resources. */ - rest_activate_resource(&res_plugtest_test, "test"); - rest_activate_resource(&res_plugtest_validate, "validate"); - rest_activate_resource(&res_plugtest_create1, "create1"); - rest_activate_resource(&res_plugtest_create2, "create2"); - rest_activate_resource(&res_plugtest_create3, "create3"); - rest_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3"); - rest_activate_resource(&res_plugtest_query, "query"); - rest_activate_resource(&res_plugtest_locquery, "location-query"); - rest_activate_resource(&res_plugtest_multi, "multi-format"); - rest_activate_resource(&res_plugtest_link1, "link1"); - rest_activate_resource(&res_plugtest_link2, "link2"); - rest_activate_resource(&res_plugtest_link3, "link3"); - rest_activate_resource(&res_plugtest_path, "path"); - rest_activate_resource(&res_plugtest_separate, "separate"); - rest_activate_resource(&res_plugtest_large, "large"); - rest_activate_resource(&res_plugtest_large_update, "large-update"); - rest_activate_resource(&res_plugtest_large_create, "large-create"); - rest_activate_resource(&res_plugtest_obs, "obs"); + coap_activate_resource(&res_plugtest_test, "test"); + coap_activate_resource(&res_plugtest_validate, "validate"); + coap_activate_resource(&res_plugtest_create1, "create1"); + coap_activate_resource(&res_plugtest_create2, "create2"); + coap_activate_resource(&res_plugtest_create3, "create3"); + coap_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3"); + coap_activate_resource(&res_plugtest_query, "query"); + coap_activate_resource(&res_plugtest_locquery, "location-query"); + coap_activate_resource(&res_plugtest_multi, "multi-format"); + coap_activate_resource(&res_plugtest_link1, "link1"); + coap_activate_resource(&res_plugtest_link2, "link2"); + coap_activate_resource(&res_plugtest_link3, "link3"); + coap_activate_resource(&res_plugtest_path, "path"); + coap_activate_resource(&res_plugtest_separate, "separate"); + coap_activate_resource(&res_plugtest_large, "large"); + coap_activate_resource(&res_plugtest_large_update, "large-update"); + coap_activate_resource(&res_plugtest_large_create, "large-create"); + coap_activate_resource(&res_plugtest_obs, "obs"); - rest_activate_resource(&res_mirror, "mirror"); + coap_activate_resource(&res_mirror, "mirror"); /* Define application-specific events here. */ while(1) { diff --git a/examples/coap/plugtest.h b/examples/coap/plugtest.h index 78b168d4b..dff97282f 100644 --- a/examples/coap/plugtest.h +++ b/examples/coap/plugtest.h @@ -47,12 +47,8 @@ #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) #else #define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) #endif /* double expansion */ diff --git a/examples/coap/project-conf.h b/examples/coap/project-conf.h index d8a3b1122..115d6fbb0 100644 --- a/examples/coap/project-conf.h +++ b/examples/coap/project-conf.h @@ -36,43 +36,37 @@ * Matthias Kovatsch */ -#ifndef __PROJECT_ERBIUM_CONF_H__ -#define __PROJECT_ERBIUM_CONF_H__ +#ifndef PROJECT_ERBIUM_CONF_H_ +#define PROJECT_ERBIUM_CONF_H_ /* Custom channel and PAN ID configuration for your project. */ -/* - #define RF_CHANNEL 26 - #define IEEE802154_CONF_PANID 0xABCD - */ +/* #define RF_CHANNEL 26 */ +/* #define IEEE802154_CONF_PANID 0xABCD */ /* IP buffer size must match all other hops, in particular the border router. */ -/* - #define UIP_CONF_BUFFER_SIZE 256 - */ +/* #define UIP_CONF_BUFFER_SIZE 256 */ /* Increase rpl-border-router IP-buffer when using more than 64. */ -#define REST_MAX_CHUNK_SIZE 48 +#define COAP_MAX_CHUNK_SIZE 48 /* Estimate your header size, especially when using Proxy-Uri. */ -/* - #define COAP_MAX_HEADER_SIZE 70 - */ +/* #define COAP_MAX_HEADER_SIZE 70 */ /* Multiplies with chunk size, be aware of memory constraints. */ +#ifndef COAP_MAX_OPEN_TRANSACTIONS #define COAP_MAX_OPEN_TRANSACTIONS 4 +#endif /* COAP_MAX_OPEN_TRANSACTIONS */ /* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ -/* - #define COAP_MAX_OBSERVERS 2 - */ +/* #define COAP_MAX_OBSERVERS 2 */ /* Filtering .well-known/core per query can be disabled to save space. */ #define COAP_LINK_FORMAT_FILTERING 0 #define COAP_PROXY_OPTION_PROCESSING 0 -/* Turn off DAO-ACK to make code smaller */ -#define RPL_CONF_WITH_DAO_ACK 0 - /* Enable client-side support for COAP observe */ -#define COAP_OBSERVE_CLIENT 1 -#endif /* __PROJECT_ERBIUM_CONF_H__ */ +#ifndef COAP_OBSERVE_CLIENT +#define COAP_OBSERVE_CLIENT 1 +#endif /* COAP_OBSERVE_CLIENT */ + +#endif /* PROJECT_ERBIUM_CONF_H_ */ diff --git a/examples/coap/resources-plugtest/res-plugtest-create1.c b/examples/coap/resources-plugtest/res-plugtest-create1.c index 4e8c52231..50f48a09e 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create1.c +++ b/examples/coap/resources-plugtest/res-plugtest-create1.c @@ -37,12 +37,12 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create1, "title=\"Creates on PUT\"", @@ -54,27 +54,27 @@ RESOURCE(res_plugtest_create1, static uint8_t create1_exists = 0; static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create1 PUT"); if(coap_get_header_if_none_match(request)) { if(!create1_exists) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); create1_exists = 1; } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } else { - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create1 DELETE "); - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); create1_exists = 0; } diff --git a/examples/coap/resources-plugtest/res-plugtest-create2.c b/examples/coap/resources-plugtest/res-plugtest-create2.c index 714432ff6..169f47812 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create2.c +++ b/examples/coap/resources-plugtest/res-plugtest-create2.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create2, "title=\"Creates on POST\"", @@ -51,10 +51,10 @@ RESOURCE(res_plugtest_create2, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create2 "); - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/location1/location2/location3"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/location1/location2/location3"); } diff --git a/examples/coap/resources-plugtest/res-plugtest-create3.c b/examples/coap/resources-plugtest/res-plugtest-create3.c index fe7526eba..178a0089e 100644 --- a/examples/coap/resources-plugtest/res-plugtest-create3.c +++ b/examples/coap/resources-plugtest/res-plugtest-create3.c @@ -37,12 +37,12 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create3, "title=\"Default test resource\"", @@ -54,27 +54,27 @@ RESOURCE(res_plugtest_create3, static uint8_t create3_exists = 0; static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create3 PUT "); if(coap_get_header_if_none_match(request)) { if(!create3_exists) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); create3_exists = 1; } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } else { - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/create3 DELETE "); - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); create3_exists = 0; } diff --git a/examples/coap/resources-plugtest/res-plugtest-large-create.c b/examples/coap/resources-plugtest/res-plugtest-large-create.c index ac1e27a3d..78d21b69b 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large-create.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-create.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Large resource that can be created using POST method @@ -54,38 +54,38 @@ RESOURCE(res_plugtest_large_create, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; uint8_t *incoming = NULL; size_t len = 0; unsigned int ct = -1; - if(!REST.get_header_content_type(request, &ct)) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + if(!coap_get_header_content_format(request, &ct)) { + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoContentType"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) { + if((len = coap_get_payload(request, (const uint8_t **)&incoming))) { if(coap_req->block1_num * coap_req->block1_size + len <= 2048) { - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/nirvana"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/nirvana"); coap_set_header_block1(response, coap_req->block1_num, 0, coap_req->block1_size); } else { - REST.set_response_status(response, REST.status.REQUEST_ENTITY_TOO_LARGE); + coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13); const char *error_msg = "2048B max."; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoPayload"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } diff --git a/examples/coap/resources-plugtest/res-plugtest-large-update.c b/examples/coap/resources-plugtest/res-plugtest-large-update.c index 8263ccc2a..a79978be1 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large-update.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-update.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include #include "sys/cc.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE( res_plugtest_large_update, @@ -58,21 +59,21 @@ static uint8_t large_update_store[MAX_PLUGFEST_BODY] = { 0 }; static unsigned int large_update_ct = APPLICATION_OCTET_STREAM; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Check the offset for boundaries of the resource data. */ if(*offset >= large_update_size) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - REST.set_response_payload(response, large_update_store + *offset, + coap_set_payload(response, large_update_store + *offset, MIN(large_update_size - *offset, preferred_size)); - REST.set_header_content_type(response, large_update_ct); + coap_set_header_content_format(response, large_update_ct); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += preferred_size; @@ -83,22 +84,22 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; uint8_t *incoming = NULL; size_t len = 0; unsigned int ct = -1; - if(!REST.get_header_content_type(request, &ct)) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + if(!coap_get_header_content_format(request, &ct)) { + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoContentType"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) { + if((len = coap_get_payload(request, (const uint8_t **)&incoming))) { if(coap_req->block1_num * coap_req->block1_size + len <= sizeof(large_update_store)) { memcpy( large_update_store + coap_req->block1_num * coap_req->block1_size, @@ -106,13 +107,13 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr large_update_size = coap_req->block1_num * coap_req->block1_size + len; large_update_ct = ct; - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); coap_set_header_block1(response, coap_req->block1_num, 0, coap_req->block1_size); } else { - REST.set_response_status(response, - REST.status.REQUEST_ENTITY_TOO_LARGE); - REST.set_response_payload( + coap_set_status_code(response, + REQUEST_ENTITY_TOO_LARGE_4_13); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "%uB max.", @@ -120,9 +121,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr return; } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoPayload"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } diff --git a/examples/coap/resources-plugtest/res-plugtest-large.c b/examples/coap/resources-plugtest/res-plugtest-large.c index 8a7372eb8..f828e4dbe 100644 --- a/examples/coap/resources-plugtest/res-plugtest-large.c +++ b/examples/coap/resources-plugtest/res-plugtest-large.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_large, "title=\"Large resource\";rt=\"block\";sz=\"" TO_STRING(CHUNKS_TOTAL) "\"", @@ -51,17 +52,17 @@ RESOURCE(res_plugtest_large, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; /* Check the offset for boundaries of the resource data. */ if(*offset >= CHUNKS_TOTAL) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } @@ -79,8 +80,8 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(*offset + (int32_t)strpos > CHUNKS_TOTAL) { strpos = CHUNKS_TOTAL - *offset; } - REST.set_response_payload(response, buffer, strpos); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_payload(response, buffer, strpos); + coap_set_header_content_format(response, TEXT_PLAIN); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += strpos; diff --git a/examples/coap/resources-plugtest/res-plugtest-links.c b/examples/coap/resources-plugtest/res-plugtest-links.c index f802d3c56..99315a17f 100644 --- a/examples/coap/resources-plugtest/res-plugtest-links.c +++ b/examples/coap/resources-plugtest/res-plugtest-links.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_link1, "rt=\"Type1 Type2\";if=\"If1\"", @@ -63,9 +63,9 @@ RESOURCE(res_plugtest_link3, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *msg = "Dummy link"; - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, msg, strlen(msg)); } diff --git a/examples/coap/resources-plugtest/res-plugtest-locquery.c b/examples/coap/resources-plugtest/res-plugtest-locquery.c index d75a9a620..e93ef8b65 100644 --- a/examples/coap/resources-plugtest/res-plugtest-locquery.c +++ b/examples/coap/resources-plugtest/res-plugtest-locquery.c @@ -37,11 +37,11 @@ */ #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_locquery, "title=\"Resource accepting query parameters\"", @@ -51,15 +51,15 @@ RESOURCE(res_plugtest_locquery, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; #endif PRINTF( "/location-query POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "?first=1&second=2"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_query(response, "?first=1&second=2"); } diff --git a/examples/coap/resources-plugtest/res-plugtest-longpath.c b/examples/coap/resources-plugtest/res-plugtest-longpath.c index 5a26d4db9..7a1271321 100644 --- a/examples/coap/resources-plugtest/res-plugtest-longpath.c +++ b/examples/coap/resources-plugtest/res-plugtest-longpath.c @@ -36,12 +36,14 @@ * Matthias Kovatsch */ + +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_longpath, "title=\"Long path resource\"", @@ -51,14 +53,14 @@ RESOURCE(res_plugtest_longpath, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/seg1/seg2/seg3 GET "); /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, diff --git a/examples/coap/resources-plugtest/res-plugtest-multi.c b/examples/coap/resources-plugtest/res-plugtest-multi.c index c6592b397..f0a388430 100644 --- a/examples/coap/resources-plugtest/res-plugtest-multi.c +++ b/examples/coap/resources-plugtest/res-plugtest-multi.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_multi, "title=\"Resource providing text/plain and application/xml\";ct=\"0 41\"", @@ -51,27 +52,27 @@ RESOURCE(res_plugtest_multi, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); PRINTF("/multi-format GET (%s %u) ", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload( + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u%s", coap_req->type, coap_req->code, coap_req->mid, accept != -1 ? "\nAccept: 0" : "")); PRINTF("PLAIN\n"); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - REST.set_response_payload( + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, @@ -79,9 +80,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr coap_req->type, coap_req->code, coap_req->mid, accept)); PRINTF("XML\n"); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/xml"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); PRINTF("ERROR\n"); } } diff --git a/examples/coap/resources-plugtest/res-plugtest-obs.c b/examples/coap/resources-plugtest/res-plugtest-obs.c index 74d61d894..d60aaec04 100644 --- a/examples/coap/resources-plugtest/res-plugtest-obs.c +++ b/examples/coap/resources-plugtest/res-plugtest-obs.c @@ -36,15 +36,16 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "coap-observe.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_plugtest_obs, @@ -67,35 +68,35 @@ static void obs_purge_list() { PRINTF("### SERVER ACTION ### Purging obs list"); - coap_remove_observer_by_uri(NULL, 0, res_plugtest_obs.url); + coap_remove_observer_by_uri(NULL, res_plugtest_obs.url); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Keep server log clean from ticking events */ if(request != NULL) { PRINTF("/obs GET\n"); } - REST.set_header_content_type(response, obs_format); - REST.set_header_max_age(response, 5); + coap_set_header_content_format(response, obs_format); + coap_set_header_max_age(response, 5); if(obs_content_len) { - REST.set_header_content_type(response, obs_format); - REST.set_response_payload(response, obs_content, obs_content_len); + coap_set_header_content_format(response, obs_format); + coap_set_payload(response, obs_content, obs_content_len); } else { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, obs_content, + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, obs_content, snprintf(obs_content, MAX_PLUGFEST_PAYLOAD, "TICK %lu", (unsigned long) obs_counter)); } - /* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */ + /* A post_handler that handles subscriptions will be called for periodic resources by the CoAP framework. */ } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint8_t *incoming = NULL; unsigned int ct = -1; - REST.get_header_content_type(request, &ct); + coap_get_header_content_format(request, &ct); PRINTF("/obs PUT\n"); @@ -103,26 +104,26 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr obs_status = 1; obs_format = ct; } else { - obs_content_len = REST.get_request_payload(request, + obs_content_len = coap_get_payload(request, (const uint8_t **)&incoming); memcpy(obs_content, incoming, obs_content_len); res_periodic_handler(); } - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { PRINTF("/obs DELETE\n"); obs_status = 2; - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. - * It will be called by the REST manager process with the defined period. + * It will be called by the CoAP manager process with the defined period. */ static void res_periodic_handler() @@ -134,7 +135,7 @@ res_periodic_handler() if(obs_status == 1) { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); PRINTF("######### sending 5.00\n"); @@ -142,7 +143,7 @@ res_periodic_handler() } else if(obs_status == 2) { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); obs_purge_list(); @@ -150,6 +151,6 @@ res_periodic_handler() obs_content_len = 0; } else { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); } obs_status = 0; } diff --git a/examples/coap/resources-plugtest/res-plugtest-path.c b/examples/coap/resources-plugtest/res-plugtest-path.c index 03eb362bb..fac05ccb0 100644 --- a/examples/coap/resources-plugtest/res-plugtest-path.c +++ b/examples/coap/resources-plugtest/res-plugtest-path.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); PARENT_RESOURCE(res_plugtest_path, "title=\"Path test resource\";ct=\"40\"", @@ -51,22 +52,22 @@ PARENT_RESOURCE(res_plugtest_path, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *uri_path = NULL; - int len = REST.get_url(request, &uri_path); + int len = coap_get_header_uri_path(request, &uri_path); int base_len = strlen(res_plugtest_path.url); if(len == base_len) { - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); + coap_set_header_content_format(response, APPLICATION_LINK_FORMAT); snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, ",,"); } else { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "/%.*s", len, uri_path); } - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } diff --git a/examples/coap/resources-plugtest/res-plugtest-query.c b/examples/coap/resources-plugtest/res-plugtest-query.c index 6ffbccbbb..10df145b3 100644 --- a/examples/coap/resources-plugtest/res-plugtest-query.c +++ b/examples/coap/resources-plugtest/res-plugtest-query.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_query, "title=\"Resource accepting query parameters\"", @@ -51,22 +52,22 @@ RESOURCE(res_plugtest_query, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; int len = 0; const char *query = NULL; PRINTF( "/query GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - if((len = REST.get_query(request, &query))) { + if((len = coap_get_header_uri_query(request, &query))) { PRINTF("Query: %.*s\n", len, query); /* Code 2.05 CONTENT is default. */ } - REST.set_header_content_type(response, - REST.type.TEXT_PLAIN); - REST.set_response_payload( + coap_set_header_content_format(response, + TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, diff --git a/examples/coap/resources-plugtest/res-plugtest-separate.c b/examples/coap/resources-plugtest/res-plugtest-separate.c index b45841ec1..16aa267ce 100644 --- a/examples/coap/resources-plugtest/res-plugtest-separate.c +++ b/examples/coap/resources-plugtest/res-plugtest-separate.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "coap-transactions.h" #include "coap-separate.h" #include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); PERIODIC_RESOURCE(res_plugtest_separate, @@ -67,9 +68,9 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[1]; void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/separate "); if(separate_active) { @@ -97,17 +98,16 @@ res_resume_handler() PRINTF("/separate "); coap_transaction_t *transaction = NULL; if((transaction = coap_new_transaction(separate_store->request_metadata.mid, - &separate_store->request_metadata.addr, - separate_store->request_metadata.port))) { + &separate_store->request_metadata.endpoint))) { PRINTF( "RESPONSE (%s %u)\n", separate_store->request_metadata.type == COAP_TYPE_CON ? "CON" : "NON", separate_store->request_metadata.mid); - coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ + coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); @@ -120,8 +120,8 @@ res_resume_handler() separate_store->request_metadata.block2_size); /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(response, - transaction->packet); + transaction->message_len = coap_serialize_message(response, + transaction->message); coap_send_transaction(transaction); /* The engine will clear the transaction (right after send for NON, after acked for CON). */ diff --git a/examples/coap/resources-plugtest/res-plugtest-test.c b/examples/coap/resources-plugtest/res-plugtest-test.c index 4af32b9ba..f7ac97c83 100644 --- a/examples/coap/resources-plugtest/res-plugtest-test.c +++ b/examples/coap/resources-plugtest/res-plugtest-test.c @@ -36,15 +36,17 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" +#include "random.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_test, "title=\"Default test resource\"", res_get_handler, res_post_handler, res_put_handler, res_delete_handler); @@ -69,9 +71,9 @@ test_update_etag() PRINTF("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", test_etag_len, test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; if(test_change) { test_update_etag(); @@ -82,48 +84,48 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && len == test_etag_len && memcmp(test_etag, bytes, len) == 0) { PRINTF("validate "); - REST.set_response_status(response, REST.status.NOT_MODIFIED); - REST.set_header_etag(response, test_etag, test_etag_len); + coap_set_status_code(response, VALID_2_03); + coap_set_header_etag(response, test_etag, test_etag_len); test_change = 1; PRINTF("### SERVER ACTION ### Resource will change\n"); } else { /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_etag(response, test_etag, test_etag_len); - REST.set_header_max_age(response, 30); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_etag(response, test_etag, test_etag_len); + coap_set_header_max_age(response, 30); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u", coap_req->type, coap_req->code, coap_req->mid)); } } static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/test POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/location1/location2/location3"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/location1/location2/location3"); } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/test PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif if(coap_get_header_if_none_match(request)) { if(test_none_match_okay) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); test_none_match_okay = 0; PRINTF("### SERVER ACTION ### If-None-Match will FAIL\n"); } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); test_none_match_okay = 1; PRINTF("### SERVER ACTION ### If-None-Match will SUCCEED\n"); @@ -133,9 +135,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && memcmp(test_etag, bytes, len) == 0)) || len == 0) { test_update_etag(); - REST.set_header_etag(response, test_etag, test_etag_len); + coap_set_header_etag(response, test_etag, test_etag_len); - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); if(len > 0) { test_change = 1; @@ -148,15 +150,15 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/test DELETE (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); } diff --git a/examples/coap/resources-plugtest/res-plugtest-validate.c b/examples/coap/resources-plugtest/res-plugtest-validate.c index ab7b6cfca..30d97e727 100644 --- a/examples/coap/resources-plugtest/res-plugtest-validate.c +++ b/examples/coap/resources-plugtest/res-plugtest-validate.c @@ -36,13 +36,15 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "plugtest.h" +#include "random.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_validate, "title=\"Validation test resource\"", @@ -72,9 +74,9 @@ validate_update_etag() validate_etag_len, validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; if(validate_change) { validate_update_etag(); @@ -85,17 +87,17 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if((len = coap_get_header_etag(request, &bytes)) > 0 && len == validate_etag_len && memcmp(validate_etag, bytes, len) == 0) { PRINTF("validate "); - REST.set_response_status(response, REST.status.NOT_MODIFIED); - REST.set_header_etag(response, validate_etag, validate_etag_len); + coap_set_status_code(response, VALID_2_03); + coap_set_header_etag(response, validate_etag, validate_etag_len); validate_change = 1; PRINTF("### SERVER ACTION ### Resouce will change\n"); } else { /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_etag(response, validate_etag, validate_etag_len); - REST.set_header_max_age(response, 30); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_etag(response, validate_etag, validate_etag_len); + coap_set_header_max_age(response, 30); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, @@ -104,10 +106,10 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { #if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; #endif PRINTF("/validate PUT "); @@ -118,9 +120,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && memcmp(validate_etag, bytes, len) == 0)) || len == 0) { validate_update_etag(); - REST.set_header_etag(response, validate_etag, validate_etag_len); + coap_set_header_etag(response, validate_etag, validate_etag_len); - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); if(len > 0) { validate_change = 1; @@ -134,6 +136,6 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]); - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } diff --git a/examples/coap/resources/res-b1-sep-b2.c b/examples/coap/resources/res-b1-sep-b2.c index 26b6b8606..0fa76726f 100644 --- a/examples/coap/resources/res-b1-sep-b2.c +++ b/examples/coap/resources/res-b1-sep-b2.c @@ -36,13 +36,14 @@ * Lars Schmertmann */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap-block1.h" #include "coap-separate.h" #include "coap-transactions.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); SEPARATE_RESOURCE(res_b1_sep_b2, "title=\"Block1 + Separate + Block2 demo\"", NULL, res_post_handler, NULL, NULL, NULL); #define MAX_DATA_LEN 256 @@ -52,7 +53,7 @@ static size_t big_msg_len = 0; static coap_separate_t request_metadata; static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Example allows only one request on time. There are no checks for multiply access !!! */ if(*offset == 0) { @@ -75,8 +76,8 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer /* Send first block */ coap_transaction_t *transaction = NULL; - if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.addr, request_metadata.port))) { - coap_packet_t resp[1]; /* This way the packet can be treated as pointer as usual. */ + if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.endpoint))) { + coap_message_t resp[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(resp, &request_metadata, CONTENT_2_05); @@ -88,7 +89,7 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer } /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(resp, transaction->packet); + transaction->message_len = coap_serialize_message(resp, transaction->message); coap_send_transaction(transaction); } } else { diff --git a/examples/coap/resources/res-battery.c b/examples/coap/resources/res-battery.c index b82523594..b4c7623b3 100644 --- a/examples/coap/resources/res-battery.c +++ b/examples/coap/resources/res-battery.c @@ -41,10 +41,11 @@ #if PLATFORM_HAS_BATTERY #include -#include "rest-engine.h" +#include +#include "coap-engine.h" #include "dev/battery-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_battery, @@ -55,27 +56,27 @@ RESOURCE(res_battery, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int battery = battery_sensor.value(0); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", battery); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", battery); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'battery':%d}", battery); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'battery':%d}", battery); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_BATTERY */ diff --git a/examples/coap/resources/res-chunks.c b/examples/coap/resources/res-chunks.c index 13de706c8..39555d091 100644 --- a/examples/coap/resources/res-chunks.c +++ b/examples/coap/resources/res-chunks.c @@ -36,13 +36,14 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* - * For data larger than REST_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation + * For data larger than COAP_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation * and split their responses by themselves. To transfer the complete resource through a TCP stream or CoAP's blockwise transfer, * the byte offset where to continue is provided to the handler as int32_t pointer. * These chunk-wise resources must set the offset value to its new position or -1 of the end is reached. @@ -58,17 +59,17 @@ RESOURCE(res_chunks, #define CHUNKS_TOTAL 2050 static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; /* Check the offset for boundaries of the resource data. */ if(*offset >= CHUNKS_TOTAL) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } @@ -85,7 +86,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(*offset + (int32_t)strpos > CHUNKS_TOTAL) { strpos = CHUNKS_TOTAL - *offset; } - REST.set_response_payload(response, buffer, strpos); + coap_set_payload(response, buffer, strpos); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += strpos; diff --git a/examples/coap/resources/res-event.c b/examples/coap/resources/res-event.c index 35ff1f8eb..5640353b3 100644 --- a/examples/coap/resources/res-event.c +++ b/examples/coap/resources/res-event.c @@ -36,8 +36,9 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #define DEBUG 0 @@ -52,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_event_handler(void); /* @@ -74,10 +75,10 @@ EVENT_RESOURCE(res_event, static int32_t event_counter = 0; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter)); /* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */ } @@ -96,6 +97,6 @@ res_event_handler(void) PRINTF("TICK %u for /%s\n", event_counter, res_event.url); /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_event); + coap_notify_observers(&res_event); } } diff --git a/examples/coap/resources/res-hello.c b/examples/coap/resources/res-hello.c index 9208f8b74..46b0139ef 100644 --- a/examples/coap/resources/res-hello.c +++ b/examples/coap/resources/res-hello.c @@ -38,9 +38,9 @@ #include #include -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * A handler function named [resource name]_handler must be implemented for each RESOURCE. @@ -56,7 +56,7 @@ RESOURCE(res_hello, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *len = NULL; /* Some data that has the length up to REST_MAX_CHUNK_SIZE. For more, see the chunk resource. */ @@ -64,7 +64,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr int length = 12; /* |<-------->| */ /* The query string can be retrieved by rest_get_query() or parsed for its key-value pairs. */ - if(REST.get_query_variable(request, "len", &len)) { + if(coap_get_query_variable(request, "len", &len)) { length = atoi(len); if(length < 0) { length = 0; @@ -75,7 +75,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr memcpy(buffer, message, length); } else { memcpy(buffer, message, length); - } REST.set_header_content_type(response, REST.type.TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */ - REST.set_header_etag(response, (uint8_t *)&length, 1); - REST.set_response_payload(response, buffer, length); + } coap_set_header_content_format(response, TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */ + coap_set_header_etag(response, (uint8_t *)&length, 1); + coap_set_payload(response, buffer, length); } diff --git a/examples/coap/resources/res-leds.c b/examples/coap/resources/res-leds.c index 5fbcf6c77..d601e49f5 100644 --- a/examples/coap/resources/res-leds.c +++ b/examples/coap/resources/res-leds.c @@ -37,12 +37,12 @@ */ #include "contiki.h" - -#if PLATFORM_HAS_LEDS +#include "coap-engine.h" +#include "dev/leds.h" #include -#include "rest-engine.h" -#include "dev/leds.h" + +#if PLATFORM_HAS_LEDS || LEDS_COUNT #define DEBUG 0 #if DEBUG @@ -56,9 +56,9 @@ #define PRINTLLADDR(addr) #endif -static void res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ +/* A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated */ RESOURCE(res_leds, "title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\"", NULL, @@ -67,7 +67,7 @@ RESOURCE(res_leds, NULL); static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *color = NULL; @@ -75,7 +75,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr uint8_t led = 0; int success = 1; - if((len = REST.get_query_variable(request, "color", &color))) { + if((len = coap_get_query_variable(request, "color", &color))) { PRINTF("color %.*s\n", len, color); if(strncmp(color, "r", len) == 0) { @@ -89,7 +89,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr } } else { success = 0; - } if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + } if(success && (len = coap_get_post_variable(request, "mode", &mode))) { PRINTF("mode %s\n", mode); if(strncmp(mode, "on", len) == 0) { @@ -102,7 +102,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr } else { success = 0; } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } #endif /* PLATFORM_HAS_LEDS */ diff --git a/examples/coap/resources/res-light.c b/examples/coap/resources/res-light.c index 226d814bb..3384b2e5f 100644 --- a/examples/coap/resources/res-light.c +++ b/examples/coap/resources/res-light.c @@ -40,11 +40,12 @@ #if PLATFORM_HAS_LIGHT +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/light-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_light, @@ -55,33 +56,33 @@ RESOURCE(res_light, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint16_t light_photosynthetic = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); uint16_t light_solar = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", light_photosynthetic, light_solar); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain, application/xml, and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_LIGHT */ diff --git a/examples/coap/resources/res-mirror.c b/examples/coap/resources/res-mirror.c index 15b7c3b80..1ba948b0d 100644 --- a/examples/coap/resources/res-mirror.c +++ b/examples/coap/resources/res-mirror.c @@ -36,8 +36,9 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #define DEBUG 0 @@ -52,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -static void res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */ RESOURCE(res_mirror, @@ -63,7 +64,7 @@ RESOURCE(res_mirror, res_any_handler); static void -res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* The ETag and Token is copied to the header. */ uint8_t opaque[] = { 0x0A, 0xBC, 0xDE }; @@ -89,28 +90,28 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr /* snprintf() counts the terminating '\0' to the size parameter. * The additional byte is taken care of by allocating REST_MAX_CHUNK_SIZE+1 bytes in the REST framework. * Add +1 to fill the complete buffer, as the payload does not need a terminating '\0'. */ - if(REST.get_header_content_type(request, &content_format)) { + if(coap_get_header_content_format(request, &content_format)) { strpos += snprintf((char *)buffer, REST_MAX_CHUNK_SIZE + 1, "CF %u\n", content_format); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_accept(request, &content_format))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_accept(request, &content_format))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ac %u\n", content_format); /* Some getters such as for ETag or Location are omitted, as these options should not appear in a request. * Max-Age might appear in HTTP requests or used for special purposes in CoAP. */ } - if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_max_age(request, &longint)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_max_age(request, &longint)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "MA %lu\n", (unsigned long) longint); /* For HTTP this is the Length option, for CoAP it is the Size option. */ } - if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_length(request, &longint)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_size1(request, &longint)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "SZ %lu\n", (unsigned long) longint); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_host(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_host(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UH %.*s\n", len, str); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_url(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_path(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UP %.*s\n", len, str); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_query(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_query(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UQ %.*s\n", len, str); /* Undefined request options for debugging: actions not required for normal RESTful Web service. */ } @@ -121,7 +122,7 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "LQ %.*s\n", len, str); /* CoAP-specific example: actions not required for normal RESTful Web service. */ } - coap_packet_t *const coap_pkt = (coap_packet_t *)request; + coap_message_t *const coap_pkt = (coap_message_t *)request; if(strpos <= REST_MAX_CHUNK_SIZE && coap_pkt->token_len > 0) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "To 0x"); @@ -132,10 +133,10 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "\n"); } - if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ob %lu\n", (unsigned long) coap_pkt->observe); } - if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "ET 0x"); int index = 0; for(index = 0; index < coap_pkt->etag_len; ++index) { @@ -149,22 +150,22 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_block1(request, &block_num, &block_more, &block_size, NULL)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "B1 %lu%s (%u)\n", (unsigned long) block_num, block_more ? "+" : "", block_size); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_request_payload(request, &bytes))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_payload(request, &bytes))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "%.*s", len, bytes); } if(strpos >= REST_MAX_CHUNK_SIZE) { buffer[REST_MAX_CHUNK_SIZE - 1] = 0xBB; /* '»' to indicate truncation */ } - REST.set_response_payload(response, buffer, strpos); + coap_set_payload(response, buffer, strpos); PRINTF("/mirror options received: %s\n", buffer); /* Set dummy header options for response. Like getters, some setters are not implemented for HTTP and have no effect. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */ - REST.set_header_etag(response, opaque, 2); - REST.set_header_location(response, location); /* Initial slash is omitted by framework */ - REST.set_header_length(response, strpos); /* For HTTP, browsers will not re-request the page for 10 seconds. CoAP action depends on the client. */ + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */ + coap_set_header_etag(response, opaque, 2); + coap_set_header_location_path(response, location); /* Initial slash is omitted by framework */ + coap_set_header_size1(response, strpos); /* For HTTP, browsers will not re-request the page for 10 s. CoAP action depends on the client. */ /* CoAP-specific example: actions not required for normal RESTful Web service. */ coap_set_header_uri_host(response, "tiki"); diff --git a/examples/coap/resources/res-push.c b/examples/coap/resources/res-push.c index 120e2ffef..ffc8c9c07 100644 --- a/examples/coap/resources/res-push.c +++ b/examples/coap/resources/res-push.c @@ -36,11 +36,12 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_push, @@ -58,18 +59,18 @@ PERIODIC_RESOURCE(res_push, static int32_t event_counter = 0; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. - * Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers(). + * Otherwise the requests must be stored with the observer list and passed by coap_notify_subscribers(). * This would be a TODO in the corresponding files in contiki/apps/erbium/! */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter)); - /* The REST.subscription_handler() will be called for observable resources by the REST framework. */ + /* The coap_subscription_handler() will be called for observable resources by the REST framework. */ } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. @@ -84,6 +85,6 @@ res_periodic_handler() /* Usually a condition is defined under with subscribers are notified, e.g., large enough delta in sensor reading. */ if(1) { /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_push); + coap_notify_observers(&res_push); } } diff --git a/examples/coap/resources/res-radio.c b/examples/coap/resources/res-radio.c index b33bf703a..c23436bb6 100644 --- a/examples/coap/resources/res-radio.c +++ b/examples/coap/resources/res-radio.c @@ -39,12 +39,12 @@ #include "contiki.h" #if PLATFORM_HAS_RADIO - +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "net/netstack.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading of the rssi/lqi from radio sensor */ RESOURCE(res_radio, @@ -55,7 +55,7 @@ RESOURCE(res_radio, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *p = NULL; @@ -64,9 +64,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr int success = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if((len = REST.get_query_variable(request, "p", &p))) { + if((len = coap_get_query_variable(request, "p", &p))) { if(strncmp(p, "rssi", len) == 0) { if(NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &value) == RADIO_RESULT_OK) { @@ -77,23 +77,23 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } if(success) { - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", rssi); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", rssi); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } #endif /* PLATFORM_HAS_RADIO */ diff --git a/examples/coap/resources/res-separate.c b/examples/coap/resources/res-separate.c index fb402d2b9..6b98345bb 100644 --- a/examples/coap/resources/res-separate.c +++ b/examples/coap/resources/res-separate.c @@ -37,11 +37,12 @@ */ #include -#include "rest-engine.h" +#include +#include "coap-engine.h" #include "coap-separate.h" #include "coap-transactions.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); SEPARATE_RESOURCE(res_separate, @@ -68,7 +69,7 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[COAP_MAX_OPEN_SEPARATE]; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * Example allows only one open separate response. @@ -96,11 +97,11 @@ res_resume_handler() { if(separate_active) { coap_transaction_t *transaction = NULL; - if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.addr, separate_store->request_metadata.port))) { - coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ + if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.endpoint))) { + coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ - coap_separate_resume(response, &separate_store->request_metadata, REST.status.OK); + coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); @@ -111,7 +112,7 @@ res_resume_handler() coap_set_header_block2(response, separate_store->request_metadata.block2_num, 0, separate_store->request_metadata.block2_size); /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(response, transaction->packet); + transaction->message_len = coap_serialize_message(response, transaction->message); coap_send_transaction(transaction); /* The engine will clear the transaction (right after send for NON, after acked for CON). */ diff --git a/examples/coap/resources/res-sht11.c b/examples/coap/resources/res-sht11.c index 56ed86c01..4dcf30e70 100644 --- a/examples/coap/resources/res-sht11.c +++ b/examples/coap/resources/res-sht11.c @@ -43,11 +43,12 @@ #if PLATFORM_HAS_SHT11 +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/sht11/sht11-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* Get Method Example. Returns the reading from temperature and humidity sensors. */ RESOURCE(res_sht11, @@ -58,7 +59,7 @@ RESOURCE(res_sht11, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Temperature in Celsius (t in 14 bits resolution at 3 Volts) * T = -39.60 + 0.01*t @@ -70,27 +71,27 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr uint16_t rh = sht11_sensor.value(SHT11_SENSOR_HUMIDITY); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", temperature, rh); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", temperature, rh); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", temperature, rh); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", temperature, rh); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain, application/xml, and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_SHT11 */ diff --git a/examples/coap/resources/res-sub.c b/examples/coap/resources/res-sub.c index 1d6f17aeb..88bc6a584 100644 --- a/examples/coap/resources/res-sub.c +++ b/examples/coap/resources/res-sub.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Example for a resource that also handles all its sub-resources. - * Use REST.get_url() to multiplex the handling of the request depending on the Uri-Path. + * Use coap_get_url() to multiplex the handling of the request depending on the Uri-Path. */ PARENT_RESOURCE(res_sub, "title=\"Sub-resource demo\"", @@ -53,17 +54,17 @@ PARENT_RESOURCE(res_sub, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); const char *uri_path = NULL; - int len = REST.get_url(request, &uri_path); + int len = coap_get_header_uri_path(request, &uri_path); int base_len = strlen(res_sub.url); if(len == base_len) { - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url); } else { - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len); - } REST.set_response_payload(response, buffer, strlen((char *)buffer)); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len); + } coap_set_payload(response, buffer, strlen((char *)buffer)); } diff --git a/examples/coap/resources/res-temperature.c b/examples/coap/resources/res-temperature.c index c8bce8ba8..ac34dbe33 100644 --- a/examples/coap/resources/res-temperature.c +++ b/examples/coap/resources/res-temperature.c @@ -44,11 +44,12 @@ #include #include +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/temperature-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); #define MAX_AGE 60 @@ -69,43 +70,43 @@ PERIODIC_RESOURCE(res_temperature, res_periodic_handler); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. - * Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers(). + * Otherwise the requests must be stored with the observer list and passed by coap_notify_observers(). * This would be a TODO in the corresponding files in contiki/apps/erbium/! */ int temperature = temperature_sensor.value(0); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", temperature); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", temperature); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } - REST.set_header_max_age(response, MAX_AGE); + coap_set_header_max_age(response, MAX_AGE); - /* The REST.subscription_handler() will be called for observable resources by the REST framework. */ + /* The coap_subscription_handler() will be called for observable resources by the coap_framework. */ } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. - * It will be called by the REST manager process with the defined period. + * It will be called by the coap_manager process with the defined period. */ static void res_periodic_handler() @@ -119,7 +120,7 @@ res_periodic_handler() interval_counter = 0; temperature_old = temperature; /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_temperature); + coap_notify_observers(&res_temperature); } } #endif /* PLATFORM_HAS_TEMPERATURE */ diff --git a/examples/coap/resources/res-toggle.c b/examples/coap/resources/res-toggle.c index d8a773306..b90ac77c7 100644 --- a/examples/coap/resources/res-toggle.c +++ b/examples/coap/resources/res-toggle.c @@ -37,15 +37,14 @@ */ #include "contiki.h" - -#if PLATFORM_HAS_LEDS - -#include -#include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +#include + +#if PLATFORM_HAS_LEDS || LEDS_COUNT + +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple actuator example. Toggles the red led */ RESOURCE(res_toggle, @@ -56,7 +55,7 @@ RESOURCE(res_toggle, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); } diff --git a/examples/coap/server-client-native.csc b/examples/coap/server-client-native.csc deleted file mode 100644 index cec9ca8a7..000000000 --- a/examples/coap/server-client-native.csc +++ /dev/null @@ -1,231 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - slipradio - Sky SLIP radio - [CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.c - make slip-radio.sky TARGET=sky - [CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-client.c - make coap-example-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 30.303994886410642 - 17.22128424003353 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - slipradio - - - - - org.contikios.cooja.interfaces.Position - 46.57186415376375 - 37.25589203828498 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 18.194682268367348 - 50.210548118402656 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 1 - 2 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 2.255467003316979 0.0 0.0 2.255467003316979 59.30641698643764 -13.478401994502008 - - 300 - 2 - 178 - 262 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 4 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 6 - 712 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 1 - - Serial port - 0,0 - - 853 - 3 - 491 - 765 - 182 - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 1 - 82 - 606 - 51 - - - diff --git a/examples/coap/server-client-observe.csc b/examples/coap/server-client-observe.csc deleted file mode 100644 index a7c9cca8b..000000000 --- a/examples/coap/server-client-observe.csc +++ /dev/null @@ -1,203 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-observe-client.c - make coap-example-observe-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-observe-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 54.537149936813485 - 51.51086225537906 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 77.97942851220571 - 67.86182390447284 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 3 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 2.092412892721766 0.0 0.0 2.092412892721766 34.70057915472623 -45.606066372444175 - - 300 - 4 - 178 - 261 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 0 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 167 - - false - false - - - 560 - 1 - 492 - 764 - 181 - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - - 60001 - true - - 362 - 2 - 116 - 561 - 1 - - - diff --git a/examples/coap/server-client.csc b/examples/coap/server-client.csc deleted file mode 100644 index a649d048a..000000000 --- a/examples/coap/server-client.csc +++ /dev/null @@ -1,231 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-client.c - make coap-example-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 46.57186415376375 - 40.35946215910942 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 18.638049428485125 - 47.55034515769599 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 3.61568947862321 0.0 0.0 3.61568947862321 15.610600779367 -85.92728269158351 - - 300 - 2 - 178 - 261 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 3 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 4 - 74 - 578 - 18 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 6 - 712 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 2 - - Serial port - 0,0 - - 853 - 1 - 491 - 765 - 182 - - - diff --git a/examples/coap/server-only.csc b/examples/coap/server-only.csc deleted file mode 100644 index 715deae1c..000000000 --- a/examples/coap/server-only.csc +++ /dev/null @@ -1,193 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 35.100895239785295 - 39.70574552287428 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 7.9849281638410705 0.0 0.0 7.9849281638410705 -133.27812697619663 -225.04752569190535 - - 300 - 1 - 175 - 262 - 2 - - - org.contikios.cooja.plugins.LogListener - - - - - - 560 - 3 - 326 - 1 - 293 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 4 - 74 - 39 - 199 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 4 - 622 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 1 - - Serial port - 0,0 - - 702 - 2 - 646 - 564 - 2 - - - diff --git a/examples/coap/sky/module-macros.h b/examples/coap/sky/module-macros.h new file mode 100644 index 000000000..3fcb04015 --- /dev/null +++ b/examples/coap/sky/module-macros.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#error The CoAP example no longer fits the limited ROM in the Tmote Sky. \ + Please select another platform with more ROM to compile the CoAP example. + +/*---------------------------------------------------------------------------*/ +#define COAP_OBSERVE_CLIENT 0 + +#define COAP_MAX_CHUNK_SIZE 48 + +/* Turn off DAO-ACK and probing to make code smaller */ +#define RPL_CONF_WITH_DAO_ACK 0 + +#define LOG_CONF_LEVEL_MAIN 0 + +#define DCOSYNCH_CONF_ENABLED 0 + +#define PROCESS_CONF_NUMEVENTS 8 +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/Makefile b/examples/dev/gpio-hal/Makefile new file mode 100644 index 000000000..d20495a60 --- /dev/null +++ b/examples/dev/gpio-hal/Makefile @@ -0,0 +1,10 @@ +CONTIKI_PROJECT = gpio-hal-example +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.identify-target + +MODULES_REL += $(TARGET) + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/dev/gpio-hal/README.md b/examples/dev/gpio-hal/README.md new file mode 100644 index 000000000..84ab68f88 --- /dev/null +++ b/examples/dev/gpio-hal/README.md @@ -0,0 +1,36 @@ +# GPIO HAL Example +This example demonstrates and tests the functionality of the GPIO HAL. You can +use it to: + +* Understand the logic of the GPIO HAL. +* Test your implementation of arch-specific GPIO HAL components if you are +developing a new port. + +This example assumes a device with: + +* 3 output pins (e.g. LEDs). +* 1 button. + +# Supported devices +This example is expected to work off-the-shelf on the following boards: + +* All CC13xx/CC26xx devices +* All CC2538 devices + +# Extending for other platforms +Create a sub-directory with the same name as your platform. For example, for +platform `my-new-platform` create a subdirectory called `my-new-platform`. +Source files in this directory will be compiled automatically. In the most +simple case, all you will need is a source file called e.g. `pins.c` (it's OK +to use a different filename). In this file, you will need to provide +definitions of the variables used by the example to manipulate pins. These +variables are: + +* `out_pin1`, `out_pin2` and `out_pin3` for output pins. +* `btn_pin` for the button pin. + +Assign to those variables a value that corresponds to the output pin in your +board that you wish to test with the example. For example, if you have a LED +connected to pin 20, then you will need to + + gpio_hal_pin_t out_pin1 = 20; diff --git a/examples/dev/gpio-hal/cc2538dk/pins.c b/examples/dev/gpio-hal/cc2538dk/pins.c new file mode 100644 index 000000000..4cb3e9742 --- /dev/null +++ b/examples/dev/gpio-hal/cc2538dk/pins.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +/* + * LEDs on the SmartRF06 (EB and BB) are connected as follows: + * - LED1 (Red) -> PC0 + * - LED2 (Yellow) -> PC1 (gpio_hal_pin_t 17) + * - LED3 (Green) -> PC2 (gpio_hal_pin_t 18) + * - LED4 (Orange) -> PC3 (gpio_hal_pin_t 19) + * + * LED1 shares the same pin with the USB pullup, so here we'll use PC1, PC2 + * and PC3. + */ +gpio_hal_pin_t out_pin1 = 17; +gpio_hal_pin_t out_pin2 = 18; +gpio_hal_pin_t out_pin3 = 19; +/*---------------------------------------------------------------------------*/ +/* Button pin: Button select, PA3 */ +gpio_hal_pin_t btn_pin = 3; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/gpio-hal-example.c b/examples/dev/gpio-hal/gpio-hal-example.c new file mode 100644 index 000000000..83f3b6a2f --- /dev/null +++ b/examples/dev/gpio-hal/gpio-hal-example.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "sys/etimer.h" +#include "lib/sensors.h" +#include "dev/button-sensor.h" + +#include +/*---------------------------------------------------------------------------*/ +extern gpio_hal_pin_t out_pin1, out_pin2, out_pin3; +extern gpio_hal_pin_t btn_pin; +/*---------------------------------------------------------------------------*/ +static struct etimer et; +static uint8_t counter; +/*---------------------------------------------------------------------------*/ +PROCESS(gpio_hal_example, "GPIO HAL Example"); +AUTOSTART_PROCESSES(&gpio_hal_example); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(gpio_hal_example, ev, data) +{ + PROCESS_BEGIN(); + + counter = 0; + + etimer_set(&et, CLOCK_SECOND); + + while(1) { + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER && data == &et) { + if((counter & 7) == 0) { + /* Set output and test write, high */ + gpio_hal_arch_pin_set_output(out_pin1); + gpio_hal_arch_pin_set_output(out_pin2); + gpio_hal_arch_pin_set_output(out_pin3); + + gpio_hal_arch_write_pin(out_pin1, 1); + gpio_hal_arch_write_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3), + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 1) { + /* Test write, low */ + gpio_hal_arch_write_pin(out_pin1, 0); + gpio_hal_arch_write_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3), 0); + } else if((counter & 7) == 2) { + /* Test set */ + gpio_hal_arch_set_pin(out_pin1); + gpio_hal_arch_set_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 3) { + /* Test clear */ + gpio_hal_arch_clear_pin(out_pin1); + gpio_hal_arch_clear_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 4) { + /* Test toggle (should go high) */ + gpio_hal_arch_toggle_pin(out_pin1); + gpio_hal_arch_toggle_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 5) { + /* Test toggle (should go low) */ + gpio_hal_arch_toggle_pin(out_pin1); + gpio_hal_arch_toggle_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 6) { + /* Set to input and then set. Should stay off */ + gpio_hal_arch_pin_set_input(out_pin1); + gpio_hal_arch_pin_set_input(out_pin2); + gpio_hal_arch_pin_set_input(out_pin3); + gpio_hal_arch_set_pin(out_pin1); + gpio_hal_arch_set_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 7) { + /* Toggle button interrupt */ + gpio_hal_pin_cfg_t interrupt; + + interrupt = gpio_hal_arch_pin_cfg_get(btn_pin) & + GPIO_HAL_PIN_CFG_INT_ENABLE; + + if(interrupt == 0) { + printf("Enabling button interrupt\n"); + gpio_hal_arch_interrupt_enable(btn_pin); + } else { + printf("Disabling button interrupt\n"); + gpio_hal_arch_interrupt_disable(btn_pin); + } + } + + /* Test read */ + printf("%u: Pins are 1-%u, 2=%u, 3=%u, mask=0x%08lx\n", counter & 7, + gpio_hal_arch_read_pin(out_pin1), + gpio_hal_arch_read_pin(out_pin2), + gpio_hal_arch_read_pin(out_pin3), + gpio_hal_arch_read_pins(gpio_hal_pin_to_mask(out_pin1) | + gpio_hal_pin_to_mask(out_pin2) | + gpio_hal_pin_to_mask(out_pin3))); + + counter++; + etimer_set(&et, CLOCK_SECOND); + } else if(ev == sensors_event && data == &button_sensor) { + printf("Button event\n"); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/openmote-cc2538/pins.c b/examples/dev/gpio-hal/openmote-cc2538/pins.c new file mode 100644 index 000000000..340aff15c --- /dev/null +++ b/examples/dev/gpio-hal/openmote-cc2538/pins.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +/* + * LEDs on the OpenMote-CC2538 are connected as follows: + * - LED1 (Red) -> PC4 (gpio_hal_pin_t 20) + * - LED2 (Yellow) -> PC6 (gpio_hal_pin_t 22) + * - LED3 (Green) -> PC7 (gpio_hal_pin_t 23) + * - LED4 (Orange) -> PC5 + */ +gpio_hal_pin_t out_pin1 = 20; +gpio_hal_pin_t out_pin2 = 22; +gpio_hal_pin_t out_pin3 = 23; +/*---------------------------------------------------------------------------*/ +/* Button pin: PC3 */ +gpio_hal_pin_t btn_pin = 19; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/srf06-cc26xx/pins.c b/examples/dev/gpio-hal/srf06-cc26xx/pins.c new file mode 100644 index 000000000..700f8961b --- /dev/null +++ b/examples/dev/gpio-hal/srf06-cc26xx/pins.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +#if CONTIKI_BOARD_SENSORTAG_CC1350 +#define PINS2_AND_3 BOARD_IOID_LED_1 +#else +#define PINS2_AND_3 BOARD_IOID_LED_2 +#endif +gpio_hal_pin_t out_pin1 = BOARD_IOID_LED_1; +gpio_hal_pin_t out_pin2 = PINS2_AND_3; +gpio_hal_pin_t out_pin3 = PINS2_AND_3; +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t btn_pin = BOARD_IOID_KEY_LEFT; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/zoul/pins.c b/examples/dev/gpio-hal/zoul/pins.c new file mode 100644 index 000000000..ff44bf4d1 --- /dev/null +++ b/examples/dev/gpio-hal/zoul/pins.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t out_pin1 = (LEDS_ARCH_L1_PORT << 3) + LEDS_ARCH_L1_PIN; +gpio_hal_pin_t out_pin2 = (LEDS_ARCH_L2_PORT << 3) + LEDS_ARCH_L2_PIN; +gpio_hal_pin_t out_pin3 = (LEDS_ARCH_L3_PORT << 3) + LEDS_ARCH_L3_PIN; +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t btn_pin = (BUTTON_USER_PORT << 3) + BUTTON_USER_PIN; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/leds/Makefile b/examples/dev/leds/Makefile new file mode 100644 index 000000000..7c5f5f592 --- /dev/null +++ b/examples/dev/leds/Makefile @@ -0,0 +1,8 @@ +CONTIKI_PROJECT = leds-example +CONTIKI = ../../.. + +MODULES_REL += $(TARGET) + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/dev/leds/README.md b/examples/dev/leds/README.md new file mode 100644 index 000000000..05bdc20ba --- /dev/null +++ b/examples/dev/leds/README.md @@ -0,0 +1,15 @@ +# LED HAL Example +This example demonstrates and tests the functionality of the LED HAL. You can +use it to: + +* Understand the logic of the LED HAL. +* Test your implementation of arch-specific LED HAL components if you are +developing a new port. + +This example assumes a device with at least 1 LED. + +# Supported devices +This example is expected to work off-the-shelf on the following boards: + +* All CC13xx/CC26xx devices +* All CC2538 devices diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h b/examples/dev/leds/leds-example.c similarity index 62% rename from arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h rename to examples/dev/leds/leds-example.c index 1a993d3be..b62668e8b 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h +++ b/examples/dev/leds/leds-example.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * 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 @@ -28,44 +29,56 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup cc26xx - * @{ - * - * \defgroup cc26xx-gpio-interrupts CC13xx/CC26xx GPIO interrupt handling - * - * The CC13xx/CC26xx GPIO interrupt handler and an API which can be used by - * other parts of the code when they wish to be notified of a GPIO interrupt - * - * @{ - * - * \file - * Header file for the CC13xx/CC26xx GPIO interrupt management - */ -/*---------------------------------------------------------------------------*/ -#ifndef GPIO_INTERRUPT_H_ -#define GPIO_INTERRUPT_H_ -/*---------------------------------------------------------------------------*/ -#include -/*---------------------------------------------------------------------------*/ -typedef void (*gpio_interrupt_handler_t)(uint8_t ioid); -/*---------------------------------------------------------------------------*/ -/** \brief Initialise the GPIO interrupt handling module */ -void gpio_interrupt_init(void); +#include "contiki.h" +#include "dev/leds.h" +#include "sys/etimer.h" -/** - * \brief Register a GPIO interrupt handler - * \param f Pointer to a handler to be called when an interrupt is raised on - * ioid - * \param ioid Associate \a f with this ioid. \e ioid must be specified with - * its numeric representation (0, 1, .. 31). Defines for these - * numeric representations are IOID_x - */ -void gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f); - -#endif /* GPIO_INTERRUPT_H_ */ +#include +/*---------------------------------------------------------------------------*/ +static struct etimer et; +static uint8_t counter; +/*---------------------------------------------------------------------------*/ +PROCESS(leds_example, "LED HAL Example"); +AUTOSTART_PROCESSES(&leds_example); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(leds_example, ev, data) +{ + PROCESS_BEGIN(); + + counter = 0; + + etimer_set(&et, CLOCK_SECOND); + + while(1) { + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER && data == &et) { + if((counter & 7) == 0) { + leds_set(LEDS_ALL); + } else if((counter & 7) == 1) { + leds_off(LEDS_ALL); + } else if((counter & 7) == 2) { + leds_on(LEDS_ALL); + } else if((counter & 7) == 3) { + leds_toggle(LEDS_ALL); +#if !LEDS_LEGACY_API + } else if((counter & 7) == 4) { + leds_single_on(LEDS_LED1); + } else if((counter & 7) == 5) { + leds_single_off(LEDS_LED1); + } else if((counter & 7) == 6) { + leds_single_toggle(LEDS_LED1); +#endif /* LEDS_LEGACY_API */ + } else if((counter & 7) == 7) { + leds_toggle(LEDS_ALL); + } + + counter++; + etimer_set(&et, CLOCK_SECOND); + } + } + + PROCESS_END(); +} /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/examples/dev/rgb-led/Makefile b/examples/dev/rgb-led/Makefile new file mode 100644 index 000000000..0b3f4b229 --- /dev/null +++ b/examples/dev/rgb-led/Makefile @@ -0,0 +1,8 @@ +CONTIKI_PROJECT = rgb-led-example +CONTIKI = ../../.. + +MODULES_REL += $(TARGET) + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/dev/rgb-led/Makefile.target b/examples/dev/rgb-led/Makefile.target new file mode 100644 index 000000000..75430a6e4 --- /dev/null +++ b/examples/dev/rgb-led/Makefile.target @@ -0,0 +1 @@ +TARGET = zoul diff --git a/examples/dev/rgb-led/README.md b/examples/dev/rgb-led/README.md new file mode 100644 index 000000000..1b10926ce --- /dev/null +++ b/examples/dev/rgb-led/README.md @@ -0,0 +1,14 @@ +# RGB LED Example +This example demonstrates and tests the functionality of the RGB LED driver. +You can use it to: + +* Understand the logic of the RGB LED driver. +* Test your implementation if you are developing a new port for a device that +features this part. + +This example assumes a device with an RGB LED. + +# Supported devices +This example is expected to work off-the-shelf on the following boards: + +* All Zoul-based devices diff --git a/examples/dev/rgb-led/rgb-led-example.c b/examples/dev/rgb-led/rgb-led-example.c new file mode 100644 index 000000000..e2c2de21e --- /dev/null +++ b/examples/dev/rgb-led/rgb-led-example.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/rgb-led/rgb-led.h" +#include "sys/etimer.h" + +#include +/*---------------------------------------------------------------------------*/ +static struct etimer et; +static uint8_t counter; +/*---------------------------------------------------------------------------*/ +PROCESS(rgb_led_example, "RGB LED Example"); +AUTOSTART_PROCESSES(&rgb_led_example); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(rgb_led_example, ev, data) +{ + PROCESS_BEGIN(); + + counter = 0; + + etimer_set(&et, CLOCK_SECOND); + + while(1) { + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER && data == &et) { + if((counter & 7) == 0) { + rgb_led_off(); + } else if((counter & 7) == 1) { + rgb_led_set(RGB_LED_RED); + } else if((counter & 7) == 2) { + rgb_led_set(RGB_LED_GREEN); + } else if((counter & 7) == 3) { + rgb_led_set(RGB_LED_BLUE); + } else if((counter & 7) == 4) { + rgb_led_set(RGB_LED_CYAN); + } else if((counter & 7) == 5) { + rgb_led_set(RGB_LED_MAGENTA); + } else if((counter & 7) == 6) { + rgb_led_set(RGB_LED_YELLOW); + } else if((counter & 7) == 7) { + rgb_led_set(RGB_LED_WHITE); + } + + counter++; + etimer_set(&et, CLOCK_SECOND); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ip64-router/ip64-router.c b/examples/ip64-router/ip64-router.c index a6a5af450..632b9ba2e 100644 --- a/examples/ip64-router/ip64-router.c +++ b/examples/ip64-router/ip64-router.c @@ -2,7 +2,7 @@ #include "contiki-net.h" #include "ip64/ip64.h" #include "net/netstack.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include "sys/autostart.h" /*---------------------------------------------------------------------------*/ @@ -14,7 +14,7 @@ PROCESS_THREAD(router_node_process, ev, data) PROCESS_BEGIN(); /* Set us up as a RPL root node. */ - rpl_dag_root_init_dag_delay(); + NETSTACK_ROUTING.root_start(); /* Initialize the IP64 module so we'll start translating packets */ ip64_init(); diff --git a/examples/ipso-objects/example-ipso-objects.c b/examples/ipso-objects/example-ipso-objects.c index 180369076..013c62205 100644 --- a/examples/ipso-objects/example-ipso-objects.c +++ b/examples/ipso-objects/example-ipso-objects.c @@ -37,8 +37,16 @@ */ #include "contiki.h" +#include "dev/leds.h" #include "services/lwm2m/lwm2m-engine.h" +#include "services/lwm2m/lwm2m-rd-client.h" +#include "services/lwm2m/lwm2m-device.h" +#include "services/lwm2m/lwm2m-server.h" +#include "services/lwm2m/lwm2m-security.h" #include "services/ipso-objects/ipso-objects.h" +#include "services/ipso-objects/ipso-sensor-template.h" +#include "services/ipso-objects/ipso-control-template.h" +#include "dev/leds.h" #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" @@ -52,9 +60,84 @@ #endif #ifndef LWM2M_SERVER_ADDRESS -#define LWM2M_SERVER_ADDRESS "fd00::1" +#define LWM2M_SERVER_ADDRESS "coap://[fd00::1]" #endif +#if BOARD_SENSORTAG +#include "board-peripherals.h" + +/* Temperature reading */ +static lwm2m_status_t +read_temp_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); + return LWM2M_STATUS_OK; +} +/* Humitidy reading */ +static lwm2m_status_t +read_hum_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); + return LWM2M_STATUS_OK; +} +/* Lux reading */ +static lwm2m_status_t +read_lux_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * opt_3001_sensor.value(0); + return LWM2M_STATUS_OK; +} +/* Barometer reading */ +static lwm2m_status_t +read_bar_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS); + return LWM2M_STATUS_OK; +} +/* LED control */ +static lwm2m_status_t +leds_set_val(ipso_control_t *control, uint8_t value) +{ + if(value > 0) { + leds_single_on(LEDS_LED1); + } else { + leds_single_off(LEDS_LED1); + } + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ + +IPSO_CONTROL(led_control, 3311, 0, leds_set_val); + +IPSO_SENSOR(temp_sensor, 3303, read_temp_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .unit = "Cel", + .update_interval = 30 + ); + +IPSO_SENSOR(hum_sensor, 3304, read_hum_value, + .max_range = 100000, /* 100 % RH */ + .min_range = 0, + .unit = "% RH", + .update_interval = 30 + ); + +IPSO_SENSOR(lux_sensor, 3301, read_lux_value, + .max_range = 100000, + .min_range = -10000, + .unit = "LUX", + .update_interval = 30 + ); + +IPSO_SENSOR(bar_sensor, 3315, read_bar_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .unit = "hPa", + .update_interval = 30 + ); +#endif /* BOARD_SENSORTAG */ + PROCESS(example_ipso_objects, "IPSO object example"); AUTOSTART_PROCESSES(&example_ipso_objects); /*---------------------------------------------------------------------------*/ @@ -62,39 +145,70 @@ static void setup_lwm2m_servers(void) { #ifdef LWM2M_SERVER_ADDRESS - uip_ipaddr_t addr; - if(uiplib_ipaddrconv(LWM2M_SERVER_ADDRESS, &addr)) { - lwm2m_engine_register_with_bootstrap_server(&addr, 0); - lwm2m_engine_register_with_server(&addr, 0); + coap_endpoint_t server_ep; + if(coap_endpoint_parse(LWM2M_SERVER_ADDRESS, strlen(LWM2M_SERVER_ADDRESS), + &server_ep) != 0) { + lwm2m_rd_client_register_with_bootstrap_server(&server_ep); + lwm2m_rd_client_register_with_server(&server_ep); } #endif /* LWM2M_SERVER_ADDRESS */ - lwm2m_engine_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER); - lwm2m_engine_use_registration_server(REGISTER_WITH_LWM2M_SERVER); + lwm2m_rd_client_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER); + lwm2m_rd_client_use_registration_server(REGISTER_WITH_LWM2M_SERVER); } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(example_ipso_objects, ev, data) { + static struct etimer periodic; PROCESS_BEGIN(); PROCESS_PAUSE(); - PRINTF("Starting IPSO objects example\n"); - + PRINTF("Starting IPSO objects example%s\n", + REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER ? " (bootstrap)" : ""); /* Initialize the OMA LWM2M engine */ lwm2m_engine_init(); /* Register default LWM2M objects */ - lwm2m_engine_register_default_objects(); + lwm2m_device_init(); + lwm2m_security_init(); + lwm2m_server_init(); - /* Register default IPSO objects */ +#if BOARD_SENSORTAG + ipso_sensor_add(&temp_sensor); + ipso_sensor_add(&hum_sensor); + ipso_sensor_add(&lux_sensor); + ipso_sensor_add(&bar_sensor); + ipso_control_add(&led_control); + ipso_button_init(); + + SENSORS_ACTIVATE(hdc_1000_sensor); + SENSORS_ACTIVATE(opt_3001_sensor); + SENSORS_ACTIVATE(bmp_280_sensor); +#else /* BOARD_SENSORTAG */ + /* Register default IPSO objects - such as button..*/ ipso_objects_init(); +#endif /* BOARD_SENSORTAG */ setup_lwm2m_servers(); + /* Tick loop each 5 seconds */ + etimer_set(&periodic, CLOCK_SECOND * 5); while(1) { PROCESS_WAIT_EVENT(); - } + if(ev == PROCESS_EVENT_TIMER && etimer_expired(&periodic)) { +#if BOARD_SENSORTAG + /* deactive / activate to do a new reading */ + SENSORS_DEACTIVATE(hdc_1000_sensor); + SENSORS_DEACTIVATE(opt_3001_sensor); + SENSORS_DEACTIVATE(bmp_280_sensor); + SENSORS_ACTIVATE(hdc_1000_sensor); + SENSORS_ACTIVATE(opt_3001_sensor); + SENSORS_ACTIVATE(bmp_280_sensor); +#endif /* BOARD_SENSORTAG */ + etimer_reset(&periodic); + } + } PROCESS_END(); } diff --git a/examples/ipso-objects/example-server.c b/examples/ipso-objects/example-server.c index acec7ee25..4eac38f69 100644 --- a/examples/ipso-objects/example-server.c +++ b/examples/ipso-objects/example-server.c @@ -38,13 +38,12 @@ #include "contiki.h" #include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "net/netstack.h" +#include "net/routing/routing.h" #include "coap-constants.h" #include "coap-engine.h" #include "lwm2m-engine.h" -#include "oma-tlv.h" +#include "lwm2m-tlv.h" #include "dev/serial-line.h" #include "serial-protocol.h" @@ -187,13 +186,13 @@ client_chunk_handler(void *response) } else { /* otherwise update the current value */ if(format == LWM2M_TLV) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; /* we can only read int32 for now ? */ - if(oma_tlv_read(&tlv, chunk, len) > 0) { + if(lwm2m_tlv_read(&tlv, chunk, len) > 0) { /* printf("TLV.type=%d len=%d id=%d value[0]=%d\n", */ /* tlv.type, tlv.length, tlv.id, tlv.value[0]); */ - int value = oma_tlv_get_int32(&tlv); + int value = lwm2m_tlv_get_int32(&tlv); snprintf(current_value, sizeof(current_value), "%d", value); } } else { @@ -237,8 +236,8 @@ setup_network(void) uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); #endif - rpl_dag_root_init(&ipaddr, &ipaddr); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_set_prefix(&ipaddr, &ipaddr); + NETSTACK_ROUTING.root_start(); #endif /* UIP_CONF_ROUTER */ PRINTF("IPv6 addresses: "); @@ -257,8 +256,8 @@ setup_network(void) /*---------------------------------------------------------------------------*/ PROCESS_THREAD(router_process, ev, data) { - /* This way the packet can be treated as pointer as usual. */ - static coap_packet_t request[1]; + /* This way the message can be treated as pointer as usual. */ + static coap_message_t request[1]; static struct etimer timer; uip_ds6_route_t *r; uip_ipaddr_t *nexthop; @@ -269,7 +268,7 @@ PROCESS_THREAD(router_process, ev, data) PROCESS_PAUSE(); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); setup_network(); diff --git a/examples/ipso-objects/project-conf.h b/examples/ipso-objects/project-conf.h index 075cd7444..a7ad8b3ea 100644 --- a/examples/ipso-objects/project-conf.h +++ b/examples/ipso-objects/project-conf.h @@ -30,6 +30,9 @@ #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) @@ -40,10 +43,14 @@ #define PLATFORM_REBOOT watchdog_reboot #endif +#if BOARD_SENSORTAG +/* Real sensor is present... */ +#else #define IPSO_TEMPERATURE example_ipso_temperature +#endif /* BOARD_SENSORTAG */ /* Increase rpl-border-router IP-buffer when using more than 64. */ -#define REST_MAX_CHUNK_SIZE 64 +#define COAP_MAX_CHUNK_SIZE 64 /* Multiplies with chunk size, be aware of memory constraints. */ #define COAP_MAX_OPEN_TRANSACTIONS 4 diff --git a/examples/ipv6-hooks/ipv6-hooks.c b/examples/ipv6-hooks/ipv6-hooks.c index 30269b030..d3ca8861c 100644 --- a/examples/ipv6-hooks/ipv6-hooks.c +++ b/examples/ipv6-hooks/ipv6-hooks.c @@ -1,9 +1,10 @@ #include "contiki.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "random.h" #include "net/netstack.h" #include "net/ipv6/simple-udp.h" #include "net/ipv6/uipbuf.h" +#include "net/ipv6/uip-ds6.h" #include "sys/log.h" #define LOG_MODULE "App" diff --git a/examples/libs/logging/project-conf.h b/examples/libs/logging/project-conf.h index f42f08723..8f393c319 100644 --- a/examples/libs/logging/project-conf.h +++ b/examples/libs/logging/project-conf.h @@ -45,6 +45,8 @@ #define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_DBG #define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG #define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG +#define LOG_CONF_LEVEL_COAP LOG_LEVEL_DBG +#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_DBG #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_DBG /* Enable cooja annotations */ diff --git a/examples/libs/trickle-library/trickle-library.c b/examples/libs/trickle-library/trickle-library.c index 30e02caf0..c449aade9 100644 --- a/examples/libs/trickle-library/trickle-library.c +++ b/examples/libs/trickle-library/trickle-library.c @@ -36,7 +36,6 @@ #include "contiki-net.h" #include "lib/trickle-timer.h" -#include "dev/leds.h" #include "lib/random.h" #include @@ -80,7 +79,6 @@ AUTOSTART_PROCESSES(&trickle_protocol_process); static void tcpip_handler(void) { - leds_on(LEDS_GREEN); if(uip_newdata()) { PRINTF("At %lu (I=%lu, c=%u): ", (unsigned long)clock_time(), (unsigned long)tt.i_cur, tt.c); @@ -109,7 +107,6 @@ tcpip_handler(void) tt.ct.etimer.timer.interval)); } } - leds_off(LEDS_GREEN); return; } /*---------------------------------------------------------------------------*/ @@ -126,8 +123,6 @@ trickle_tx(void *ptr, uint8_t suppress) return; } - leds_on(LEDS_RED); - PRINTF("At %lu (I=%lu, c=%u): ", (unsigned long)clock_time(), (unsigned long)loc_tt->i_cur, loc_tt->c); @@ -144,8 +139,6 @@ trickle_tx(void *ptr, uint8_t suppress) /* Restore to 'accept incoming from any IP' */ uip_create_unspecified(&trickle_conn->ripaddr); - - leds_off(LEDS_RED); } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(trickle_protocol_process, ev, data) diff --git a/examples/libs/trickle-library/trickle-library.csc b/examples/libs/trickle-library/trickle-library.csc index bea3f6c3e..a450f15e8 100644 --- a/examples/libs/trickle-library/trickle-library.csc +++ b/examples/libs/trickle-library/trickle-library.csc @@ -4,7 +4,6 @@ [CONTIKI_DIR]/tools/cooja/apps/mspsim [CONTIKI_DIR]/tools/cooja/apps/avrora [CONTIKI_DIR]/tools/cooja/apps/serial_socket - [CONTIKI_DIR]/tools/cooja/apps/collect-view [CONTIKI_DIR]/tools/cooja/apps/powertracker Example Demonstrating the Trickle Library's Functionality diff --git a/examples/multicast/multicast.csc b/examples/multicast/multicast.csc index e88913825..d59708d54 100644 --- a/examples/multicast/multicast.csc +++ b/examples/multicast/multicast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Example of a uIPv6 network with multicast support diff --git a/examples/multicast/root.c b/examples/multicast/root.c index b4bf9dcdb..f997e9613 100644 --- a/examples/multicast/root.c +++ b/examples/multicast/root.c @@ -48,8 +48,7 @@ #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #define MAX_PAYLOAD_LEN 120 #define MCAST_SINK_UDP_PORT 3001 /* Host byte order */ @@ -84,7 +83,7 @@ multicast_send(void) PRINTF("Send to: "); PRINT6ADDR(&mcast_conn->ripaddr); PRINTF(" Remote Port %u,", uip_ntohs(mcast_conn->rport)); - PRINTF(" (msg=0x%08lx)", (unsigned long)uip_ntohl(*((uint32_t *)buf))); + PRINTF(" (msg=0x%08"PRIx32")", uip_ntohl(*((uint32_t *)buf))); PRINTF(" %lu bytes\n", (unsigned long)sizeof(id)); seq_id++; @@ -112,7 +111,7 @@ PROCESS_THREAD(rpl_root_process, ev, data) PRINTF("Multicast Engine: '%s'\n", UIP_MCAST6.name); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); prepare_mcast(); diff --git a/examples/multicast/sink.c b/examples/multicast/sink.c index e15d0f695..34ad6009d 100644 --- a/examples/multicast/sink.c +++ b/examples/multicast/sink.c @@ -71,7 +71,7 @@ tcpip_handler(void) if(uip_newdata()) { count++; PRINTF("In: [0x%08lx], TTL %u, total %u\n", - uip_ntohl((unsigned long) *((uint32_t *)(uip_appdata))), + (unsigned long)uip_ntohl((unsigned long) *((uint32_t *)(uip_appdata))), UIP_IP_BUF->ttl, count); } return; diff --git a/examples/nullnet/nullnet-broadcast.c b/examples/nullnet/nullnet-broadcast.c index d654784eb..7bb1f1c87 100644 --- a/examples/nullnet/nullnet-broadcast.c +++ b/examples/nullnet/nullnet-broadcast.c @@ -65,9 +65,13 @@ AUTOSTART_PROCESSES(&nullnet_example_process); void input_callback(const void *data, uint16_t len, const linkaddr_t *src, const linkaddr_t *dest) { - LOG_INFO("Received %u from ", *(unsigned *)data); - LOG_INFO_LLADDR(src); - LOG_INFO_("\n"); + if(len == sizeof(unsigned)) { + unsigned count; + memcpy(&count, data, sizeof(count)); + LOG_INFO("Received %u from ", count); + LOG_INFO_LLADDR(src); + LOG_INFO_("\n"); + } } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(nullnet_example_process, ev, data) diff --git a/examples/nullnet/nullnet-broadcast.csc b/examples/nullnet/nullnet-broadcast.csc index 0542bfc97..616845525 100644 --- a/examples/nullnet/nullnet-broadcast.csc +++ b/examples/nullnet/nullnet-broadcast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/examples/nullnet/nullnet-unicast.c b/examples/nullnet/nullnet-unicast.c index 98866f381..5dd9d9fcd 100644 --- a/examples/nullnet/nullnet-unicast.c +++ b/examples/nullnet/nullnet-unicast.c @@ -67,9 +67,13 @@ AUTOSTART_PROCESSES(&nullnet_example_process); void input_callback(const void *data, uint16_t len, const linkaddr_t *src, const linkaddr_t *dest) { - LOG_INFO("Received %u from ", *(unsigned *)data); - LOG_INFO_LLADDR(src); - LOG_INFO_("\n"); + if(len == sizeof(unsigned)) { + unsigned count; + memcpy(&count, data, sizeof(count)); + LOG_INFO("Received %u from ", count); + LOG_INFO_LLADDR(src); + LOG_INFO_("\n"); + } } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(nullnet_example_process, ev, data) diff --git a/examples/nullnet/nullnet-unicast.csc b/examples/nullnet/nullnet-unicast.csc index d756d9892..56e860d82 100644 --- a/examples/nullnet/nullnet-unicast.csc +++ b/examples/nullnet/nullnet-unicast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c b/examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c index 18b806ac9..b818b88ca 100644 --- a/examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c +++ b/examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c @@ -42,11 +42,8 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "mqtt.h" -#include "rpl.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-icmp6.h" #include "net/ipv6/sicslowpan.h" @@ -58,6 +55,7 @@ #include "dev/cc2538-sensors.h" #include +#include /*---------------------------------------------------------------------------*/ /* * IBM server: messaging.quickstart.internetofthings.ibmcloud.com diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c index e14991d04..ebbe66c29 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c @@ -39,7 +39,7 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "board-peripherals.h" #include "lib/sensors.h" #include "lib/list.h" @@ -55,6 +55,7 @@ #include #include #include +#include #include "ti-lib.h" /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c index e12f2cd16..d3042bf81 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c @@ -35,8 +35,13 @@ #include "contiki.h" #include "contiki-lib.h" #include "contiki-net.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "net/ipv6/uip.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif #include #include diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c index 8897eb23f..54289f102 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c @@ -37,7 +37,7 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "board-peripherals.h" #include "rf-core/rf-ble.h" #include "cc26xx-web-demo.h" @@ -47,48 +47,48 @@ #include /*---------------------------------------------------------------------------*/ /* Common resources */ -extern resource_t res_leds; +extern coap_resource_t res_leds; -extern resource_t res_batmon_temp; -extern resource_t res_batmon_volt; +extern coap_resource_t res_batmon_temp; +extern coap_resource_t res_batmon_volt; -extern resource_t res_device_sw; -extern resource_t res_device_hw; -extern resource_t res_device_uptime; -extern resource_t res_device_cfg_reset; +extern coap_resource_t res_device_sw; +extern coap_resource_t res_device_hw; +extern coap_resource_t res_device_uptime; +extern coap_resource_t res_device_cfg_reset; -extern resource_t res_parent_rssi; -extern resource_t res_parent_ip; +extern coap_resource_t res_parent_rssi; +extern coap_resource_t res_parent_ip; #if RF_BLE_ENABLED -extern resource_t res_ble_advd; +extern coap_resource_t res_ble_advd; #endif -extern resource_t res_toggle_red; -extern resource_t res_toggle_green; +extern coap_resource_t res_toggle_red; +extern coap_resource_t res_toggle_green; /* Board-specific resources */ #if BOARD_SENSORTAG -extern resource_t res_bmp280_temp; -extern resource_t res_bmp280_press; -extern resource_t res_tmp007_amb; -extern resource_t res_tmp007_obj; -extern resource_t res_hdc1000_temp; -extern resource_t res_hdc1000_hum; -extern resource_t res_opt3001_light; -extern resource_t res_mpu_acc_x; -extern resource_t res_mpu_acc_y; -extern resource_t res_mpu_acc_z; -extern resource_t res_mpu_gyro_x; -extern resource_t res_mpu_gyro_y; -extern resource_t res_mpu_gyro_z; +extern coap_resource_t res_bmp280_temp; +extern coap_resource_t res_bmp280_press; +extern coap_resource_t res_tmp007_amb; +extern coap_resource_t res_tmp007_obj; +extern coap_resource_t res_hdc1000_temp; +extern coap_resource_t res_hdc1000_hum; +extern coap_resource_t res_opt3001_light; +extern coap_resource_t res_mpu_acc_x; +extern coap_resource_t res_mpu_acc_y; +extern coap_resource_t res_mpu_acc_z; +extern coap_resource_t res_mpu_gyro_x; +extern coap_resource_t res_mpu_gyro_y; +extern coap_resource_t res_mpu_gyro_z; #else -extern resource_t res_toggle_orange; -extern resource_t res_toggle_yellow; +extern coap_resource_t res_toggle_orange; +extern coap_resource_t res_toggle_yellow; #endif #if CC26XX_WEB_DEMO_ADC_DEMO -extern resource_t res_adc_dio23; +extern coap_resource_t res_adc_dio23; #endif /*---------------------------------------------------------------------------*/ const char *coap_server_not_found_msg = "Resource not found"; @@ -101,27 +101,27 @@ static void start_board_resources(void) { - rest_activate_resource(&res_toggle_green, "lt/g"); - rest_activate_resource(&res_toggle_red, "lt/r"); - rest_activate_resource(&res_leds, "lt"); + coap_activate_resource(&res_toggle_green, "lt/g"); + coap_activate_resource(&res_toggle_red, "lt/r"); + coap_activate_resource(&res_leds, "lt"); #if BOARD_SENSORTAG - rest_activate_resource(&res_bmp280_temp, "sen/bar/temp"); - rest_activate_resource(&res_bmp280_press, "sen/bar/pres"); - rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); - rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); - rest_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); - rest_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); - rest_activate_resource(&res_opt3001_light, "sen/opt/light"); - rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); - rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); - rest_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z"); - rest_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); - rest_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); - rest_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); + coap_activate_resource(&res_bmp280_temp, "sen/bar/temp"); + coap_activate_resource(&res_bmp280_press, "sen/bar/pres"); + coap_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); + coap_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); + coap_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); + coap_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); + coap_activate_resource(&res_opt3001_light, "sen/opt/light"); + coap_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); + coap_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); + coap_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z"); + coap_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); + coap_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); + coap_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); #elif BOARD_SMARTRF06EB - rest_activate_resource(&res_toggle_yellow, "lt/y"); - rest_activate_resource(&res_toggle_orange, "lt/o"); + coap_activate_resource(&res_toggle_yellow, "lt/y"); + coap_activate_resource(&res_toggle_orange, "lt/o"); #endif } /*---------------------------------------------------------------------------*/ @@ -134,25 +134,25 @@ PROCESS_THREAD(coap_server_process, ev, data) printf("CC26XX CoAP Server\n"); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); - rest_activate_resource(&res_batmon_temp, "sen/batmon/temp"); - rest_activate_resource(&res_batmon_volt, "sen/batmon/voltage"); + coap_activate_resource(&res_batmon_temp, "sen/batmon/temp"); + coap_activate_resource(&res_batmon_volt, "sen/batmon/voltage"); #if CC26XX_WEB_DEMO_ADC_DEMO - rest_activate_resource(&res_adc_dio23, "sen/adc/dio23"); + coap_activate_resource(&res_adc_dio23, "sen/adc/dio23"); #endif - rest_activate_resource(&res_device_hw, "dev/mdl/hw"); - rest_activate_resource(&res_device_sw, "dev/mdl/sw"); - rest_activate_resource(&res_device_uptime, "dev/uptime"); - rest_activate_resource(&res_device_cfg_reset, "dev/cfg_reset"); + coap_activate_resource(&res_device_hw, "dev/mdl/hw"); + coap_activate_resource(&res_device_sw, "dev/mdl/sw"); + coap_activate_resource(&res_device_uptime, "dev/uptime"); + coap_activate_resource(&res_device_cfg_reset, "dev/cfg_reset"); - rest_activate_resource(&res_parent_rssi, "net/parent/RSSI"); - rest_activate_resource(&res_parent_ip, "net/parent/IPv6"); + coap_activate_resource(&res_parent_rssi, "net/parent/RSSI"); + coap_activate_resource(&res_parent_ip, "net/parent/IPv6"); #if RF_BLE_ENABLED - rest_activate_resource(&res_ble_advd, "dev/ble_advd"); + coap_activate_resource(&res_ble_advd, "dev/ble_advd"); #endif start_board_resources(); diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c index 59ecee1ce..7eb4ab5ee 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c @@ -36,11 +36,8 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "mqtt.h" -#include "rpl.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-icmp6.h" #include "sys/etimer.h" diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c index f3dc146c9..ca3bf8c82 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c @@ -71,6 +71,7 @@ #include #include +#include #include #include /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c index 2dccd1b75..a94a0b7a0 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c @@ -36,7 +36,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "rf-core/rf-ble.h" @@ -49,7 +49,8 @@ const char *forbidden_payload = "Name to advertise unspecified.\n" "Use name= in the request"; /*---------------------------------------------------------------------------*/ static void -res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, +res_ble_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; @@ -60,7 +61,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, memset(name, 0, BLE_NAME_BUF_LEN); - len = REST.get_post_variable(request, "name", &text); + len = coap_get_post_variable(request, "name", &text); if(len > 0 && len < BLE_NAME_BUF_LEN) { memcpy(name, text, len); @@ -68,7 +69,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, success = 1; } - len = REST.get_post_variable(request, "interval", &text); + len = coap_get_post_variable(request, "interval", &text); rv = atoi(text); @@ -77,15 +78,15 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, success = 1; } - len = REST.get_post_variable(request, "mode", &text); + len = coap_get_post_variable(request, "mode", &text); if(len) { if(strncmp(text, "on", len) == 0) { if(rf_ble_beacond_start()) { success = 1; } else { - REST.set_response_status(response, REST.status.FORBIDDEN); - REST.set_response_payload(response, forbidden_payload, + coap_set_status_code(response, FORBIDDEN_4_03); + coap_set_payload(response, forbidden_payload, strlen(forbidden_payload)); return; } @@ -98,7 +99,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c index a52557ffe..46344d1ef 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c @@ -37,7 +37,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "sys/clock.h" #include "coap-server.h" @@ -46,6 +46,7 @@ #include "ti-lib.h" #include +#include /*---------------------------------------------------------------------------*/ static uint16_t detect_chip(void) @@ -74,106 +75,110 @@ detect_chip(void) } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hw(void *request, void *response, uint8_t *buffer, +res_get_handler_hw(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; uint16_t chip = detect_chip(); - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s on CC%u", BOARD_STRING, chip); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"HW Ver\":\"%s on CC%u\"}", BOARD_STRING, chip); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", BOARD_STRING, chip); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_sw(void *request, void *response, uint8_t *buffer, +res_get_handler_sw(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"SW Ver\":\"%s\"}", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_uptime(void *request, void *response, uint8_t *buffer, +res_get_handler_uptime(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%lu", clock_seconds()); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"uptime\":%lu}", clock_seconds()); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "", clock_seconds()); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_post_handler_cfg_reset(void *request, void *response, uint8_t *buffer, +res_post_handler_cfg_reset(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { cc26xx_web_demo_restore_defaults(); diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c index 85ce353b5..6c396145c 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c @@ -40,13 +40,14 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #include /*---------------------------------------------------------------------------*/ static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, +res_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; @@ -55,7 +56,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint8_t led = 0; int success = 1; - if((len = REST.get_query_variable(request, "color", &color))) { + if((len = coap_get_query_variable(request, "color", &color))) { if(strncmp(color, "r", len) == 0) { led = LEDS_RED; } else if(strncmp(color, "g", len) == 0) { @@ -73,7 +74,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, success = 0; } - if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + if(success && (len = coap_get_post_variable(request, "mode", &mode))) { if(strncmp(mode, "on", len) == 0) { leds_on(led); } else if(strncmp(mode, "off", len) == 0) { @@ -86,7 +87,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c index 86346a999..81575f345 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c @@ -37,82 +37,86 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" +#include "net/ipv6/uip-ds6.h" #include "coap-server.h" #include "cc26xx-web-demo.h" #include "ti-lib.h" #include +#include /*---------------------------------------------------------------------------*/ extern int def_rt_rssi; /*---------------------------------------------------------------------------*/ static void -res_get_handler_parent_rssi(void *request, void *response, uint8_t *buffer, +res_get_handler_parent_rssi(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", def_rt_rssi); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", def_rt_rssi); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}", + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}", def_rt_rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", def_rt_rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_pref_parent(void *request, void *response, uint8_t *buffer, +res_get_handler_pref_parent(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; char def_rt_str[64]; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); memset(def_rt_str, 0, sizeof(def_rt_str)); cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose()); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", def_rt_str); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%s", def_rt_str); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}", + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}", def_rt_str); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "", def_rt_str); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c index b5fe9adb9..9ccc79e97 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c @@ -37,7 +37,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "cc26xx-web-demo.h" #include "coap-server.h" @@ -51,7 +51,8 @@ * called by all handlers and populates the CoAP response */ static void -res_get_handler_all(int sens_type, void *request, void *response, +res_get_handler_all(int sens_type, coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; @@ -60,43 +61,44 @@ res_get_handler_all(int sens_type, void *request, void *response, reading = cc26xx_web_demo_sensor_lookup(sens_type); if(reading == NULL) { - REST.set_response_status(response, REST.status.NOT_FOUND); - REST.set_response_payload(response, coap_server_not_found_msg, + coap_set_status_code(response, NOT_FOUND_4_04); + coap_set_payload(response, coap_server_not_found_msg, strlen(coap_server_not_found_msg)); return; } - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", reading->converted); - REST.set_response_payload(response, (uint8_t *)buffer, + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"%s\":%s}", reading->descr, reading->converted); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<%s val=\"%s\" unit=\"%s\"/>", reading->xml_element, reading->converted, reading->units); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ /* BatMon resources and handler: Temperature, Voltage */ static void -res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_batmon_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP, request, response, @@ -104,7 +106,8 @@ res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_batmon_volt(void *request, void *response, uint8_t *buffer, +res_get_handler_batmon_volt(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT, request, response, @@ -120,7 +123,8 @@ RESOURCE(res_batmon_volt, "title=\"Battery Voltage\";rt=\"mV\"", #if CC26XX_WEB_DEMO_ADC_DEMO /*---------------------------------------------------------------------------*/ static void -res_get_handler_adc_dio23(void *request, void *response, uint8_t *buffer, +res_get_handler_adc_dio23(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_ADC_DIO23, request, response, @@ -136,7 +140,8 @@ RESOURCE(res_adc_dio23, "title=\"ADC DIO23\";rt=\"mV\"", /*---------------------------------------------------------------------------*/ /* MPU resources and handler: Accelerometer and Gyro */ static void -res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_x(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X, request, response, @@ -144,7 +149,8 @@ res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_y(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y, request, response, @@ -152,7 +158,8 @@ res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_z(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z, request, response, @@ -160,7 +167,8 @@ res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_x(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X, request, response, @@ -168,7 +176,8 @@ res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_y(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y, request, response, @@ -176,7 +185,8 @@ res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_z(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_z(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, request, response, @@ -199,7 +209,8 @@ RESOURCE(res_mpu_gyro_z, "title=\"Gyro Z\";rt=\"deg/sec\"", /*---------------------------------------------------------------------------*/ /* TMP sensor resources and handlers: Object, Ambient */ static void -res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_obj_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT, request, response, @@ -207,7 +218,8 @@ res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_amb_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_amb_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, request, response, @@ -222,7 +234,8 @@ RESOURCE(res_tmp007_amb, "title=\"Temperature (Ambient)\";rt=\"C\"", /*---------------------------------------------------------------------------*/ /* BMP sensor resources: Temperature, Pressure */ static void -res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_bmp_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, request, response, @@ -230,7 +243,8 @@ res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_bmp_press(void *request, void *response, uint8_t *buffer, +res_get_handler_bmp_press(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_PRES, request, response, @@ -246,7 +260,8 @@ RESOURCE(res_bmp280_press, /*---------------------------------------------------------------------------*/ /* HDC1000 sensor resources and handler: Temperature, Pressure */ static void -res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, request, response, @@ -254,7 +269,8 @@ res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hdc_humidity(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_humidity(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, request, response, @@ -269,7 +285,8 @@ RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"", /*---------------------------------------------------------------------------*/ /* Illuminance resources and handler */ static void -res_get_handler_opt(void *request, void *response, uint8_t *buffer, +res_get_handler_opt(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT, request, response, diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c index 2fb424a03..1c708b539 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c @@ -42,20 +42,22 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #include /*---------------------------------------------------------------------------*/ static void -res_post_handler_red(void *request, void *response, uint8_t *buffer, +res_post_handler_red(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); } /*---------------------------------------------------------------------------*/ static void -res_post_handler_green(void *request, void *response, uint8_t *buffer, +res_post_handler_green(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_GREEN); @@ -81,14 +83,16 @@ RESOURCE(res_toggle_green, #if BOARD_SMARTRF06EB /*---------------------------------------------------------------------------*/ static void -res_post_handler_yellow(void *request, void *response, uint8_t *buffer, +res_post_handler_yellow(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_YELLOW); } /*---------------------------------------------------------------------------*/ static void -res_post_handler_orange(void *request, void *response, uint8_t *buffer, +res_post_handler_orange(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_ORANGE); diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c index e56ee93e6..e24aac689 100644 --- a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c +++ b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c @@ -40,11 +40,8 @@ #include "net/netstack.h" #include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-route.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "coap.h" #include "ti-lib.h" @@ -104,38 +101,38 @@ PROCESS(very_sleepy_demo_process, "CC13xx/CC26xx very sleepy process"); AUTOSTART_PROCESSES(&very_sleepy_demo_process); /*---------------------------------------------------------------------------*/ static void -readings_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +readings_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; int temp; int voltage; if(request != NULL) { - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); } temp = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP); voltage = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + if(accept == -1 || accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"temp\":{\"v\":%d,\"u\":\"C\"}," "\"voltage\":{\"v\":%d,\"u\":\"mV\"}}", temp, (voltage * 125) >> 5); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV", + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV", temp, (voltage * 125) >> 5); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, not_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, not_supported_msg, strlen(not_supported_msg)); } } @@ -144,39 +141,39 @@ RESOURCE(readings_resource, "title=\"Sensor Readings\";obs", readings_get_handler, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ static void -conf_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +conf_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; if(request != NULL) { - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); } - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + if(accept == -1 || accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"config\":{\"mode\":%u,\"duration\":%lu,\"interval\":%lu}}", config.mode, config.duration, config.interval); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Mode=%u, Duration=%lusecs, Interval=%lusecs", config.mode, config.duration, config.interval); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, not_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, not_supported_msg, strlen(not_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -conf_post_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +conf_post_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *ptr = NULL; char tmp_buf[16]; @@ -186,7 +183,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, uint8_t post_status = POST_STATUS_NONE; int rv; - rv = REST.get_post_variable(request, "mode", &ptr); + rv = coap_get_post_variable(request, "mode", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -203,7 +200,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, } } - rv = REST.get_post_variable(request, "duration", &ptr); + rv = coap_get_post_variable(request, "duration", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -217,7 +214,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, } } - rv = REST.get_post_variable(request, "interval", &ptr); + rv = coap_get_post_variable(request, "interval", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -232,13 +229,13 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, if((post_status & POST_STATUS_BAD) == POST_STATUS_BAD || post_status == POST_STATUS_NONE) { - REST.set_response_status(response, REST.status.BAD_REQUEST); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_status_code(response, BAD_REQUEST_4_00); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "mode=0|1&duration=[%u,%u]&interval=[%u,%u]", NORMAL_OP_DURATION_MIN, NORMAL_OP_DURATION_MAX, PERIODIC_INTERVAL_MIN, PERIODIC_INTERVAL_MAX); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); return; } @@ -345,11 +342,11 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) event_new_config = process_alloc_event(); - rest_init_engine(); + coap_engine_init(); readings_resource.flags += IS_OBSERVABLE; - rest_activate_resource(&readings_resource, "sen/readings"); - rest_activate_resource(&very_sleepy_conf, "very_sleepy_config"); + coap_activate_resource(&readings_resource, "sen/readings"); + coap_activate_resource(&very_sleepy_conf, "very_sleepy_config"); printf("Very Sleepy Demo Process\n"); @@ -390,7 +387,7 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) * send notifications to observers as required. */ if(state == STATE_NOTIFY_OBSERVERS) { - REST.notify_subscribers(&readings_resource); + coap_notify_observers(&readings_resource); state = STATE_NORMAL; } diff --git a/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile index 1b39fbae3..538bacf91 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile +++ b/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile @@ -8,7 +8,7 @@ CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/lib/json -MODULES_REL += .. ../tools +MODULES_REL += .. MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c index 1e3ab0842..2fb2d7761 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c @@ -34,16 +34,16 @@ #include "contiki.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "sys/ctimer.h" #include #include "dev/leds.h" static void ct_callback(void *ptr); -static void put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; static struct ctimer ct; @@ -77,7 +77,7 @@ RESOURCE(resource_led_toggle, put_post_led_toggle_handler, NULL); static void -put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { static int led_state = 0; unsigned int accept = -1; @@ -110,10 +110,10 @@ put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint break; } /* Return message */ - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*---------------------------------------------------------------------------*/ @@ -130,15 +130,13 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } printf("Starting RPL node\n"); + NETSTACK_ROUTING.root_start(); + } + NETSTACK_MAC.on(); + printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_led_toggle, "Dongle/LED-toggle"); + coap_engine_init(); + coap_activate_resource(&resource_led_toggle, "Dongle/LED-toggle"); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile index 79a7e7f13..6fb119351 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile +++ b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile @@ -8,7 +8,7 @@ CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/lib/json -MODULES_REL += .. ../tools +MODULES_REL += .. MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c index 2cd40c283..443cf4fbe 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c @@ -35,8 +35,8 @@ #include "contiki.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "light-sensor.h" #include "ht-sensor.h" #include "dev/leds.h" @@ -46,19 +46,19 @@ #include static void event_sensors_dr1175_handler(void); -static void get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } } @@ -90,26 +90,26 @@ EVENT_RESOURCE(resource_sensors_dr1175, /* name */ NULL, /* DELETE handler */ event_sensors_dr1175_handler); /* event handler */ static void -get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == APPLICATION_JSON) { content_len = 0; CONTENT_PRINTF("{\"DR1175\":["); CONTENT_PRINTF("{\"Humidity\":\"%d\"},", ht_sensor.value(HT_SENSOR_HUM)); CONTENT_PRINTF("{\"Light\":\"%d\"},", light_sensor.value(0)); CONTENT_PRINTF("{\"Temp\":\"%d\"}", ht_sensor.value(HT_SENSOR_TEMP)); CONTENT_PRINTF("]}"); - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)content, content_len); } } static void event_sensors_dr1175_handler() { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_sensors_dr1175); + coap_notify_observers(&resource_sensors_dr1175); } /*****************************************************/ /* Resource and handler to obtain light sensor value */ @@ -121,15 +121,15 @@ RESOURCE(resource_light_sensor_value, NULL, NULL); static void -get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", light_sensor.value(0)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***************************************************/ @@ -142,15 +142,15 @@ RESOURCE(resource_light_sensor_unit, NULL, NULL); static void -get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("Lux"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***********************************************************/ @@ -163,15 +163,15 @@ RESOURCE(resource_temperature_value, NULL, NULL); static void -get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_TEMP)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*********************************************************/ @@ -184,15 +184,15 @@ RESOURCE(resource_temperature_unit, NULL, NULL); static void -get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("degrees C"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /********************************************************/ @@ -205,15 +205,15 @@ RESOURCE(resource_humidity_value, NULL, NULL); static void -get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_HUM)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /******************************************************/ @@ -226,15 +226,15 @@ RESOURCE(resource_humidity_unit, NULL, NULL); static void -get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("relative %%"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***************************************************/ @@ -247,15 +247,15 @@ RESOURCE(resource_white_led, put_post_white_led_handler, NULL); static void -put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); level = atoi((const char *)request_content); CLIP(level, 255) leds_set_level(level, LEDS_WHITE); @@ -271,7 +271,7 @@ RESOURCE(resource_rgb_led, put_post_rgb_led_handler, NULL); static void -put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; char *pch; @@ -279,9 +279,9 @@ put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_ int index = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); pch = strtok((char *)request_content, " "); while((pch != NULL) && (index != sizeof(RGB) / sizeof(int))) { /* Convert token to int */ @@ -306,13 +306,13 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP0); } } @@ -326,13 +326,13 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP1); } } @@ -350,25 +350,23 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } printf("Starting RPL node\n"); + NETSTACK_ROUTING.root_start(); + } + NETSTACK_MAC.on(); + printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value"); - rest_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit"); - rest_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit"); - rest_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value"); - rest_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit"); - rest_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value"); - rest_activate_resource(&resource_white_led, "DR1175/WhiteLED"); - rest_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue"); - rest_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174"); - rest_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174"); - rest_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors"); + coap_engine_init(); + coap_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value"); + coap_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit"); + coap_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit"); + coap_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value"); + coap_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit"); + coap_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value"); + coap_activate_resource(&resource_white_led, "DR1175/WhiteLED"); + coap_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue"); + coap_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174"); + coap_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174"); + coap_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors"); /* Level of LEDS=0, so no light after start-up */ leds_on(LEDS_WHITE | LEDS_RED | LEDS_GREEN | LEDS_BLUE); diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile index a5887a8ef..bdef1a42a 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile +++ b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile @@ -8,7 +8,7 @@ CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/lib/json -MODULES_REL += .. ../tools +MODULES_REL += .. MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c index 0309538ec..d341170ad 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c @@ -34,31 +34,31 @@ #include "contiki.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "dev/leds.h" #include "button-sensor.h" #include "pot-sensor.h" #include #include -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; static void event_sensors_dr1199_handler(); -static void get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } } @@ -93,25 +93,25 @@ EVENT_RESOURCE(resource_sensors_dr1199, /* name */ NULL, /* DELETE handler */ event_sensors_dr1199_handler); /* event handler */ static void -get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == APPLICATION_JSON) { content_len = 0; CONTENT_PRINTF("{\"DR1199\":["); CONTENT_PRINTF("{\"Switch\":\"0x%X\"},", button_sensor.value(0)); CONTENT_PRINTF("{\"Pot\":\"%d\"}", pot_sensor.value(0)); CONTENT_PRINTF("]}"); - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)content, content_len); } } static void event_sensors_dr1199_handler() { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_sensors_dr1199); + coap_notify_observers(&resource_sensors_dr1199); } /***********************************************/ /* Resource and handler to obtain switch value */ @@ -123,15 +123,15 @@ RESOURCE(resource_switch_sw1, NULL, NULL); static void -get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(1) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw2, @@ -141,15 +141,15 @@ RESOURCE(resource_switch_sw2, NULL, NULL); static void -get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(2) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw3, @@ -159,15 +159,15 @@ RESOURCE(resource_switch_sw3, NULL, NULL); static void -get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(3) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw4, @@ -177,15 +177,15 @@ RESOURCE(resource_switch_sw4, NULL, NULL); static void -get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(4) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_dio8, @@ -195,15 +195,15 @@ RESOURCE(resource_switch_dio8, NULL, NULL); static void -get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(0) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*******************************************************/ @@ -216,15 +216,15 @@ RESOURCE(resource_pot, NULL, NULL); static void -get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { CONTENT_PRINTF("%d", pot_sensor.value(0)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /************************************/ @@ -237,13 +237,13 @@ RESOURCE(resource_led_d1, put_post_led_d1_handler, NULL); static void -put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GREEN) } } @@ -254,13 +254,13 @@ RESOURCE(resource_led_d2, put_post_led_d2_handler, NULL); static void -put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_BLUE) } } @@ -271,13 +271,13 @@ RESOURCE(resource_led_d3, put_post_led_d3_handler, NULL); static void -put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_RED) } } @@ -288,13 +288,13 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP0); } } @@ -305,13 +305,13 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP1); } } @@ -322,13 +322,13 @@ RESOURCE(resource_led_all, put_post_led_all_handler, NULL); static void -put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); if(atoi((const char *)request_content) != 0) { leds_on(LEDS_ALL); } else { @@ -351,27 +351,25 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } printf("Starting RPL node\n"); + NETSTACK_ROUTING.root_start(); + } + NETSTACK_MAC.on(); + printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1"); - rest_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2"); - rest_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3"); - rest_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4"); - rest_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8"); - rest_activate_resource(&resource_pot, "DR1199/Potentiometer"); - rest_activate_resource(&resource_led_d1, "DR1199/LED/D1"); - rest_activate_resource(&resource_led_d2, "DR1199/LED/D2"); - rest_activate_resource(&resource_led_d3, "DR1199/LED/D3"); - rest_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174"); - rest_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174"); - rest_activate_resource(&resource_led_all, "DR1199/LED/All"); - rest_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors"); + coap_engine_init(); + coap_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1"); + coap_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2"); + coap_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3"); + coap_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4"); + coap_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8"); + coap_activate_resource(&resource_pot, "DR1199/Potentiometer"); + coap_activate_resource(&resource_led_d1, "DR1199/LED/D1"); + coap_activate_resource(&resource_led_d2, "DR1199/LED/D2"); + coap_activate_resource(&resource_led_d3, "DR1199/LED/D3"); + coap_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174"); + coap_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174"); + coap_activate_resource(&resource_led_all, "DR1199/LED/All"); + coap_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors"); /* If sensor process generates an event, call event_handler of resource. This will make this resource observable by the client */ while(1) { @@ -382,4 +380,3 @@ PROCESS_THREAD(start_app, ev, data) PROCESS_END(); } - diff --git a/examples/platform-specific/jn516x/rpl/node/Makefile b/examples/platform-specific/jn516x/rpl/node/Makefile index 83cd48869..228287cf8 100644 --- a/examples/platform-specific/jn516x/rpl/node/Makefile +++ b/examples/platform-specific/jn516x/rpl/node/Makefile @@ -6,6 +6,6 @@ TARGET ?= jn516x CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH -MODULES_REL += .. ../tools +MODULES_REL += .. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/jn516x/rpl/node/node.c b/examples/platform-specific/jn516x/rpl/node/node.c index 3c24f36c1..71e015e6d 100644 --- a/examples/platform-specific/jn516x/rpl/node/node.c +++ b/examples/platform-specific/jn516x/rpl/node/node.c @@ -37,8 +37,7 @@ #include "contiki.h" #include "net/ipv6/uip-ds6.h" -#include "rpl.h" -#include "tools/rpl-tools.h" +#include "net/routing/routing.h" #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" @@ -59,7 +58,6 @@ AUTOSTART_PROCESSES(&node_process); /*---------------------------------------------------------------------------*/ PROCESS_THREAD(node_process, ev, data) { - static struct etimer et; PROCESS_BEGIN(); /* 3 possible roles: @@ -73,6 +71,7 @@ PROCESS_THREAD(node_process, ev, data) #if CONFIG_VIA_BUTTON { #define CONFIG_WAIT_TIME 5 + static struct etimer et; SENSORS_ACTIVATE(button_sensor); etimer_set(&et, CLOCK_SECOND * CONFIG_WAIT_TIME); @@ -96,22 +95,10 @@ PROCESS_THREAD(node_process, ev, data) node_role == role_6ln ? "6ln" : "6dr"); is_coordinator = node_role > role_6ln; - if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } - - /* Print out routing tables every minute */ - etimer_set(&et, CLOCK_SECOND * 60); - while(1) { - print_network_status(); - PROCESS_YIELD_UNTIL(etimer_expired(&et)); - etimer_reset(&et); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.c b/examples/platform-specific/jn516x/rpl/tools/rpl-tools.c deleted file mode 100644 index 570be8566..000000000 --- a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2015, SICS Swedish ICT. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \file - * - * \author Simon Duquennoy - */ - -#include "contiki.h" -#include "contiki-net.h" -#include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" -#include -#include - -#define DEBUG DEBUG_PRINT -#include "net/ipv6/uip-debug.h" - -/*---------------------------------------------------------------------------*/ -void -print_network_status(void) -{ - int i; - uint8_t state; - uip_ds6_defrt_t *default_route; - uip_ds6_route_t *route; - - PRINTA("--- Network status ---\n"); - - /* Our IPv6 addresses */ - PRINTA("- Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA("-- "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } - - /* Our default route */ - PRINTA("- Default route:\n"); - default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose()); - if(default_route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&default_route->ipaddr);; - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval); - } else { - PRINTA("-- None\n"); - } - - /* Our routing entries */ - PRINTA("- Routing entries (%u in total):\n", uip_ds6_route_num_routes()); - route = uip_ds6_route_head(); - while(route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&route->ipaddr); - PRINTA(" via "); - uip_debug_ipaddr_print(uip_ds6_route_nexthop(route)); - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); - route = uip_ds6_route_next(route); - } - - PRINTA("----------------------\n"); -} -/*---------------------------------------------------------------------------*/ -static void -print_local_addresses(void) -{ - int i; - uint8_t state; - - PRINTA("Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA(" "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } -} -/*---------------------------------------------------------------------------*/ -void -rpl_tools_init(uip_ipaddr_t *br_prefix) -{ - if(br_prefix) { /* We are root */ - rpl_dag_root_init(br_prefix, NULL); - rpl_dag_root_init_dag_immediately(); - } else { - rpl_dag_root_init(NULL, NULL); - } - - - NETSTACK_MAC.on(); - - print_local_addresses(); -} diff --git a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.h b/examples/platform-specific/jn516x/rpl/tools/rpl-tools.h deleted file mode 100644 index f14ec1d86..000000000 --- a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2015, SICS Swedish ICT. - * 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. - * - */ -/** - - * \author Simon Duquennoy - */ - -void rpl_tools_init(uip_ipaddr_t *br_prefix); -void print_network_status(void); diff --git a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile index 2e7e32585..82685c610 100644 --- a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile +++ b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile @@ -5,7 +5,7 @@ JN516x_WITH_DONGLE = 1 CONTIKI=../../../../../.. -MODULES_REL += .. ../../tools +MODULES_REL += .. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/net/app-layer/coap MODULES += os/services/orchestra os/lib/json 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 0b1bc3414..12350a5f4 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 @@ -37,14 +37,10 @@ #include "net/mac/tsch/tsch-schedule.h" #include "net/mac/tsch/tsch.h" #include "net/mac/tsch/tsch-private.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "net/mac/tsch/tsch-schedule.h" #include "net/ipv6/uip-debug.h" #include "lib/random.h" -#include "rpl-tools.h" #include "node-id.h" #include "waveform.h" #include "leds.h" @@ -173,12 +169,9 @@ PROCESS_THREAD(node_process, ev, data) is_coordinator = node_role > role_6ln; if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xbbbb, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); /* Selected waveform depends on LS byte of MAC */ selected_waveform = node_mac[7] % NUMBER_OF_WAVEFORMS; @@ -214,10 +207,6 @@ PROCESS_THREAD(node_process, ev, data) printf("No host\n"); } etimer_restart(&et); - if (total_time%60 == 0) { - /* Print network status once per minute */ - print_network_status(); - } } } PROCESS_END(); diff --git a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.c b/examples/platform-specific/jn516x/tsch/tools/rpl-tools.c deleted file mode 100644 index e71a19bc9..000000000 --- a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2014, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \file - * - * \author Simon Duquennoy - */ - -#include "contiki.h" -#include "contiki-net.h" -#include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" -#include -#include - -#define DEBUG DEBUG_PRINT -#include "net/ipv6/uip-debug.h" - -void -print_network_status(void) -{ - int i; - uint8_t state; - uip_ds6_defrt_t *default_route; - uip_ds6_route_t *route; - PRINTA("--- Network status ---\n"); - /* Our IPv6 addresses */ - PRINTA("- Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA("-- "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } - /* Our default route */ - PRINTA("- Default route:\n"); - default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose()); - if(default_route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&default_route->ipaddr);; - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval); - } else { - PRINTA("-- None\n"); - } - /* Our routing entries */ - PRINTA("- Routing entries (%u in total):\n", uip_ds6_route_num_routes()); - route = uip_ds6_route_head(); - while(route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&route->ipaddr); - PRINTA(" via "); - uip_debug_ipaddr_print(uip_ds6_route_nexthop(route)); - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); - route = uip_ds6_route_next(route); - } - PRINTA("----------------------\n"); -} -/*---------------------------------------------------------------------------*/ -static void -print_local_addresses(void) -{ - int i; - uint8_t state; - - PRINTA("Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA(" "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } -} -/*---------------------------------------------------------------------------*/ -void -rpl_tools_init(uip_ipaddr_t *br_prefix) -{ - if(br_prefix) { /* We are root */ - rpl_dag_root_init(br_prefix, NULL); - rpl_dag_root_init_dag_immediately(); - } else { - rpl_dag_root_init(NULL, NULL); - } - - /* Start TSCH */ - NETSTACK_MAC.on(); - print_local_addresses(); -} diff --git a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.h b/examples/platform-specific/jn516x/tsch/tools/rpl-tools.h deleted file mode 100644 index b04cdb712..000000000 --- a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2014, Swedish Institute of Computer Science. - * 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. - * - */ -/** - - * \author Simon Duquennoy - */ - -void rpl_tools_init(uip_ipaddr_t *br_prefix); -void print_network_status(void); diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile index 3884b9d30..43a0490ce 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile @@ -5,7 +5,7 @@ JN516x_WITH_DONGLE = 1 CONTIKI=../../../../../.. -MODULES_REL += .. ../../tools +MODULES_REL += .. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c index 115649535..995dc3304 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c @@ -33,19 +33,19 @@ */ #include "contiki.h" #include "net/ipv6/uip-ds6.h" +#include "net/routing/routing.h" #include "net/netstack.h" #include "net/ipv6/uip.h" #include "net/linkaddr.h" -#include "rpl-tools.h" -#include "rest-engine.h" -#include -#include +#include "coap-engine.h" +#include +#include #include -static void set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -56,45 +56,45 @@ AUTOSTART_PROCESSES(&start_app); /*---------------------------------------------------------------------------*/ /*********** sensor/ resource ************************************************/ -RESOURCE(resource_set_tx_power, +RESOURCE(resource_set_tx_power, "title=\"Set TX Power\"", NULL, set_tx_power_handler, set_tx_power_handler, NULL); static void -set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int tx_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); tx_level = atoi((const char *)request_content); NETSTACK_RADIO.set_value(RADIO_PARAM_TXPOWER, tx_level); } } -RESOURCE(resource_get_tx_power, +RESOURCE(resource_get_tx_power, "title=\"Get TX Power\"", get_tx_power_handler, NULL, NULL, NULL); static void -get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int tx_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; NETSTACK_RADIO.get_value(RADIO_PARAM_TXPOWER, &tx_level); CONTENT_PRINTF("%d", tx_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*---------------------------------------------------------------------------*/ @@ -102,20 +102,17 @@ PROCESS_THREAD(start_app, ev, data) { PROCESS_BEGIN(); static int is_coordinator = 0; - + /* Start network stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); printf("Starting RPL node\n"); - - rest_init_engine(); - rest_activate_resource(&resource_set_tx_power, "Set-TX-Power"); - rest_activate_resource(&resource_get_tx_power, "Get-TX-Power"); + + coap_engine_init(); + coap_activate_resource(&resource_set_tx_power, "Set-TX-Power"); + coap_activate_resource(&resource_get_tx_power, "Get-TX-Power"); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile index 3773e04a5..edbc2fe19 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile @@ -7,7 +7,7 @@ CONTIKI=../../../../../.. PROJECT_SOURCEFILES += slip-bridge.c slip.c -MODULES_REL += .. ../../tools +MODULES_REL += .. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c index e15a77989..642e370d1 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c @@ -36,14 +36,13 @@ #include "contiki-net.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "simple-udp.h" #include "net/mac/tsch/tsch.h" #include "net/mac/tsch/tsch-schedule.h" #include "net/netstack.h" #include "dev/slip.h" -#include "rest-engine.h" -#include "rpl-tools.h" +#include "coap-engine.h" #include #include @@ -56,10 +55,10 @@ static uip_ipaddr_t prefix; static uint8_t prefix_set; -static void get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_last_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -67,45 +66,45 @@ static int content_len = 0; PROCESS(border_router_process, "Border router process"); AUTOSTART_PROCESSES(&border_router_process); -RESOURCE(resource_get_rssi, +RESOURCE(resource_get_rssi, "title=\"Get RSSI\"", get_rssi_handler, NULL, NULL, NULL); static void -get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int rssi_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &rssi_level); CONTENT_PRINTF("%d", rssi_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } -RESOURCE(resource_get_last_rssi, +RESOURCE(resource_get_last_rssi, "title=\"Get last RSSI\"", get_last_rssi_handler, NULL, NULL, NULL); static void -get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_last_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int last_rssi_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &last_rssi_level); CONTENT_PRINTF("%d", last_rssi_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } @@ -157,11 +156,12 @@ PROCESS_THREAD(border_router_process, ev, data) uip_debug_ipaddr_print(&prefix); PRINTF("\n"); - rpl_tools_init(&prefix); + NETSTACK_ROUTING.root_set_prefix(&prefix, NULL); + NETSTACK_ROUTING.root_start(); - rest_init_engine(); - rest_activate_resource(&resource_get_rssi, "Get-RSSI"); - rest_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI"); + coap_engine_init(); + coap_activate_resource(&resource_get_rssi, "Get-RSSI"); + coap_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI"); PROCESS_END(); diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile b/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile index 640495432..1dd86cc3d 100644 --- a/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile +++ b/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile @@ -6,7 +6,7 @@ TARGET_WITH_UART1 = 1 CONTIKI=../../../../.. -MODULES_REL += .. ../tools +MODULES_REL += .. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c index 244672d48..dd647fa21 100644 --- a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c +++ b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c @@ -34,24 +34,24 @@ #include "contiki.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip.h" +#include "net/routing/routing.h" #include "net/linkaddr.h" -#include "rpl-tools.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "sys/ctimer.h" #include "dev/uart-driver.h" #include "uart1.h" #include -static void get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void event_coap_rx_uart1_handler(void); -static void put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void string2uart1(uint8_t *c); static int handleRxChar(uint8_t c); static int get_ringbuf(uint8_t *c); static int put_ringbuf(uint8_t c); /* COAP helpers */ -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -64,7 +64,7 @@ static int tail_index = 0; /* index where last read took place */ /* String aligned buffer */ #define RX_BUFFER_SIZE RINGBUF_SIZE -static uint8_t rx_buf[RX_BUFFER_SIZE+1]; +static uint8_t rx_buf[RX_BUFFER_SIZE+1]; static uint8_t rx_buf_index = 0; /* index for rx_buf */ /*---------------------------------------------------------------------------*/ @@ -75,7 +75,7 @@ AUTOSTART_PROCESSES(&start_app, &rx_data_process); /*********** COAP resources *************************************************/ /*****************************************************************************/ -/* Observable resource and event handler to obtain terminal input from UART1 */ +/* Observable resource and event handler to obtain terminal input from UART1 */ /*****************************************************************************/ EVENT_RESOURCE(resource_coap_rx_uart1, /* name */ "obs;title=\"rx_uart1\"", /* attributes */ @@ -85,27 +85,27 @@ EVENT_RESOURCE(resource_coap_rx_uart1, /* name */ NULL, /* DELETE handler */ event_coap_rx_uart1_handler); /* event handler */ static void -get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%s", rx_buf); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } -} +} static void event_coap_rx_uart1_handler(void) { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_coap_rx_uart1); + coap_notify_observers(&resource_coap_rx_uart1); } /*****************************************************************************/ -/* GET/PUT resource to send data to terminal on UART1 */ +/* GET/PUT resource to send data to terminal on UART1 */ /*****************************************************************************/ RESOURCE(resource_coap_tx_uart1, /* name */ "obs;title=\"tx_uart1\"", /* attributes */ @@ -115,14 +115,14 @@ RESOURCE(resource_coap_tx_uart1, /* name */ NULL); /* DELETE handler */ static void -put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); string2uart1((uint8_t *)request_content); } } @@ -140,23 +140,20 @@ PROCESS_THREAD(start_app, ev, data) /* Define process that handles data */ process_start(&rx_data_process ,NULL); /* Initialise UART1 */ - uart1_init(UART1_BAUD_RATE); + uart1_init(UART1_BAUD_RATE); /* Callback received byte */ uart1_set_input(handleRxChar); /* Start network stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); printf("Starting RPL node\n"); - - rest_init_engine(); - rest_activate_resource(&resource_coap_rx_uart1, "UART1-RX"); - rest_activate_resource(&resource_coap_tx_uart1, "UART1-TX"); + + coap_engine_init(); + coap_activate_resource(&resource_coap_rx_uart1, "UART1-RX"); + coap_activate_resource(&resource_coap_tx_uart1, "UART1-TX"); PROCESS_END(); } @@ -166,29 +163,29 @@ PROCESS_THREAD(start_app, ev, data) PROCESS_THREAD(rx_data_process, ev, data) { PROCESS_BEGIN(); - + /* Process is polled whenever data is available from uart isr */ uint8_t c; while(1) { PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); - /* Read RX ringbuffer. ASCII chars Output when LF is seen. - If overflowed, strings are skipped */ + /* Read RX ringbuffer. ASCII chars Output when LF is seen. + If overflowed, strings are skipped */ do { if (get_ringbuf(&c) == -1) { break; /* No more rx char's in ringbuffer */ } else { if (rx_buf_index == RX_BUFFER_SIZE) { /* Skip current content if buffer full */ rx_buf_index = 0; - } + } rx_buf[rx_buf_index++] = c; if ((c == '\n')||(c == '\r')) { rx_buf[rx_buf_index] = '\0'; - printf("RX on UART1: %s", rx_buf); + printf("RX on UART1: %s", rx_buf); /* Signal event to coap clients. Demo assumes data is consumed before new data comes in */ - event_coap_rx_uart1_handler(); - rx_buf_index = 0; + event_coap_rx_uart1_handler(); + rx_buf_index = 0; } } } while (1); @@ -200,7 +197,7 @@ PROCESS_THREAD(rx_data_process, ev, data) /* Local test functions */ /*************************************************************************/ /* TX function for UART1 */ -static void +static void string2uart1(uint8_t *c) { while (*c!= '\0') { @@ -210,7 +207,7 @@ string2uart1(uint8_t *c) } /* handleRxChar runs on uart isr */ -static int +static int handleRxChar(uint8_t c) { if (put_ringbuf(c) == -1) { @@ -225,7 +222,7 @@ handleRxChar(uint8_t c) /* Simple ringbuffer if tail==head, no data has been written yet on that position. So, empty buffer is also initial state */ -static int +static int get_ringbuf(uint8_t *c) { int return_val = 0; @@ -241,7 +238,7 @@ get_ringbuf(uint8_t *c) return return_val; } -static int +static int put_ringbuf(uint8_t c) { int return_val = 0; @@ -249,11 +246,10 @@ put_ringbuf(uint8_t c) uart1_disable_interrupts(); if (head_index != tail_index) { ringbuf[head_index] = c; - head_index = ((head_index+1)&RINGBUF_MAX_INDEX); + head_index = ((head_index+1)&RINGBUF_MAX_INDEX); } else { return_val = -1; } uart1_enable_interrupts(); - return return_val; + return return_val; } - diff --git a/examples/platform-specific/nrf52dk/blink-hello/Makefile b/examples/platform-specific/nrf52dk/blink-hello/Makefile index d5d2de18d..9bc1ee34f 100644 --- a/examples/platform-specific/nrf52dk/blink-hello/Makefile +++ b/examples/platform-specific/nrf52dk/blink-hello/Makefile @@ -1,6 +1,6 @@ CONTIKI_PROJECT = blink-hello -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MAKE_MAC=MAKE_MAC_NULLMAC NRF52_WITHOUT_SOFTDEVICE=1 diff --git a/examples/platform-specific/nrf52dk/coap-demo/Makefile b/examples/platform-specific/nrf52dk/coap-demo/Makefile index 37b4cef4d..39692524d 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/Makefile +++ b/examples/platform-specific/nrf52dk/coap-demo/Makefile @@ -5,10 +5,10 @@ $(error Please specify whether coap-client or coap-server should be built) endif ifneq ($(filter coap-client coap-client.flash, $(MAKECMDGOALS)),) -ifeq ($(SERVER_IPV6_ADDR),) -$(error Please define SERVER_IPV6_ADDR=) +ifeq ($(SERVER_IPV6_EP),) +$(error Please define SERVER_IPV6_EP=) else -CFLAGS += -DSERVER_IPV6_ADDR=\"$(SERVER_IPV6_ADDR)\" +CFLAGS += -DSERVER_IPV6_EP=\"$(SERVER_IPV6_EP)\" CFLAGS += -DDEVICE_NAME=\"nRF52_DK_CoAP_Client\" endif else @@ -21,6 +21,6 @@ MODULES_REL += ./resources # REST Engine shall use Erbium CoAP implementation MODULES += os/net/app-layer/coap -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-client.c b/examples/platform-specific/nrf52dk/coap-demo/coap-client.c index 1ef59b369..4effcc876 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/coap-client.c +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-client.c @@ -51,6 +51,7 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" +#include "coap-endpoint.h" #include "dev/button-sensor.h" #include "dev/leds.h" @@ -63,13 +64,11 @@ #endif /*----------------------------------------------------------------------------*/ -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) #define OBS_RESOURCE_URI "lights/led3" #define SUBS_LED LEDS_4 #define OBS_LED LEDS_3 /*----------------------------------------------------------------------------*/ -static uip_ipaddr_t server_ipaddr[1]; /* holds the server ip address */ static coap_observee_t *obs; static struct ctimer ct; /*----------------------------------------------------------------------------*/ @@ -146,11 +145,11 @@ notification_callback(coap_observee_t *obs, void *notification, PROCESS_THREAD(er_example_observe_client, ev, data) { PROCESS_BEGIN(); - - uiplib_ipaddrconv(SERVER_IPV6_ADDR, server_ipaddr); + static coap_endpoint_t server_endpoint; + coap_endpoint_parse(SERVER_IPV6_EP, strlen(SERVER_IPV6_EP), &server_endpoint); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); #if PLATFORM_HAS_BUTTON SENSORS_ACTIVATE(button_1); @@ -164,7 +163,7 @@ PROCESS_THREAD(er_example_observe_client, ev, data) if (ev == sensors_event) { if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) { PRINTF("Starting observation\n"); - obs = coap_obs_request_registration(server_ipaddr, REMOTE_PORT, + obs = coap_obs_request_registration(&server_endpoint, OBS_RESOURCE_URI, notification_callback, NULL); } diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-server.c b/examples/platform-specific/nrf52dk/coap-demo/coap-server.c index 9df517886..6b4025cd3 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/coap-server.c +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-server.c @@ -51,7 +51,7 @@ #include #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "uip.h" #include "dev/button-sensor.h" #include "dev/leds.h" @@ -63,7 +63,7 @@ * Resources to be activated need to be imported through the extern keyword. * The build system automatically compiles the resources in the corresponding sub-directory. */ -extern resource_t res_led3; +extern coap_resource_t res_led3; static void print_local_addresses(void) @@ -99,13 +99,13 @@ PROCESS_THREAD(er_example_server, ev, data) PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); PRINTF("LL header: %u\n", UIP_LLH_LEN); PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); - PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + PRINTF("REST max chunk: %u\n", COAP_MAX_CHUNK_SIZE); print_local_addresses(); /* Initialize the REST engine. */ - rest_init_engine(); - rest_activate_resource(&res_led3, "lights/led3"); + coap_engine_init(); + coap_activate_resource(&res_led3, "lights/led3"); SENSORS_ACTIVATE(button_1); diff --git a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c index f990fcf38..695eca6a2 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c +++ b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c @@ -40,22 +40,25 @@ #include #include "contiki.h" -#include "rest-engine.h" +#include "coap.h" +#include "coap-engine.h" #include "dev/leds.h" #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, +res_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void -res_get_handler(void *request, void *response, uint8_t *buffer, +res_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void -res_event_handler(); +res_event_handler(void); /*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ EVENT_RESOURCE(res_led3, @@ -68,30 +71,30 @@ EVENT_RESOURCE(res_led3, ); static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +res_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *payload; - REST.get_request_payload(request, &payload); + coap_get_payload(request, &payload); - if (*payload == '0' || *payload == '1') { - if (*payload == '1') { + if(*payload == '0' || *payload == '1') { + if(*payload == '1') { leds_on(LEDS_3); } else { leds_off(LEDS_3); } - REST.notify_subscribers(&res_led3); - REST.set_response_status(response, REST.status.CHANGED); + coap_notify_observers(&res_led3); + coap_set_status_code(response, CHANGED_2_04); } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); } /* @@ -102,5 +105,5 @@ static void res_event_handler() { /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_led3); + coap_notify_observers(&res_led3); } diff --git a/examples/platform-specific/nrf52dk/mqtt-demo/Makefile b/examples/platform-specific/nrf52dk/mqtt-demo/Makefile index bf1b35fff..d32903531 100644 --- a/examples/platform-specific/nrf52dk/mqtt-demo/Makefile +++ b/examples/platform-specific/nrf52dk/mqtt-demo/Makefile @@ -1,6 +1,6 @@ all: mqtt-demo -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MODULES += os/net/app-layer/mqtt diff --git a/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c b/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c index 80339a4ad..6fa071617 100644 --- a/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c +++ b/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c @@ -55,6 +55,7 @@ #include "dev/leds.h" #include +#include /*---------------------------------------------------------------------------*/ /* * IBM server: quickstart.messaging.internetofthings.ibmcloud.com diff --git a/examples/platform-specific/nrf52dk/timer-test/Makefile b/examples/platform-specific/nrf52dk/timer-test/Makefile index de851dcf1..c5ddcfbd2 100644 --- a/examples/platform-specific/nrf52dk/timer-test/Makefile +++ b/examples/platform-specific/nrf52dk/timer-test/Makefile @@ -1,6 +1,6 @@ CONTIKI_PROJECT = timer-test -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MAKE_MAC=MAKE_MAC_NULLMAC NRF52_WITHOUT_SOFTDEVICE=1 diff --git a/examples/platform-specific/zoul/Makefile b/examples/platform-specific/zoul/Makefile index bc018f171..3b8a3a751 100644 --- a/examples/platform-specific/zoul/Makefile +++ b/examples/platform-specific/zoul/Makefile @@ -3,7 +3,7 @@ CONTIKI_PROJECT += test-bmp085-bmp180 test-motion test-rotation-sensor CONTIKI_PROJECT += test-grove-light-sensor test-grove-loudness-sensor CONTIKI_PROJECT += test-weather-meter test-grove-gyro test-lcd test-iaq CONTIKI_PROJECT += test-pm10-sensor test-vac-sensor test-aac-sensor -CONTIKI_PROJECT += test-zonik test-dht22.c test-ac-dimmer.c test-servo.c +CONTIKI_PROJECT += test-zonik test-dht22.c test-ac-dimmer.c CONTIKI_PROJECT += test-bme280 CONTIKI_TARGET_SOURCEFILES += tsl256x.c sht25.c bmpx8x.c motion-sensor.c diff --git a/examples/platform-specific/zoul/at-test/Makefile b/examples/platform-specific/zoul/at-test/Makefile index 8715c949f..04d282aaa 100644 --- a/examples/platform-specific/zoul/at-test/Makefile +++ b/examples/platform-specific/zoul/at-test/Makefile @@ -2,5 +2,5 @@ CONTIKI_PROJECT = at-master-test MODULES = os/services/at-master all: $(CONTIKI_PROJECT) -CONTIKI = ../../.. +CONTIKI = ../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/zoul/at-test/at-master-test.c b/examples/platform-specific/zoul/at-test/at-master-test.c index 012010c87..b7a1acddc 100644 --- a/examples/platform-specific/zoul/at-test/at-master-test.c +++ b/examples/platform-specific/zoul/at-test/at-master-test.c @@ -52,6 +52,7 @@ #include "dev/ioc.h" #include "lib/list.h" #include "dev/sha256.h" +#include "net/linkaddr.h" #include #include #include diff --git a/examples/platform-specific/zoul/orion/client/client.c b/examples/platform-specific/zoul/orion/client/client.c index 18f1a5e91..ebbd34fb0 100644 --- a/examples/platform-specific/zoul/orion/client/client.c +++ b/examples/platform-specific/zoul/orion/client/client.c @@ -33,7 +33,7 @@ #include "http-socket.h" #include "ipv6/ip64-addr.h" #include "dev/leds.h" -#include "rpl.h" +#include "net/routing/routing.h" #include /*---------------------------------------------------------------------------*/ static struct http_socket s; diff --git a/examples/platform-specific/zoul/orion/client/ifttt-client.c b/examples/platform-specific/zoul/orion/client/ifttt-client.c index ec1288753..7cc962c18 100644 --- a/examples/platform-specific/zoul/orion/client/ifttt-client.c +++ b/examples/platform-specific/zoul/orion/client/ifttt-client.c @@ -33,7 +33,7 @@ #include "http-socket.h" #include "ipv6/ip64-addr.h" #include "dev/leds.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "dev/button-sensor.h" #include /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/zoul/orion/ip64-router/Makefile.target b/examples/platform-specific/zoul/orion/ip64-router/Makefile.target index 75430a6e4..420fc52cc 100644 --- a/examples/platform-specific/zoul/orion/ip64-router/Makefile.target +++ b/examples/platform-specific/zoul/orion/ip64-router/Makefile.target @@ -1 +1,2 @@ TARGET = zoul +BOARD = orion diff --git a/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c b/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c index 433f58426..5f2a98e24 100644 --- a/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c +++ b/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c @@ -45,8 +45,7 @@ #include "contiki-net.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include "dev/leds.h" #include "ip64/ip64.h" #include "net/netstack.h" @@ -248,7 +247,7 @@ PT_THREAD(generate_routes(struct httpd_state *s)) #if WEBSERVER_CONF_LOADTIME numticks = clock_time() - numticks + 1; - ADD(" (%u.%02u sec)", numticks / CLOCK_SECOND, + ADD(" (%u.%02u sec)", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND)) / CLOCK_SECOND)); #endif @@ -308,7 +307,7 @@ PROCESS_THREAD(router_node_process, ev, data) leds_off(LEDS_DHCP); /* Set us up as a RPL root node. */ - rpl_dag_root_init_dag_delay(); + NETSTACK_ROUTING.root_start(); /* ... and do nothing more. */ while(1) { diff --git a/examples/platform-specific/zoul/rev-b/Makefile.target b/examples/platform-specific/zoul/rev-b/Makefile.target index 75430a6e4..cb458a6d9 100644 --- a/examples/platform-specific/zoul/rev-b/Makefile.target +++ b/examples/platform-specific/zoul/rev-b/Makefile.target @@ -1 +1,2 @@ TARGET = zoul +BOARD = remote-revb diff --git a/examples/platform-specific/zoul/rev-b/test-power-mgmt.c b/examples/platform-specific/zoul/rev-b/test-power-mgmt.c index 0bb364aba..942a01933 100644 --- a/examples/platform-specific/zoul/rev-b/test-power-mgmt.c +++ b/examples/platform-specific/zoul/rev-b/test-power-mgmt.c @@ -136,7 +136,7 @@ PROCESS_THREAD(test_remote_pm, ev, data) printf("PM: Soft shutdown, timeout set to %lu\n", pm_get_timeout()); leds_off(LEDS_ALL); - leds_on(LEDS_PURPLE); + leds_on(LEDS_RED); /* Wait just enough to be able to check the LED result */ etimer_set(&et, CLOCK_SECOND * 3); diff --git a/examples/platform-specific/zoul/test-grove-gyro.c b/examples/platform-specific/zoul/test-grove-gyro.c index 978aa69f8..74ff66e03 100644 --- a/examples/platform-specific/zoul/test-grove-gyro.c +++ b/examples/platform-specific/zoul/test-grove-gyro.c @@ -65,7 +65,7 @@ gyro_interrupt_callback(uint8_t status) * returns the outcome of the read operation, check to validate if the * data is valid to read */ - leds_toggle(LEDS_PURPLE); + leds_toggle(LEDS_RED); printf("Gyro: X_axis %u, Y_axis %u, Z_axis %u\n", gyro_values.x, gyro_values.y, diff --git a/examples/platform-specific/zoul/test-tsl256x.c b/examples/platform-specific/zoul/test-tsl256x.c index ed6f72327..0e6fce588 100644 --- a/examples/platform-specific/zoul/test-tsl256x.c +++ b/examples/platform-specific/zoul/test-tsl256x.c @@ -63,7 +63,7 @@ void light_interrupt_callback(uint8_t value) { printf("* Light sensor interrupt!\n"); - leds_toggle(LEDS_PURPLE); + leds_toggle(LEDS_RED); } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(remote_tsl256x_process, ev, data) diff --git a/examples/rpl-border-router/webserver/webserver.c b/examples/rpl-border-router/webserver/webserver.c index 61be96086..3658381bf 100644 --- a/examples/rpl-border-router/webserver/webserver.c +++ b/examples/rpl-border-router/webserver/webserver.c @@ -31,50 +31,31 @@ */ #include "contiki.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" +#include "net/ipv6/uip-ds6-route.h" +#include "net/ipv6/uip-sr.h" #include #include /*---------------------------------------------------------------------------*/ -static const char *TOP = "Contiki-NG\n"; -static const char *BOTTOM = "\n"; -#if BUF_USES_STACK -static char *bufptr, *bufend; -#define ADD(...) do { \ - bufptr += snprintf(bufptr, bufend - bufptr, __VA_ARGS__); \ - } while(0) -#else +static const char *TOP = "\n \n Contiki-NG\n \n\n"; +static const char *BOTTOM = "\n\n\n"; static char buf[256]; static int blen; #define ADD(...) do { \ blen += snprintf(&buf[blen], sizeof(buf) - blen, __VA_ARGS__); \ } while(0) -#endif +#define SEND(s) do { \ + SEND_STRING(s, buf); \ + blen = 0; \ +} while(0); /* Use simple webserver with only one page for minimum footprint. * Multiple connections can result in interleaved tcp segments since * a single static buffer is used for all segments. */ #include "httpd-simple.h" -/* The internal webserver can provide additional information if - * enough program flash is available. - */ -#define WEBSERVER_CONF_LOADTIME 0 -#define WEBSERVER_CONF_FILESTATS 0 -#define WEBSERVER_CONF_NEIGHBOR_STATUS 0 -/* Adding links requires a larger RAM buffer. To avoid static allocation - * the stack can be used for formatting; however tcp retransmissions - * and multiple connections can result in garbled segments. - * TODO:use PSOCk_GENERATOR_SEND and tcp state storage to fix this. - */ -#define WEBSERVER_CONF_ROUTE_LINKS 0 -#if WEBSERVER_CONF_ROUTE_LINKS -#define BUF_USES_STACK 1 -#endif /*---------------------------------------------------------------------------*/ static void @@ -102,210 +83,72 @@ ipaddr_add(const uip_ipaddr_t *addr) static PT_THREAD(generate_routes(struct httpd_state *s)) { - static uip_ds6_route_t *r; -#if RPL_WITH_NON_STORING - static rpl_ns_node_t *link; -#endif /* RPL_WITH_NON_STORING */ static uip_ds6_nbr_t *nbr; -#if BUF_USES_STACK - char buf[256]; -#endif -#if WEBSERVER_CONF_LOADTIME - static clock_time_t numticks; - numticks = clock_time(); -#endif PSOCK_BEGIN(&s->sout); - SEND_STRING(&s->sout, TOP); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif - ADD("Neighbors
");
 
+  ADD("  Neighbors\n  
    \n"); + SEND(&s->sout); for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { - -#if WEBSERVER_CONF_NEIGHBOR_STATUS -#if BUF_USES_STACK - { char *j = bufptr + 25; - ipaddr_add(&nbr->ipaddr); - while(bufptr < j) ADD(" "); - switch(nbr->state) { - case NBR_INCOMPLETE: ADD(" INCOMPLETE"); - break; - case NBR_REACHABLE: ADD(" REACHABLE"); - break; - case NBR_STALE: ADD(" STALE"); - break; - case NBR_DELAY: ADD(" DELAY"); - break; - case NBR_PROBE: ADD(" NBR_PROBE"); - break; - } - } -#else - { uint8_t j = blen + 25; - ipaddr_add(&nbr->ipaddr); - while(blen < j) ADD(" "); - switch(nbr->state) { - case NBR_INCOMPLETE: ADD(" INCOMPLETE"); - break; - case NBR_REACHABLE: ADD(" REACHABLE"); - break; - case NBR_STALE: ADD(" STALE"); - break; - case NBR_DELAY: ADD(" DELAY"); - break; - case NBR_PROBE: ADD(" NBR_PROBE"); - break; - } - } -#endif -#else + ADD("
  • "); ipaddr_add(&nbr->ipaddr); -#endif - - ADD("\n"); -#if BUF_USES_STACK - if(bufptr > bufend - 45) { - SEND_STRING(&s->sout, buf); - bufptr = buf; - bufend = bufptr + sizeof(buf); - } -#else - if(blen > sizeof(buf) - 45) { - SEND_STRING(&s->sout, buf); - blen = 0; - } -#endif + ADD("
  • \n"); + SEND(&s->sout); } - ADD("
Routes
\n");
-  SEND_STRING(&s->sout, buf);
-#if BUF_USES_STACK
-  bufptr = buf;
-  bufend = bufptr + sizeof(buf);
-#else
-  blen = 0;
-#endif
+  ADD("  \n");
+  SEND(&s->sout);
 
-  for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) {
-
-#if BUF_USES_STACK
-#if WEBSERVER_CONF_ROUTE_LINKS
-    ADD("ipaddr);
-    ADD("]/status.shtml>");
-    ipaddr_add(&r->ipaddr);
-    ADD("");
-#else
-    ipaddr_add(&r->ipaddr);
-#endif
-#else
-#if WEBSERVER_CONF_ROUTE_LINKS
-    ADD("ipaddr);
-    ADD("]/status.shtml>");
-    SEND_STRING(&s->sout, buf);
-    blen = 0;
-    ipaddr_add(&r->ipaddr);
-    ADD("");
-#else
-    ipaddr_add(&r->ipaddr);
-#endif
-#endif
-    ADD("/%u (via ", r->length);
-    ipaddr_add(uip_ds6_route_nexthop(r));
-    if(1 || (r->state.lifetime < 600)) {
-      ADD(") %lus\n", (unsigned long)r->state.lifetime);
-    } else {
-      ADD(")\n");
+#if (UIP_MAX_ROUTES != 0)
+  {
+    static uip_ds6_route_t *r;
+    ADD("  Routes\n  
    \n"); + SEND(&s->sout); + for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { + ADD("
  • "); + ipaddr_add(&r->ipaddr); + ADD("/%u (via ", r->length); + ipaddr_add(uip_ds6_route_nexthop(r)); + ADD(") %lus", (unsigned long)r->state.lifetime); + ADD("
  • \n"); + SEND(&s->sout); } - SEND_STRING(&s->sout, buf); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif + ADD("
\n"); + SEND(&s->sout); } - ADD("
"); +#endif /* UIP_MAX_ROUTES != 0 */ -#if RPL_WITH_NON_STORING - ADD("Links
\n");
-  SEND_STRING(&s->sout, buf);
-#if BUF_USES_STACK
-  bufptr = buf;
-  bufend = bufptr + sizeof(buf);
-#else
-  blen = 0;
-#endif
-  for(link = rpl_ns_node_head(); link != NULL; link = rpl_ns_node_next(link)) {
-    if(link->parent != NULL) {
-      uip_ipaddr_t child_ipaddr;
-      uip_ipaddr_t parent_ipaddr;
+#if (UIP_SR_LINK_NUM != 0)
+  if(uip_sr_num_nodes() > 0) {
+    static uip_sr_node_t *link;
+    ADD("  Routing links\n  
    \n"); + SEND(&s->sout); + for(link = uip_sr_node_head(); link != NULL; link = uip_sr_node_next(link)) { + if(link->parent != NULL) { + uip_ipaddr_t child_ipaddr; + uip_ipaddr_t parent_ipaddr; - rpl_ns_get_node_global_addr(&child_ipaddr, link); - rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent); + NETSTACK_ROUTING.get_sr_node_ipaddr(&child_ipaddr, link); + NETSTACK_ROUTING.get_sr_node_ipaddr(&parent_ipaddr, link->parent); -#if BUF_USES_STACK -#if WEBSERVER_CONF_ROUTE_LINKS - ADD(""); - ipaddr_add(&child_ipaddr); - ADD(""); -#else - ipaddr_add(&child_ipaddr); -#endif -#else -#if WEBSERVER_CONF_ROUTE_LINKS - ADD(""); - SEND_STRING(&s->sout, buf); - blen = 0; - ipaddr_add(&child_ipaddr); - ADD(""); -#else - ipaddr_add(&child_ipaddr); -#endif -#endif + ADD("
  • "); + ipaddr_add(&child_ipaddr); - ADD(" (parent: "); - ipaddr_add(&parent_ipaddr); - if(1 || (link->lifetime < 600)) { - ADD(") %us\n", (unsigned int)link->lifetime); - } else { - ADD(")\n"); + ADD(" (parent: "); + ipaddr_add(&parent_ipaddr); + ADD(") %us", (unsigned int)link->lifetime); + + ADD("
  • \n"); + SEND(&s->sout); } - SEND_STRING(&s->sout, buf); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif } + ADD("
"); + SEND(&s->sout); } - ADD("
"); -#endif /* RPL_WITH_NON_STORING */ +#endif /* UIP_SR_LINK_NUM != 0 */ -#if WEBSERVER_CONF_FILESTATS - static uint16_t numtimes; - ADD("
This page sent %u times", ++numtimes); -#endif - -#if WEBSERVER_CONF_LOADTIME - numticks = clock_time() - numticks + 1; - ADD(" (%u.%02u sec)", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND)) / CLOCK_SECOND)); -#endif - - SEND_STRING(&s->sout, buf); SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); diff --git a/examples/rpl-udp/cc2538-node.resc b/examples/rpl-udp/cc2538-node.resc index 55a043852..8d5b94329 100644 --- a/examples/rpl-udp/cc2538-node.resc +++ b/examples/rpl-udp/cc2538-node.resc @@ -24,7 +24,7 @@ macro reset sysbus LoadBinary @http://antmicro.com/projects/renode/cc2538_rom_dump.bin-s_524288-0c196cdc21b5397f82e0ff42b206d1cc4b6d7522 0x0 sysbus LoadELF $bin - cpu VectorTableOffset 0x200000 + cpu VectorTableOffset `sysbus GetSymbolAddress "vectors"` """ runMacro $reset diff --git a/examples/rpl-udp/rpl-udp-cooja.csc b/examples/rpl-udp/rpl-udp-cooja.csc index b37169090..a17dd6f45 100644 --- a/examples/rpl-udp/rpl-udp-cooja.csc +++ b/examples/rpl-udp/rpl-udp-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL-UDP Example diff --git a/examples/rpl-udp/rpl-udp-sky.csc b/examples/rpl-udp/rpl-udp-sky.csc index f2a217a7b..7975acf05 100644 --- a/examples/rpl-udp/rpl-udp-sky.csc +++ b/examples/rpl-udp/rpl-udp-sky.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL-UDP Example diff --git a/examples/rpl-udp/udp-client.c b/examples/rpl-udp/udp-client.c index 10e336dac..a10d188ac 100644 --- a/examples/rpl-udp/udp-client.c +++ b/examples/rpl-udp/udp-client.c @@ -1,5 +1,5 @@ #include "contiki.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "random.h" #include "net/netstack.h" #include "net/ipv6/simple-udp.h" @@ -45,6 +45,7 @@ PROCESS_THREAD(udp_client_process, ev, data) { static struct etimer periodic_timer; static unsigned count; + uip_ipaddr_t dest_ipaddr; PROCESS_BEGIN(); @@ -56,25 +57,21 @@ PROCESS_THREAD(udp_client_process, ev, data) while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer)); - if(rpl_is_reachable()) { + if(NETSTACK_ROUTING.node_is_reachable() && NETSTACK_ROUTING.get_root_ipaddr(&dest_ipaddr)) { /* Send to DAG root */ - rpl_dag_t *dag = rpl_get_any_dag(); - if(dag != NULL) { /* Only a sanity check. Should never be NULL - as rpl_is_reachable() is true */ - LOG_INFO("Sending request %u to ", count); - LOG_INFO_6ADDR(&dag->dag_id); - LOG_INFO_("\n"); - /* Set the number of transmissions to use for this packet - - this can be used to create more reliable transmissions or - less reliable than the default. Works end-to-end if - UIP_CONF_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS is set to 1. - */ - uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, 1 + count % 5); - simple_udp_sendto(&udp_conn, &count, sizeof(count), &dag->dag_id); - count++; - } + LOG_INFO("Sending request %u to ", count); + LOG_INFO_6ADDR(&dest_ipaddr); + LOG_INFO_("\n"); + /* Set the number of transmissions to use for this packet - + this can be used to create more reliable transmissions or + less reliable than the default. Works end-to-end if + UIP_CONF_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS is set to 1. + */ + uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, 1 + count % 5); + simple_udp_sendto(&udp_conn, &count, sizeof(count), &dest_ipaddr); + count++; } else { - LOG_INFO("Not reachable yet %p\n", rpl_get_any_dag()); + LOG_INFO("Not reachable yet\n"); } /* Add some jitter */ diff --git a/examples/rpl-udp/udp-server.c b/examples/rpl-udp/udp-server.c index 222556d59..399cabfc4 100644 --- a/examples/rpl-udp/udp-server.c +++ b/examples/rpl-udp/udp-server.c @@ -28,8 +28,7 @@ */ #include "contiki.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include "net/netstack.h" #include "net/ipv6/simple-udp.h" @@ -72,7 +71,7 @@ PROCESS_THREAD(udp_server_process, ev, data) PROCESS_BEGIN(); /* Initialize DAG root */ - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); /* Initialize UDP connection */ simple_udp_register(&udp_conn, UDP_SERVER_PORT, NULL, diff --git a/examples/slip-radio/Makefile b/examples/slip-radio/Makefile index 3ab7bffa3..6b30b2d13 100644 --- a/examples/slip-radio/Makefile +++ b/examples/slip-radio/Makefile @@ -10,5 +10,5 @@ PROJECT_SOURCEFILES += slip-net.c # custom net layer, but with IPv6 enabled MAKE_NET = MAKE_NET_IPV6 -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING include $(CONTIKI)/Makefile.include diff --git a/examples/slip-radio/sky/module-macros.h b/examples/slip-radio/sky/module-macros.h index cbf6a3827..1fabdf1cf 100644 --- a/examples/slip-radio/sky/module-macros.h +++ b/examples/slip-radio/sky/module-macros.h @@ -32,7 +32,5 @@ #define QUEUEBUF_CONF_NUM 4 #define UIP_CONF_BUFFER_SIZE 140 -#define CMD_CONF_HANDLERS slip_radio_cmd_handler,cmd_handler_cc2420 -#define SLIP_RADIO_CONF_SENSORS slip_radio_sky_sensors #define UART1_CONF_RX_WITH_DMA 1 /*---------------------------------------------------------------------------*/ diff --git a/examples/slip-radio/sky/slip-radio-cc2420.c b/examples/slip-radio/sky/slip-radio-cc2420.c deleted file mode 100644 index f49e3c4e9..000000000 --- a/examples/slip-radio/sky/slip-radio-cc2420.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011, Swedish Institute of Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - * Sets up some commands for the CC2420 radio chip. - */ - -#include "contiki.h" -#include "cc2420.h" -#include "cmd.h" -#include - -int -cmd_handler_cc2420(const uint8_t *data, int len) -{ - if(data[0] == '!') { - if(data[1] == 'C') { - printf("cc2420_cmd: setting channel: %d\n", data[2]); - cc2420_set_channel(data[2]); - return 1; - } - } else if(data[0] == '?') { - if(data[1] == 'C') { - uint8_t buf[4]; - printf("cc2420_cmd: getting channel: %d\n", data[2]); - buf[0] = '!'; - buf[1] = 'C'; - buf[2] = cc2420_get_channel(); - cmd_send(buf, 3); - return 1; - } - } - return 0; -} diff --git a/examples/slip-radio/sky/slip-radio-sky-sensors.c b/examples/slip-radio/sky/slip-radio-sky-sensors.c deleted file mode 100644 index 9cf238741..000000000 --- a/examples/slip-radio/sky/slip-radio-sky-sensors.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2011, Swedish Institute of Computer Science. - * 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. - */ - -#include "contiki.h" -#include "lib/sensors.h" -#include "dev/sht11/sht11-sensor.h" -#include "slip-radio.h" -#include "cmd.h" -#include - -/*---------------------------------------------------------------------------*/ -static void -init(void) -{ -} -/*---------------------------------------------------------------------------*/ -static int -write_percent_float(char *data, int maxlen, int temp) -{ - int t; - t = temp % 100; - if(t < 0) { - t = -t; - } - return snprintf(data, maxlen, "%d.%02d", temp / 100, t); -} -/*---------------------------------------------------------------------------*/ -static void -send(void) -{ -#define MAX_SIZE 40 - char data[MAX_SIZE]; - int temperature; - int ms; - long hum; - int pos = 0; - - /* SENSORS_ACTIVATE(light_sensor); */ - SENSORS_ACTIVATE(sht11_sensor); - - pos += snprintf(data, MAX_SIZE, "!D"); - /* int light1 = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); */ - /* int light2 = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); */ - temperature = -3970 + sht11_sensor.value(SHT11_SENSOR_TEMP); - ms = sht11_sensor.value(SHT11_SENSOR_HUMIDITY); - /* this is in * 10000 */ - /* -2.0468 + 0.0367 * ms + -1.5955e-6 * ms * ms ...too small value... */ - hum = (-20468L + 367L * ms) / 100L; - - /* SENSORS_DEACTIVATE(light_sensor); */ - SENSORS_DEACTIVATE(sht11_sensor); - - pos += snprintf(&data[pos], MAX_SIZE - pos, "temp="); - pos += write_percent_float(&data[pos], MAX_SIZE - pos, temperature); - pos += snprintf(&data[pos], MAX_SIZE - pos, ";hum="); - pos += write_percent_float(&data[pos], MAX_SIZE - pos, hum); - - cmd_send((uint8_t *)data, pos); -} -/* ---------------------------------------------------------------------- */ -const struct slip_radio_sensors slip_radio_sky_sensors = { - init, send -}; -/* ---------------------------------------------------------------------- */ diff --git a/examples/slip-radio/slip-net.c b/examples/slip-radio/slip-net.c index e1efbf4cf..edf219106 100644 --- a/examples/slip-radio/slip-net.c +++ b/examples/slip-radio/slip-net.c @@ -64,7 +64,7 @@ slipnet_input(void) packetbuf_datalen(), i); for(i = 0; i < uip_len; i++) { - LOG_DBG("%02x", (unsigned char)uip_buf[i]); + LOG_DBG_("%02x", (unsigned char)uip_buf[i]); if((i & 15) == 15) { LOG_DBG_("\n"); } else if((i & 7) == 7) { diff --git a/examples/slip-radio/slip-radio.c b/examples/slip-radio/slip-radio.c index 53a0324bc..30a9387df 100644 --- a/examples/slip-radio/slip-radio.c +++ b/examples/slip-radio/slip-radio.c @@ -166,6 +166,25 @@ slip_radio_cmd_handler(const uint8_t *data, int len) packet_pos = 0; } + return 1; + } else if(data[1] == 'V') { + int type = ((uint16_t)data[2] << 8) | data[3]; + int value = ((uint16_t)data[4] << 8) | data[5]; + int param = type; /* packetutils_to_radio_param(type); */ + if(param < 0) { + printf("radio: unknown parameter %d (can not set to %d)\n", type, value); + } else { + if(param == RADIO_PARAM_RX_MODE) { + printf("radio: setting rxmode to 0x%x\n", value); + } else if(param == RADIO_PARAM_PAN_ID) { + printf("radio: setting pan id to 0x%04x\n", value); + } else if(param == RADIO_PARAM_CHANNEL) { + printf("radio: setting channel: %u\n", value); + } else { + printf("radio: setting param %d to %d (0x%02x)\n", param, value, value); + } + NETSTACK_RADIO.set_value(param, value); + } return 1; } } else if(uip_buf[0] == '?') { @@ -180,6 +199,25 @@ slip_radio_cmd_handler(const uint8_t *data, int len) uip_len = 10; cmd_send(uip_buf, uip_len); return 1; + } else if(data[1] == 'V') { + /* ask the radio about the specific parameter and send it back... */ + int type = ((uint16_t)data[2] << 8) | data[3]; + int value; + int param = type; /* packetutils_to_radio_param(type); */ + if(param < 0) { + printf("radio: unknown parameter %d\n", type); + } + + NETSTACK_RADIO.get_value(param, &value); + + uip_buf[0] = '!'; + uip_buf[1] = 'V'; + uip_buf[2] = type >> 8; + uip_buf[3] = type & 0xff; + uip_buf[4] = value >> 8; + uip_buf[5] = value & 0xff; + uip_len = 6; + cmd_send(uip_buf, uip_len); } } return 0; @@ -189,7 +227,9 @@ static void slip_input_callback(void) { LOG_DBG("SR-SIN: %u '%c%c'\n", uip_len, uip_buf[0], uip_buf[1]); - cmd_input(uip_buf, uip_len); + if(!cmd_input(uip_buf, uip_len)) { + cmd_send((uint8_t *)"EUnknown command", 16); + } uip_clear_buf(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/storage/cfs-coffee/Makefile b/examples/storage/cfs-coffee/Makefile index 4d27d6f8f..31a1aea59 100644 --- a/examples/storage/cfs-coffee/Makefile +++ b/examples/storage/cfs-coffee/Makefile @@ -1,6 +1,7 @@ CONTIKI = ../../.. MODULES += os/services/unit-test +MODULES += os/storage/cfs all: test-cfs test-coffee example-coffee diff --git a/examples/storage/cfs-coffee/README.md b/examples/storage/cfs-coffee/README.md index 991e9583b..028f518f8 100644 --- a/examples/storage/cfs-coffee/README.md +++ b/examples/storage/cfs-coffee/README.md @@ -23,6 +23,9 @@ Supported Hardware (tested or known to work) * cc2538dk * openmote-cc2538 * zoul +* TI srf06-cc26xx + - sensortag + - launchpad The examples are known to build for the 'avr-raven' platform. However, some of them currently fail at runtime due to file system overflow. diff --git a/os/contiki-default-conf.h b/os/contiki-default-conf.h index 0395f6ca4..8ec1a41f7 100644 --- a/os/contiki-default-conf.h +++ b/os/contiki-default-conf.h @@ -81,6 +81,10 @@ #define UIP_CONF_ROUTER 1 #endif /* UIP_CONF_ROUTER */ +/* UIP_CONF_IPV6_RPL tells whether the RPL routing protocol is running, + whether implemented as RPL Lite or RPL Classic */ +#define UIP_CONF_IPV6_RPL (ROUTING_CONF_RPL_LITE || ROUTING_CONF_RPL_CLASSIC) + /* If RPL is enabled also enable the RPL NBR Policy */ #if UIP_CONF_IPV6_RPL #ifndef NBR_TABLE_FIND_REMOVABLE diff --git a/os/contiki-net.h b/os/contiki-net.h index 9b467363f..1eb50dd8d 100644 --- a/os/contiki-net.h +++ b/os/contiki-net.h @@ -42,6 +42,7 @@ #include "net/ipv6/uip-udp-packet.h" #include "net/ipv6/simple-udp.h" #include "net/ipv6/uip-nameserver.h" +#include "net/routing/routing.h" #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip-icmp6.h" diff --git a/os/dev/gpio-hal.c b/os/dev/gpio-hal.c new file mode 100644 index 000000000..70b50b688 --- /dev/null +++ b/os/dev/gpio-hal.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup gpio-hal + * @{ + * + * \file + * Implementation of the platform-independent aspects of the GPIO HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "lib/list.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +LIST(handlers); +/*---------------------------------------------------------------------------*/ +void +gpio_hal_register_handler(gpio_hal_event_handler_t *handler) +{ + list_add(handlers, handler); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_event_handler(gpio_hal_pin_mask_t pins) +{ + gpio_hal_event_handler_t *this; + + for(this = list_head(handlers); this != NULL; this = this->next) { + if(pins & this->pin_mask) { + if(this->handler != NULL) { + this->handler(pins & this->pin_mask); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_init() +{ + list_init(handlers); +} +/*---------------------------------------------------------------------------*/ +#if GPIO_HAL_ARCH_SW_TOGGLE +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_toggle_pin(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + return; + } + + gpio_hal_arch_write_pin(pin, gpio_hal_arch_read_pin(pin) ^ 1); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_toggle_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_arch_write_pins(pins, ~gpio_hal_arch_read_pins(pins)); +} +/*---------------------------------------------------------------------------*/ +#endif /* GPIO_HAL_ARCH_SW_TOGGLE */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/os/dev/gpio-hal.h b/os/dev/gpio-hal.h new file mode 100644 index 000000000..aacbfb1f1 --- /dev/null +++ b/os/dev/gpio-hal.h @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup dev + * @{ + * + * \defgroup gpio-hal GPIO Hardware Abstraction Layer + * + * The GPIO HAL provides a set of common functions that can be used in a + * platform-independent fashion. + * + * Internally, the GPIO HAL handles edge detection handling and also provides + * fallback functions for GPIO pin toggling if the hardware does not have + * a direct method of toggling pins through direct register access. + * + * @{ + * + * \file + * Header file for the GPIO HAL + */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_HAL_H_ +#define GPIO_HAL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Specifies whether software-based pin toggle is required + * + * Some MCUs allow GPIO pin toggling via direct register access. For these + * MCUs, define GPIO_HAL_CONF_ARCH_SW_TOGGLE to 0 and then implement + * gpio_hal_arch_toggle_pin() and gpio_hal_arch_toggle_pins() + * + * \sa gpio_hal_arch_toggle_pin() + * \sa gpio_hal_arch_toggle_pins() + */ +#ifdef GPIO_HAL_CONF_ARCH_SW_TOGGLE +#define GPIO_HAL_ARCH_SW_TOGGLE GPIO_HAL_CONF_ARCH_SW_TOGGLE +#else +#define GPIO_HAL_ARCH_SW_TOGGLE 1 +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief GPIO pin number representation + */ +typedef uint8_t gpio_hal_pin_t; + +/** + * \brief GPIO pin configuration + * + * A logical representation of a pin's configuration. It is an OR combination + * of GPIO_HAL_PIN_CFG_xyz macros. + */ +typedef uint8_t gpio_hal_pin_cfg_t; + +#ifdef GPIO_HAL_CONF_PIN_COUNT +#define GPIO_HAL_PIN_COUNT GPIO_HAL_CONF_PIN_COUNT +#else +#define GPIO_HAL_PIN_COUNT 32 +#endif + +#if GPIO_HAL_PIN_COUNT > 32 +typedef uint64_t gpio_hal_pin_mask_t; +#else +/** + * \brief GPIO pin mask representation + */ +typedef uint32_t gpio_hal_pin_mask_t; +#endif + +typedef void (*gpio_hal_callback_t)(gpio_hal_pin_mask_t pin_mask); +/*---------------------------------------------------------------------------*/ +#define GPIO_HAL_PIN_CFG_PULL_NONE 0x00 +#define GPIO_HAL_PIN_CFG_PULL_UP 0x01 +#define GPIO_HAL_PIN_CFG_PULL_DOWN 0x02 +#define GPIO_HAL_PIN_CFG_PULL_MASK (GPIO_HAL_PIN_CFG_PULL_UP | \ + GPIO_HAL_PIN_CFG_PULL_DOWN) + +#define GPIO_HAL_PIN_CFG_EDGE_NONE 0x00 +#define GPIO_HAL_PIN_CFG_EDGE_RISING 0x04 +#define GPIO_HAL_PIN_CFG_EDGE_FALLING 0x08 +#define GPIO_HAL_PIN_CFG_EDGE_BOTH (GPIO_HAL_PIN_CFG_EDGE_RISING | \ + GPIO_HAL_PIN_CFG_EDGE_FALLING) + +#define GPIO_HAL_PIN_CFG_INT_DISABLE 0x00 +#define GPIO_HAL_PIN_CFG_INT_ENABLE 0x80 +#define GPIO_HAL_PIN_CFG_INT_MASK 0x80 +/*---------------------------------------------------------------------------*/ +/** + * \brief Datatype for GPIO event handlers + * + * A GPIO event handler is a function that gets called whenever a pin triggers + * an event. The same handler can be registered to handle events for more than + * one pin by setting the respective pin's position but in \e pin_mask. + */ +typedef struct gpio_hal_event_handler_s { + struct gpio_hal_event_handler_s *next; + gpio_hal_callback_t handler; + gpio_hal_pin_mask_t pin_mask; +} gpio_hal_event_handler_t; +/*---------------------------------------------------------------------------*/ +/** + * \name Core GPIO functions + * + * Functions implemented by the HAL itself + * @{ + */ +/** + * \brief Initialise the GPIO HAL + */ +void gpio_hal_init(void); + +/** + * \brief Register a function to be called whenever a pin triggers an event + * \param handler The handler representation + * + * The handler must be pre-allocated statically by the caller. + * + * This function can be used to register a function to be called by the HAL + * whenever a GPIO interrupt occurs. + * + * \sa gpio_hal_event_handler + */ +void gpio_hal_register_handler(gpio_hal_event_handler_t *handler); + +/** + * \brief The platform-independent GPIO event handler + * \param pins OR mask of pins that generated an event + * + * Whenever a GPIO input interrupt occurs (edge or level detection) and an ISR + * is triggered, the ISR must call this function, passing as argument an ORd + * mask of the pins that triggered the interrupt. This function will then + * call the registered event handlers (if any) for the pins that triggered the + * event. The platform code should make no assumptions as to the order that + * the handlers will be called. + * + * If a pin set in the mask has an event handler registered, this function + * will call the registered handler. + * + * This function will not clear any CPU interrupt flags, this should be done + * by the calling ISR. + * + * \sa gpio_hal_register_handler + */ +void gpio_hal_event_handler(gpio_hal_pin_mask_t pins); + +/** + * \brief Convert a pin to a pin mask + * \param pin The pin + * \return The corresponding mask + */ +#define gpio_hal_pin_to_mask(pin) (1 << (pin)) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Functions to be provided by the platform + * + * All the functions below must be provided by the platform's developer. The + * HAL offers the developer a number of options of how to provide the required + * functionality. + * + * - The developer can provide a symbol. For example, the developer can create + * a .c file and implement a function called gpio_hal_arch_set_pin() + * - The developer can provide a function-like macro that has the same name as + * the function declared here. In this scenario, the declaration here will + * be removed by the pre-processor. For example, the developer can do + * something like: + * + * \code + * #define gpio_hal_arch_write_pin(p, v) platform_sdk_function(p, v) + * \endcode + * + * - The developer can provide a static inline implementation. For this to + * work, the developer can do something like: + * + * \code + * #define gpio_hal_arch_set_pin(p) set_pin(p) + * static inline void set_pin(gpio_hal_pin_t pin) { ... } + * \endcode + * + * In the latter two cases, the developer will likely provide implementations + * in a header file. In this scenario, one of the platform's configuration + * files must define GPIO_HAL_CONF_ARCH_HDR_PATH to the name of this header + * file. For example: + * + * \code + * #define GPIO_HAL_CONF_ARCH_HDR_PATH "dev/gpio-hal-arch.h" + * \endcode + * + * @{ + */ +/*---------------------------------------------------------------------------*/ +/* Include Arch-Specific conf */ +#ifdef GPIO_HAL_CONF_ARCH_HDR_PATH +#include GPIO_HAL_CONF_ARCH_HDR_PATH +#endif /* GPIO_HAL_CONF_ARCH_HDR_PATH */ +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_interrupt_enable +/** + * \brief Enable interrupts for a gpio pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_interrupt_disable +/** + * \brief Disable interrupts for a gpio pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_cfg_set +/** + * \brief Configure a gpio pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \param cfg The configuration + * + * \e cfg is an OR mask of GPIO_HAL_PIN_CFG_xyz + * + * The implementation of this function also has to make sure that \e pin is + * configured as software-controlled GPIO. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_cfg_get +/** + * \brief Read the configuration of a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \return An OR mask of GPIO_HAL_PIN_CFG_xyz + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +gpio_hal_pin_cfg_t gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_set_input +/** + * \brief Configure a pin as GPIO input + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * The implementation of this function also has to make sure that \e pin is + * configured as software-controlled GPIO. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_pin_set_input(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_set_output +/** + * \brief Configure a pin as GPIO output + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * The implementation of this function also has to make sure that \e pin is + * configured as software-controlled GPIO. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_pin_set_output(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_set_pin +/** + * \brief Set a GPIO pin to logical high + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_set_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_clear_pin +/** + * \brief Clear a GPIO pin (logical low) + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_clear_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_toggle_pin +/** + * \brief Toggle a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * Some MCUs allow GPIO pin toggling directly via register access. In this + * case, it is a good idea to provide an implementation of this function. + * However, a default, software-based implementation is also provided by the + * HAL and can be used if the MCU does not have a pin toggle register. To use + * the HAL function, define GPIO_HAL_ARCH_SW_TOGGLE as 1. To provide your own + * implementation, define GPIO_HAL_ARCH_SW_TOGGLE as 0. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_toggle_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_read_pin +/** + * \brief Read a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \retval 0 The pin is logical low + * \retval 1 The pin is logical high + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +uint8_t gpio_hal_arch_read_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_write_pin +/** + * \brief Write a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \param value 0: Logical low; 1: Logical high + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_set_pins +/** + * \brief Set multiple pins to logical high + * \param pins An ORd pin mask of the pins to set + * + * A pin will be set to logical high if its position in \e pins is set. For + * example you can set pins 0 and 3 by passing 0x09. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_clear_pins +/** + * \brief Clear multiple pins to logical low + * \param pins An ORd pin mask of the pins to clear + * + * A pin will be set to logical low if its position in \e pins is set. For + * example you can clear pins 0 and 3 by passing 0x09. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_toggle_pins +/** + * \brief Toggle multiple pins + * \param pins An ORd pin mask of the pins to toggle + * + * A pin will be toggled if its position in \e pins is set. For example you + * can toggle pins 0 and 3 by passing 0x09. + * + * Some MCUs allow GPIO pin toggling directly via register access. In this + * case, it is a good idea to provide an implementation of this function. + * However, a default, software-based implementation is also provided by the + * HAL and can be used if the MCU does not have a pin toggle register. To use + * the HAL function, define GPIO_HAL_ARCH_SW_TOGGLE as 1. To provide your own + * implementation, define GPIO_HAL_ARCH_SW_TOGGLE as 0. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_toggle_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_read_pins +/** + * \brief Read multiple pins + * \param pins An ORd pin mask of the pins to read + * \retval An ORd mask of the pins that are high + * + * If the position of the pin in \e pins is set and the pin is logical high + * then the position of the pin in the return value will be set. For example, + * if you pass 0x09 as the value of \e pins and the return value is 0x08 then + * pin 3 is logical high and pin 0 is logical low. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +gpio_hal_pin_mask_t gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_write_pins +/** + * \brief Write multiple pins + * \param pins An ORd pin mask of the pins to write + * \param value An ORd mask of the value to write + * + * The function will modify GPIO pins that have their position in the mask set. + * pins, the function will write the value specified in the corresponding + * position in \e value. + + * For example, you can set pin 3 and clear pin 0 by a single call to this + * function. To achieve this, \e pins must be 0x09 and \e value 0x08. + * + * It is the platform developer's responsibility to provide an implementation. + * + * There is no guarantee that this function will result in an atomic operation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins, + gpio_hal_pin_mask_t value); +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* GPIO_HAL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/dev/leds.c b/os/dev/leds.c index f7028f0c2..eff3197a1 100644 --- a/os/dev/leds.c +++ b/os/dev/leds.c @@ -1,38 +1,51 @@ /* * Copyright (c) 2005, Swedish Institute of Computer Science + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. */ - +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup leds + * @{ + * + * \file + * Implementation of the platform-independent aspects of the LED HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" #include "dev/leds.h" -#include "sys/clock.h" +#include +#include +/*---------------------------------------------------------------------------*/ +#if LEDS_LEGACY_API /*---------------------------------------------------------------------------*/ void leds_init(void) @@ -59,26 +72,154 @@ leds_get(void) { } /*---------------------------------------------------------------------------*/ void -leds_set(unsigned char ledv) +leds_set(leds_mask_t ledv) { leds_arch_set(ledv); } /*---------------------------------------------------------------------------*/ void -leds_on(unsigned char ledv) +leds_on(leds_mask_t ledv) { leds_arch_set(leds_arch_get() | ledv); } /*---------------------------------------------------------------------------*/ void -leds_off(unsigned char ledv) +leds_off(leds_mask_t ledv) { leds_arch_set(leds_arch_get() & ~ledv); } /*---------------------------------------------------------------------------*/ void -leds_toggle(unsigned char ledv) +leds_toggle(leds_mask_t ledv) { leds_arch_set(leds_arch_get() ^ ledv); } /*---------------------------------------------------------------------------*/ +#else /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +extern const leds_t leds_arch_leds[]; +/*---------------------------------------------------------------------------*/ +void +leds_init() +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + gpio_hal_arch_pin_set_output(leds_arch_leds[led].pin); + } + leds_off(LEDS_ALL); +} +/*---------------------------------------------------------------------------*/ +void +leds_single_on(leds_num_t led) +{ + if(led >= LEDS_COUNT) { + return; + } + + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } +} +/*---------------------------------------------------------------------------*/ +void +leds_single_off(leds_num_t led) +{ + if(led >= LEDS_COUNT) { + return; + } + + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } +} +/*---------------------------------------------------------------------------*/ +void +leds_single_toggle(leds_num_t led) +{ + if(led >= LEDS_COUNT) { + return; + } + + gpio_hal_arch_toggle_pin(leds_arch_leds[led].pin); +} +/*---------------------------------------------------------------------------*/ +void +leds_on(leds_mask_t leds) +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + if((1 << led) & leds) { + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +leds_off(leds_mask_t leds) +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + if((1 << led) & leds) { + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +leds_toggle(leds_mask_t leds) +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + if((1 << led) & leds) { + gpio_hal_arch_toggle_pin(leds_arch_leds[led].pin); + } + } +} +/*---------------------------------------------------------------------------*/ +void +leds_set(leds_mask_t leds) +{ + leds_off(LEDS_ALL); + leds_on(leds); +} +/*---------------------------------------------------------------------------*/ +leds_mask_t +leds_get() +{ + leds_mask_t rv = 0; + leds_num_t led; + uint8_t pin_state; + + for(led = 0; led < LEDS_COUNT; led++) { + pin_state = gpio_hal_arch_read_pin(leds_arch_leds[led].pin); + + if((leds_arch_leds[led].negative_logic == false && pin_state == 1) || + (leds_arch_leds[led].negative_logic == true && pin_state == 0)) { + rv |= 1 << led; + } + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +#endif /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/os/dev/leds.h b/os/dev/leds.h index d99fb8196..654ed250e 100644 --- a/os/dev/leds.h +++ b/os/dev/leds.h @@ -1,98 +1,329 @@ /* * Copyright (c) 2005, Swedish Institute of Computer Science + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/*---------------------------------------------------------------------------*/ /** * \addtogroup dev * @{ */ - +/*---------------------------------------------------------------------------*/ /** - * \defgroup leds LEDs API + * \defgroup leds LED Hardware Abstraction Layer * - * The LEDs API defines a set of functions for accessing LEDs for - * Contiki plaforms with LEDs. + * The LED HAL provides a set of functions that can manipulate LEDS. * - * A platform with LED support must implement this API. + * Currently, the LED HAL supports two APIs: + * + * - The new, platform-independent API (recommended for all new platforms). + * - The legacy API (supported until all existing platforms have been ported + * to support the new API). + * + * The two APIs use very similar semantics and have an overlapping set of + * function calls. This is done so that platform-independent examples can + * work on all platforms, irrespective of which API each platform supports. + * + * The legacy API can be enabled by the platform code by defining + * LEDS_CONF_LEGACY_API 1. + * + * Once all platforms supported in contiki-ng/contiki-ng have been ported to + * the new API, the legacy API will be deleted without warning. For this + * reason, it is strongly recommended to use the new API for new platforms and + * for platforms hosted in external repositories. + * + * The new API provides a set of common LED manipulation functions that can be + * used in a platform-independent fashion. Functions exist to manipulate one + * LED at a time (\c leds_single_XYZ), as well as to manipulate multiple LEDs + * at a time (\c leds_XYZ). + * + * The assumption is that each LED is connected to a GPIO pin using either + * positive or negative logic. + * + * LEDs on a device are numbered incrementally, starting from 0 and counting + * upwards. Thus, if a device has 3 LEDs they will be numbered 0, 1 and 2. + * Convenience macros (LEDS_LED_n) are provided to refer to LEDs. These macros + * can be used as arguments to functions that manipulate a single LED, such + * as leds_single_on() but \e not leds_on(). + * + * The legacy scheme that uses colours to refer to LEDs is maintained, without + * semantic changes, but with minor changes in logic: + * + * - Firstly, we now define 5 LED colours: Red, Green, Blue, Yellow, Orange. + * These are sufficient to cover all currently-supported platforms. + * - Secondly, unless a platform specifies that a LED of a specific colour + * exists, the HAL will assume that it does not. + * - Trying to manipulate a non-existent LED will not cause build errors, but + * will not cause any changes to LED state either. + * - We no longer map non-existing LED colours to existing ones. + * + * Note that, in order to avoid changes to LED colour semantics between the + * two APIs, references to LED by colour are bitwise OR masks and should + * therefore only be used as argument to functions that manipulate multiple + * LEDS (e.g. leds_off() and \e not leds_single_off()). + * + * In terms of porting for new platforms, developers simply have to: + * + * - Define variables of type leds_t to represent their platform's LEDs + * - Specify the number of LEDs on their device by defining LEDS_CONF_COUNT + * - Map red colours to numbers (e.g. \#define LEDS_CONF_RED 1) + * + * \file + * Header file for the LED HAL * @{ */ - +/*---------------------------------------------------------------------------*/ #ifndef LEDS_H_ #define LEDS_H_ - -/* Allow platform to override LED numbering */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" +#include "dev/gpio-hal.h" +#include +#include +/*---------------------------------------------------------------------------*/ +#if LEDS_CONF_LEGACY_API +/** + * \brief Define to 1 to enabled the legacy LED API. + */ +#define LEDS_LEGACY_API LEDS_CONF_LEGACY_API +#else +#define LEDS_LEGACY_API 0 +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief A default LED colour for non-existing LEDs + */ +#define LEDS_COLOUR_NONE 0x00 +/*---------------------------------------------------------------------------*/ +/* LED colour to number mappings. Applicable to both APIs */ +#ifdef LEDS_CONF_RED +#define LEDS_RED LEDS_CONF_RED +#else +#define LEDS_RED LEDS_COLOUR_NONE +#endif + +#ifdef LEDS_CONF_GREEN +#define LEDS_GREEN LEDS_CONF_GREEN +#else +#define LEDS_GREEN LEDS_COLOUR_NONE +#endif + +#ifdef LEDS_CONF_BLUE +#define LEDS_BLUE LEDS_CONF_BLUE +#else +#define LEDS_BLUE LEDS_COLOUR_NONE +#endif + +#ifdef LEDS_CONF_YELLOW +#define LEDS_YELLOW LEDS_CONF_YELLOW +#else +#define LEDS_YELLOW LEDS_COLOUR_NONE +#endif + +#ifdef LEDS_CONF_ORANGE +#define LEDS_ORANGE LEDS_CONF_ORANGE +#else +#define LEDS_ORANGE LEDS_COLOUR_NONE +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief The LED number + */ +typedef uint8_t leds_num_t; + +/** + * \brief An OR mask datatype to represents multiple LEDs. + */ +typedef uint8_t leds_mask_t; +/*---------------------------------------------------------------------------*/ +#if LEDS_LEGACY_API +/*---------------------------------------------------------------------------*/ +#ifdef LEDS_CONF_ALL +#define LEDS_ALL LEDS_CONF_ALL +#else +#define LEDS_ALL 7 +#endif +/*---------------------------------------------------------------------------*/ +void leds_blink(void); + +/* Legacy LED API arch-specific functions */ +void leds_arch_init(void); +leds_mask_t leds_arch_get(void); +void leds_arch_set(leds_mask_t leds); +/*---------------------------------------------------------------------------*/ +#else /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +#ifdef LEDS_CONF_COUNT +#define LEDS_COUNT LEDS_CONF_COUNT +#else +/** + * \brief The number of LEDs present on a device + */ +#define LEDS_COUNT 0 +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief The OR mask representation of all device LEDs + */ +#define LEDS_ALL ((1 << LEDS_COUNT) - 1) +/*---------------------------------------------------------------------------*/ +#endif /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +#define LEDS_LED1 0x00 /**< Convenience macro to refer to the 1st LED (LED 1) */ +#define LEDS_LED2 0x01 /**< Convenience macro to refer to the 2nd LED (LED 2) */ +#define LEDS_LED3 0x02 /**< Convenience macro to refer to the 3rd LED (LED 3) */ +#define LEDS_LED4 0x03 /**< Convenience macro to refer to the 4th LED (LED 4) */ +#define LEDS_LED5 0x04 /**< Convenience macro to refer to the 5th LED (LED 5) */ +/*---------------------------------------------------------------------------*/ +/** + * \brief A LED logical representation + * + * \e pin corresponds to the GPIO pin a LED is driven by, using GPIO HAL pin + * representation. + * + * \e negative_logic should be set to false if the LED is active low. + */ +typedef struct leds_s { + gpio_hal_pin_t pin; + bool negative_logic; +} leds_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert a LED number to a mask representation + * \param l The pin number (normally a variable of type leds_num_t) + * \return An OR mask of type leds_mask_t + */ +#define LEDS_NUM_TO_MASK(l) (1 << (l)) +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the LED HAL + * + * This function will set corresponding LED GPIO pins to output and will also + * set the initial state of all LEDs to off. + */ void leds_init(void); /** - * Blink all LEDs. + * \brief Turn a single LED on + * \param led The led + * + * The \e led argument should be the LED's number, in other words one of the + * LED_Ln macros. + * + * This function will not change the state of other LEDs. */ -void leds_blink(void); - -#ifndef LEDS_GREEN -#define LEDS_GREEN 1 -#endif /* LEDS_GREEN */ -#ifndef LEDS_YELLOW -#define LEDS_YELLOW 2 -#endif /* LEDS_YELLOW */ -#ifndef LEDS_RED -#define LEDS_RED 4 -#endif /* LEDS_RED */ -#ifndef LEDS_BLUE -#define LEDS_BLUE LEDS_YELLOW -#endif /* LEDS_BLUE */ - -#ifdef LEDS_CONF_ALL -#define LEDS_ALL LEDS_CONF_ALL -#else /* LEDS_CONF_ALL */ -#define LEDS_ALL 7 -#endif /* LEDS_CONF_ALL */ +void leds_single_on(leds_num_t led); /** - * Returns the current status of all leds + * \brief Turn a single LED off + * \param led The led + * + * The \e led argument should be the LED's number, in other words one of the + * LED_Ln macros. + * + * This function will not change the state of other LEDs. */ -unsigned char leds_get(void); -void leds_set(unsigned char leds); -void leds_on(unsigned char leds); -void leds_off(unsigned char leds); -void leds_toggle(unsigned char leds); +void leds_single_off(leds_num_t led); /** - * Leds implementation + * \brief Toggle a single LED + * \param led The led + * + * The \e led argument should be the LED's number, in other words one of the + * LED_Ln macros. + * + * This function will not change the state of other LEDs. */ -void leds_arch_init(void); -unsigned char leds_arch_get(void); -void leds_arch_set(unsigned char leds); +void leds_single_toggle(leds_num_t led); +/** + * \brief Turn on multiple LEDs + * \param leds The leds to be turned on as an OR mask + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will not change the state of other LEDs. + */ +void leds_on(leds_mask_t leds); + +/** + * \brief Turn off multiple LEDs + * \param leds The leds to be turned off as an OR mask + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will not change the state of other LEDs. + */ +void leds_off(leds_mask_t leds); + +/** + * \brief Toggle multiple LEDs + * \param leds The leds to be toggled as an OR mask + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will not change the state of other LEDs. + */ +void leds_toggle(leds_mask_t leds); + +/** + * \brief Set all LEDs to a specific state + * \param leds The state of all LEDs afer this function returns + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will change the state of all LEDs. LEDs not set in the \e leds + * mask will be turned off. + */ +void leds_set(leds_mask_t leds); + +/** + * \brief Get the status of LEDs + * \return A bitwise mask indicating whether each individual LED is on or off + * + * The return value is a bitwise mask. If a bit is set then the corresponding + * LED is on. + */ +leds_mask_t leds_get(void); +/*---------------------------------------------------------------------------*/ #endif /* LEDS_H_ */ - -/** @} */ -/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/lib/heapmem.c b/os/lib/heapmem.c index 54394ff01..7a90f1357 100644 --- a/os/lib/heapmem.c +++ b/os/lib/heapmem.c @@ -347,7 +347,7 @@ heapmem_alloc(size_t size) chunk->line = line; #endif - PRINTF("%s ptr %p size %u\n", __func__, GET_PTR(chunk), (unsigned)size); + PRINTF("%s ptr %p size %lu\n", __func__, GET_PTR(chunk), (unsigned long)size); return GET_PTR(chunk); } diff --git a/os/net/app-layer/coap/Makefile.coap b/os/net/app-layer/coap/Makefile.coap new file mode 100644 index 000000000..4afecf78a --- /dev/null +++ b/os/net/app-layer/coap/Makefile.coap @@ -0,0 +1,31 @@ +MAKE_WITH_DTLS ?= 0 + +ifeq ($(MAKE_WITH_DTLS),1) + + TINYDTLS_PATH := os/net/security/tinydtls + + ifeq (${wildcard $(CONTIKI)/$(TINYDTLS_PATH)/Makefile},) + ${error Could not find the tinyDTLS submodule. Please run "git submodule update --init" and try again} + endif + + CFLAGS += -DWITH_DTLS=1 + + MODULES += os/net/app-layer/coap/tinydtls-support + MODULES += $(TINYDTLS_PATH) ${addprefix $(TINYDTLS_PATH)/,aes sha2 ecc} + + MAKE_COAP_DTLS_KEYSTORE_NONE := 0 + MAKE_COAP_DTLS_KEYSTORE_SIMPLE := 1 + MAKE_COAP_DTLS_KEYSTORE_LWM2M := 2 + + MAKE_COAP_DTLS_KEYSTORE ?= MAKE_COAP_DTLS_KEYSTORE_LWM2M + + ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_SIMPLE) + CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE=1 + else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_LWM2M) + CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_LWM2M=1 + else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_NONE) + # No C flag needed for no keystore + else + ${error Unsupported CoAP DTLS keystore: $(MAKE_COAP_DTLS_KEYSTORE)} + endif +endif diff --git a/os/net/app-layer/coap/coap-block1.c b/os/net/app-layer/coap/coap-block1.c index 6ecdce7c6..e08a321d1 100644 --- a/os/net/app-layer/coap/coap-block1.c +++ b/os/net/app-layer/coap/coap-block1.c @@ -36,24 +36,23 @@ * Lars Schmertmann */ -#include +/** + * \addtogroup coap + * @{ + */ + #include +#include #include "coap.h" #include "coap-block1.h" -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-block1" +#define LOG_LEVEL LOG_LEVEL_COAP -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /** * \brief Block 1 support within a coap-ressource @@ -77,39 +76,39 @@ * -1 if initialisation failed */ int -coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len) +coap_block1_handler(coap_message_t *request, coap_message_t *response, + uint8_t *target, size_t *len, size_t max_len) { const uint8_t *payload = 0; - int pay_len = REST.get_request_payload(request, &payload); + int pay_len = coap_get_payload(request, &payload); if(!pay_len || !payload) { - erbium_status_code = REST.status.BAD_REQUEST; + coap_status_code = BAD_REQUEST_4_00; coap_error_message = "NoPayload"; return -1; } - coap_packet_t *packet = (coap_packet_t *)request; - - if(packet->block1_offset + pay_len > max_len) { - erbium_status_code = REST.status.REQUEST_ENTITY_TOO_LARGE; + if(request->block1_offset + pay_len > max_len) { + coap_status_code = REQUEST_ENTITY_TOO_LARGE_4_13; coap_error_message = "Message to big"; return -1; } if(target && len) { - memcpy(target + packet->block1_offset, payload, pay_len); - *len = packet->block1_offset + pay_len; + memcpy(target + request->block1_offset, payload, pay_len); + *len = request->block1_offset + pay_len; } - if(IS_OPTION(packet, COAP_OPTION_BLOCK1)) { - PRINTF("Blockwise: block 1 request: Num: %u, More: %u, Size: %u, Offset: %u\n", - packet->block1_num, - packet->block1_more, - packet->block1_size, - packet->block1_offset); + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + LOG_DBG("Blockwise: block 1 request: Num: %"PRIu32 + ", More: %u, Size: %u, Offset: %"PRIu32"\n", + request->block1_num, + request->block1_more, + request->block1_size, + request->block1_offset); - coap_set_header_block1(response, packet->block1_num, packet->block1_more, packet->block1_size); - if(packet->block1_more) { + coap_set_header_block1(response, request->block1_num, request->block1_more, request->block1_size); + if(request->block1_more) { coap_set_status_code(response, CONTINUE_2_31); return 1; } @@ -117,3 +116,5 @@ coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, return 0; } +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-block1.h b/os/net/app-layer/coap/coap-block1.h index a6b1de5ab..50638ef66 100644 --- a/os/net/app-layer/coap/coap-block1.h +++ b/os/net/app-layer/coap/coap-block1.h @@ -36,12 +36,20 @@ * Lars Schmertmann */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_BLOCK1_H_ #define COAP_BLOCK1_H_ +#include "coap.h" #include #include -int coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len); +int coap_block1_handler(coap_message_t *request, coap_message_t *response, + uint8_t *target, size_t *len, size_t max_len); #endif /* COAP_BLOCK1_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-blocking-api.c b/os/net/app-layer/coap/coap-blocking-api.c new file mode 100644 index 000000000..0d2c5dc58 --- /dev/null +++ b/os/net/app-layer/coap/coap-blocking-api.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * CoAP implementation for the REST Engine. + * \author + * Matthias Kovatsch + */ + +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" +#include "coap-blocking-api.h" +#include "sys/cc.h" +#include +#include +#include +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-blocking-api" +#define LOG_LEVEL LOG_LEVEL_COAP + +/*---------------------------------------------------------------------------*/ +/*- Client Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +void +coap_blocking_request_callback(void *callback_data, coap_message_t *response) +{ + coap_request_state_t *state = (coap_request_state_t *)callback_data; + + state->response = response; + process_poll(state->process); +} +/*---------------------------------------------------------------------------*/ +PT_THREAD(coap_blocking_request + (coap_request_state_t *state, process_event_t ev, + coap_endpoint_t *remote_ep, + coap_message_t *request, + coap_blocking_response_handler_t request_callback)) +{ + PT_BEGIN(&state->pt); + + static uint32_t res_block; + static uint8_t more; + static uint8_t block_error; + + state->block_num = 0; + state->response = NULL; + state->process = PROCESS_CURRENT(); + + more = 0; + res_block = 0; + block_error = 0; + + do { + request->mid = coap_get_mid(); + if((state->transaction = coap_new_transaction(request->mid, remote_ep))) { + state->transaction->callback = coap_blocking_request_callback; + state->transaction->callback_data = state; + + if(state->block_num > 0) { + coap_set_header_block2(request, state->block_num, 0, + COAP_MAX_CHUNK_SIZE); + } + state->transaction->message_len = coap_serialize_message(request, + state-> + transaction-> + message); + + coap_send_transaction(state->transaction); + LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid); + + PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL); + + if(!state->response) { + LOG_WARN("Server not responding\n"); + PT_EXIT(&state->pt); + } + + coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); + + LOG_DBG("Received #%"PRIu32"%s (%u bytes)\n", res_block, more ? "+" : "", + state->response->payload_len); + + if(res_block == state->block_num) { + request_callback(state->response); + ++(state->block_num); + } else { + LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n", + res_block, state->block_num); + ++block_error; + } + } else { + LOG_WARN("Could not allocate transaction buffer"); + PT_EXIT(&state->pt); + } + } while(more && block_error < COAP_MAX_ATTEMPTS); + + PT_END(&state->pt); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/ipv6/uip-debug.c b/os/net/app-layer/coap/coap-blocking-api.h old mode 100755 new mode 100644 similarity index 51% rename from os/net/ipv6/uip-debug.c rename to os/net/app-layer/coap/coap-blocking-api.h index f83f0ee5b..d9a916c04 --- a/os/net/ipv6/uip-debug.c +++ b/os/net/app-layer/coap/coap-blocking-api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,65 +26,48 @@ * 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. */ /** - * \file - * A set of debugging tools for the IP stack - * \author - * Nicolas Tsiftes - * Niclas Finne - * Joakim Eriksson + * \addtogroup coap + * @{ */ -#include "net/ipv6/uip-debug.h" -#include "net/ipv6/ip64-addr.h" +#ifndef COAP_BLOCKING_API_H_ +#define COAP_BLOCKING_API_H_ + +#include "sys/pt.h" +#include "coap-transactions.h" /*---------------------------------------------------------------------------*/ -void -uip_debug_ipaddr_print(const uip_ipaddr_t *addr) -{ - uint16_t a; - unsigned int i; - int f; - - if(addr == NULL) { - PRINTA("(NULL IP addr)"); - return; - } - - if(ip64_addr_is_ipv4_mapped_addr(addr)) { - /* - * Printing IPv4-mapped addresses is done according to RFC 4291 [1] - * - * "An alternative form that is sometimes more - * convenient when dealing with a mixed environment - * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, - * where the 'x's are the hexadecimal values of the - * six high-order 16-bit pieces of the address, and - * the 'd's are the decimal values of the four - * low-order 8-bit pieces of the address (standard - * IPv4 representation)." - * - * [1] https://tools.ietf.org/html/rfc4291#page-4 - */ - PRINTA("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]); - } else { - for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { - a = (addr->u8[i] << 8) + addr->u8[i + 1]; - if(a == 0 && f >= 0) { - if(f++ == 0) { - PRINTA("::"); - } - } else { - if(f > 0) { - f = -1; - } else if(i > 0) { - PRINTA(":"); - } - PRINTA("%x", a); - } - } - } -} +/*- Client Part -------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +typedef struct coap_request_state { + struct pt pt; + struct process *process; + coap_transaction_t *transaction; + coap_message_t *response; + uint32_t block_num; +} coap_request_state_t; + +typedef void (* coap_blocking_response_handler_t)(coap_message_t *response); + +PT_THREAD(coap_blocking_request + (coap_request_state_t *state, process_event_t ev, + coap_endpoint_t *remote, + coap_message_t *request, + coap_blocking_response_handler_t request_callback)); + +#define COAP_BLOCKING_REQUEST(server_endpoint, request, chunk_handler) \ + { \ + static coap_request_state_t request_state; \ + PT_SPAWN(process_pt, &request_state.pt, \ + coap_blocking_request(&request_state, ev, \ + server_endpoint, \ + request, chunk_handler) \ + ); \ + } + +#endif /* COAP_BLOCKING_API_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-callback-api.c b/os/net/app-layer/coap/coap-callback-api.c new file mode 100644 index 000000000..652856233 --- /dev/null +++ b/os/net/app-layer/coap/coap-callback-api.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + */ + +/** + * \file + * Callback API for doing CoAP requests + * Adapted from the blocking API + * \author + * Joakim Eriksson, joakime@sics.se + */ + +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" +#include "coap-callback-api.h" +#include "coap-transactions.h" +#include "sys/cc.h" +#include +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-callback-api" +#define LOG_LEVEL LOG_LEVEL_COAP + +/* These should go into the state struct so that we can have multiple + requests */ + +static uint32_t res_block; +static uint8_t more; +static uint8_t block_error; + +static void coap_request_callback(void *callback_data, coap_message_t *response); + +/*---------------------------------------------------------------------------*/ + +static void +progress_request(coap_request_state_t *state) { + coap_message_t *request = state->request; + request->mid = coap_get_mid(); + if((state->transaction = + coap_new_transaction(request->mid, state->remote_endpoint))) { + state->transaction->callback = coap_request_callback; + state->transaction->callback_data = state; + + if(state->block_num > 0) { + coap_set_header_block2(request, state->block_num, 0, + COAP_MAX_CHUNK_SIZE); + } + state->transaction->message_len = + coap_serialize_message(request, state->transaction->message); + + coap_send_transaction(state->transaction); + LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid); + } +} + +/*---------------------------------------------------------------------------*/ + +static void +coap_request_callback(void *callback_data, coap_message_t *response) +{ + coap_request_state_t *state = (coap_request_state_t *)callback_data; + uint32_t res_block1; + + state->response = response; + + LOG_DBG("request callback\n"); + + if(!state->response) { + LOG_WARN("Server not responding giving up...\n"); + state->callback(state); + return; + } + + /* Got a response */ + coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); + coap_get_header_block1(state->response, &res_block1, NULL, NULL, NULL); + + LOG_DBG("Received #%lu%s B1:%lu (%u bytes)\n", + (unsigned long)res_block, (unsigned)more ? "+" : "", + (unsigned long)res_block1, + state->response->payload_len); + + if(res_block == state->block_num) { + /* Call the callback function as we have more data */ + state->callback(state); + /* this is only for counting BLOCK2 blocks.*/ + ++(state->block_num); + } else { + LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n", res_block, state->block_num); + ++block_error; + } + + if(more && block_error < COAP_MAX_ATTEMPTS) { + progress_request(state); + } else { + /* failure - now we give up and notify the callback */ + state->response = NULL; + state->callback(state); + } +} + +/*---------------------------------------------------------------------------*/ + +void +coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, + coap_message_t *request, + void (*callback)(coap_request_state_t *state)) +{ + /* can we have these variables shared between multiple requests? */ + /* ripped from blocking request */ + more = 0; + res_block = 0; + block_error = 0; + + state->block_num = 0; + state->response = NULL; + state->request = request; + state->remote_endpoint = endpoint; + state->callback = callback; + + progress_request(state); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Link.java b/os/net/app-layer/coap/coap-callback-api.h similarity index 57% rename from tools/collect-view/src/org/contikios/contiki/collect/Link.java rename to os/net/app-layer/coap/coap-callback-api.h index 6575801b4..6de7ab587 100644 --- a/tools/collect-view/src/org/contikios/contiki/collect/Link.java +++ b/os/net/app-layer/coap/coap-callback-api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Swedish Institute of Computer Science. + * Copyright (c) 2016, SICS Swedish ICT * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,60 +27,47 @@ * SUCH DAMAGE. * * - * ----------------------------------------------------------------- - * - * Link - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ */ -package org.contikios.contiki.collect; - /** - * + * \file + * Callback API for doing CoAP requests + * Adapted from the blocking API + * \author + * Joakim Eriksson, joakime@sics.se */ -public class Link { - public final Node node; +/** + * \addtogroup coap + * @{ + */ - private double etx; - private int quality = 100; - private long lastActive = 0L; +#ifndef COAP_CALLBACK_API_H_ +#define COAP_CALLBACK_API_H_ - public Link(Node node) { - this.node = node; - this.lastActive = System.currentTimeMillis(); - } +#include "coap-engine.h" +#include "coap-transactions.h" +#include "sys/cc.h" - public Node getNode() { - return node; - } +/*---------------------------------------------------------------------------*/ +/*- Client Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +typedef struct coap_request_state coap_request_state_t; - public int getQuality() { - return quality; - } +struct coap_request_state { + coap_transaction_t *transaction; + coap_message_t *response; + coap_message_t *request; + coap_endpoint_t *remote_endpoint; + uint32_t block_num; + void *user_data; + coap_timer_t coap_timer; + void (*callback)(coap_request_state_t *state); +}; - public void setQuality(int quality) { - this.quality = quality; - } +void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, + coap_message_t *request, + void (*callback)(coap_request_state_t *state)); - public double getETX() { - return etx; - } - - public void setETX(double etx) { - this.etx = etx; - } - - public long getLastActive() { - return lastActive; - } - - public void setLastActive(long time) { - this.lastActive = time; - } - -} +#endif /* COAP_CALLBACK_API_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-conf.h b/os/net/app-layer/coap/coap-conf.h index 2aabc4be4..911017ed8 100644 --- a/os/net/app-layer/coap/coap-conf.h +++ b/os/net/app-layer/coap/coap-conf.h @@ -36,8 +36,33 @@ * Matthias Kovatsch */ -#ifndef ER_COAP_CONF_H_ -#define ER_COAP_CONF_H_ +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_CONF_H_ +#define COAP_CONF_H_ + +#include "contiki.h" + +/* + * The maximum buffer size that is provided for resource responses and must be + * respected due to the limited IP buffer. Larger data must be handled by the + * resource and will be sent chunk-wise through a TCP stream or CoAP blocks. + */ +#ifndef COAP_MAX_CHUNK_SIZE +#ifdef REST_MAX_CHUNK_SIZE +#define COAP_MAX_CHUNK_SIZE REST_MAX_CHUNK_SIZE +#else /* REST_MAX_CHUNK_SIZE */ +#define COAP_MAX_CHUNK_SIZE 64 +#endif /* REST_MAX_CHUNK_SIZE */ +#endif /* COAP_MAX_CHUNK_SIZE */ + +/* Define REST_MAX_CHUNK_SIZE for backward compatibility */ +#ifndef REST_MAX_CHUNK_SIZE +#define REST_MAX_CHUNK_SIZE COAP_MAX_CHUNK_SIZE +#endif /* REST_MAX_CHUNK_SIZE */ /* Features that can be disabled to achieve smaller memory footprint */ #ifndef COAP_LINK_FORMAT_FILTERING @@ -78,4 +103,5 @@ #define COAP_OBSERVE_REFRESH_INTERVAL 20 #endif /* COAP_OBSERVE_REFRESH_INTERVAL */ -#endif /* ER_COAP_CONF_H_ */ +#endif /* COAP_CONF_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-constants.h b/os/net/app-layer/coap/coap-constants.h index cfa73abcf..f73a5b950 100644 --- a/os/net/app-layer/coap/coap-constants.h +++ b/os/net/app-layer/coap/coap-constants.h @@ -36,10 +36,16 @@ * Matthias Kovatsch */ -#ifndef ER_COAP_CONSTANTS_H_ -#define ER_COAP_CONSTANTS_H_ +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_CONSTANTS_H_ +#define COAP_CONSTANTS_H_ #define COAP_DEFAULT_PORT 5683 +#define COAP_DEFAULT_SECURE_PORT 5684 #define COAP_DEFAULT_MAX_AGE 60 #define COAP_RESPONSE_TIMEOUT 3 @@ -163,4 +169,24 @@ typedef enum { APPLICATION_X_OBIX_BINARY = 51 } coap_content_format_t; -#endif /* ER_COAP_CONSTANTS_H_ */ +/** + * Resource flags for allowed methods and special functionalities. + */ +typedef enum { + NO_FLAGS = 0, + + /* methods to handle */ + METHOD_GET = (1 << 0), + METHOD_POST = (1 << 1), + METHOD_PUT = (1 << 2), + METHOD_DELETE = (1 << 3), + + /* special flags */ + HAS_SUB_RESOURCES = (1 << 4), + IS_SEPARATE = (1 << 5), + IS_OBSERVABLE = (1 << 6), + IS_PERIODIC = (1 << 7) +} coap_resource_flags_t; + +#endif /* COAP_CONSTANTS_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-endpoint.h b/os/net/app-layer/coap/coap-endpoint.h new file mode 100644 index 000000000..969791241 --- /dev/null +++ b/os/net/app-layer/coap/coap-endpoint.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016-2018, SICS, Swedish ICT 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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * API to address CoAP endpoints + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap-transport + * @{ + */ + +#ifndef COAP_ENDPOINT_H_ +#define COAP_ENDPOINT_H_ + +#include "contiki.h" +#include + +#ifndef COAP_ENDPOINT_CUSTOM +#include "net/ipv6/uip.h" + +typedef struct { + uip_ipaddr_t ipaddr; + uint16_t port; + uint8_t secure; +} coap_endpoint_t; +#endif /* COAP_ENDPOINT_CUSTOM */ + +/** + * \brief Copy a CoAP endpoint from one memory area to another. + * + * \param dest A pointer to a CoAP endpoint to copy to. + * \param src A pointer to a CoAP endpoint to copy from. + */ +void coap_endpoint_copy(coap_endpoint_t *dest, const coap_endpoint_t *src); + +/** + * \brief Compare two CoAP endpoints. + * + * \param e1 A pointer to the first CoAP endpoint. + * \param e2 A pointer to the second CoAP endpoint. + * \return Non-zero if the endpoints are identical and zero otherwise. + */ +int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2); + +/** + * \brief Print a CoAP endpoint via the logging module. + * + * \param ep A pointer to the CoAP endpoint to log. + */ +void coap_endpoint_log(const coap_endpoint_t *ep); + +/** + * \brief Print a CoAP endpoint. + * + * \param ep A pointer to the CoAP endpoint to print. + */ +void coap_endpoint_print(const coap_endpoint_t *ep); + +/** + * \brief Print a CoAP endpoint to a string. The output is always + * null-terminated unless size is zero. + * + * \param str The string to write to. + * \param size The max number of characters to write. + * \param ep A pointer to the CoAP endpoint to print. + * \return Returns the number of characters needed for the output + * excluding the ending null-terminator or negative if an + * error occurred. + */ +int coap_endpoint_snprint(char *str, size_t size, + const coap_endpoint_t *ep); + +/** + * \brief Parse a CoAP endpoint. + * + * \param text The string to parse. + * \param size The max number of characters in the string. + * \param ep A pointer to the CoAP endpoint to write to. + * \return Returns non-zero if the endpoint was successfully parsed and + * zero otherwise. + */ +int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep); + +/** + * \brief Check if a CoAP endpoint is secure (encrypted). + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns non-zero if the endpoint is secure and zero otherwise. + */ +int coap_endpoint_is_secure(const coap_endpoint_t *ep); + +/** + * \brief Check if a CoAP endpoint is connected. + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns non-zero if the endpoint is connected and zero otherwise. + */ +int coap_endpoint_is_connected(const coap_endpoint_t *ep); + +/** + * \brief Request a connection to a CoAP endpoint. + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns zero if an error occured and non-zero otherwise. + */ +int coap_endpoint_connect(coap_endpoint_t *ep); + +/** + * \brief Request that any connection to a CoAP endpoint is discontinued. + * + * \param ep A pointer to a CoAP endpoint. + */ +void coap_endpoint_disconnect(coap_endpoint_t *ep); + +#endif /* COAP_ENDPOINT_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-engine.c b/os/net/app-layer/coap/coap-engine.c index 8cde3b836..1327cb3e6 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -31,490 +31,484 @@ /** * \file - * CoAP implementation for the REST Engine. + * CoAP implementation Engine. * \author * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" #include "sys/cc.h" +#include "lib/list.h" #include #include +#include #include -#include "coap-engine.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-engine" +#define LOG_LEVEL LOG_LEVEL_COAP -PROCESS(coap_engine, "CoAP Engine"); +static void process_callback(coap_timer_t *t); + +/* + * To be called by HTTP/COAP server as a callback function when a new service + * request appears. This function dispatches the corresponding CoAP service. + */ +static int invoke_coap_resource_service(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset); /*---------------------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static service_callback_t service_cbk = NULL; +LIST(coap_handlers); +LIST(coap_resource_services); +LIST(coap_resource_periodic_services); +static uint8_t is_initialized = 0; /*---------------------------------------------------------------------------*/ -/*- Internal API ------------------------------------------------------------*/ +/*- CoAP service handlers---------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static int -coap_receive(void) +void +coap_add_handler(coap_handler_t *handler) { - erbium_status_code = NO_ERROR; + list_add(coap_handlers, handler); +} +/*---------------------------------------------------------------------------*/ +void +coap_remove_handler(coap_handler_t *handler) +{ + list_remove(coap_handlers, handler); +} +/*---------------------------------------------------------------------------*/ +coap_handler_status_t +coap_call_handlers(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) +{ + coap_handler_status_t status; + coap_handler_t *r; + for(r = list_head(coap_handlers); r != NULL; r = r->next) { + if(r->handler) { + status = r->handler(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + /* Request handled. */ - PRINTF("handle_incoming_data(): received uip_datalen=%u \n", - (uint16_t)uip_datalen()); - - /* static declaration reduces stack peaks and program code size */ - static coap_packet_t message[1]; /* this way the packet can be treated as pointer as usual */ - static coap_packet_t response[1]; - static coap_transaction_t *transaction = NULL; - - if(uip_newdata()) { - - PRINTF("receiving UDP datagram from: "); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF(":%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), - uip_datalen()); - - erbium_status_code = - coap_parse_message(message, uip_appdata, uip_datalen()); - - if(erbium_status_code == NO_ERROR) { - - /*TODO duplicates suppression, if required by application */ - - PRINTF(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, - message->type, message->token_len, message->code, message->mid); - PRINTF(" URL: %.*s\n", message->uri_path_len, message->uri_path); - PRINTF(" Payload: %.*s\n", message->payload_len, message->payload); - - /* handle requests */ - if(message->code >= COAP_GET && message->code <= COAP_DELETE) { - - /* use transaction buffer for response to confirmable request */ - if((transaction = - coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport))) { - uint32_t block_num = 0; - uint16_t block_size = COAP_MAX_BLOCK_SIZE; - uint32_t block_offset = 0; - int32_t new_offset = 0; - - /* prepare response */ - if(message->type == COAP_TYPE_CON) { - /* reliable CON requests are answered with an ACK */ - coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, - message->mid); - } else { - /* unreliable NON requests are answered with a NON as well */ - coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, - coap_get_mid()); - /* mirror token */ - } if(message->token_len) { - coap_set_token(response, message->token, message->token_len); - /* get offset for blockwise transfers */ - } - if(coap_get_header_block2 - (message, &block_num, NULL, &block_size, &block_offset)) { - PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", - block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); - block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE); - new_offset = block_offset; - } - - /* invoke resource handler */ - if(service_cbk) { - - /* call REST framework and check if found and allowed */ - if(service_cbk - (message, response, transaction->packet + COAP_MAX_HEADER_SIZE, - block_size, &new_offset)) { - - if(erbium_status_code == NO_ERROR) { - - /* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */ - - /* resource is unaware of Block1 */ - if(IS_OPTION(message, COAP_OPTION_BLOCK1) - && response->code < BAD_REQUEST_4_00 - && !IS_OPTION(response, COAP_OPTION_BLOCK1)) { - PRINTF("Block1 NOT IMPLEMENTED\n"); - - erbium_status_code = NOT_IMPLEMENTED_5_01; - coap_error_message = "NoBlock1Support"; - - /* client requested Block2 transfer */ - } else if(IS_OPTION(message, COAP_OPTION_BLOCK2)) { - - /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ - if(new_offset == block_offset) { - PRINTF - ("Blockwise: unaware resource with payload length %u/%u\n", - response->payload_len, block_size); - if(block_offset >= response->payload_len) { - PRINTF - ("handle_incoming_data(): block_offset >= response->payload_len\n"); - - response->code = BAD_OPTION_4_02; - coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ - } else { - coap_set_header_block2(response, block_num, - response->payload_len - - block_offset > block_size, - block_size); - coap_set_payload(response, - response->payload + block_offset, - MIN(response->payload_len - - block_offset, block_size)); - } /* if(valid offset) */ - - /* resource provides chunk-wise data */ - } else { - PRINTF("Blockwise: blockwise resource, new offset %ld\n", - new_offset); - coap_set_header_block2(response, block_num, - new_offset != -1 - || response->payload_len > - block_size, block_size); - - if(response->payload_len > block_size) { - coap_set_payload(response, response->payload, - block_size); - } - } /* if(resource aware of blockwise) */ - - /* Resource requested Block2 transfer */ - } else if(new_offset != 0) { - PRINTF - ("Blockwise: no block option for blockwise resource, using block size %u\n", - COAP_MAX_BLOCK_SIZE); - - coap_set_header_block2(response, 0, new_offset != -1, - COAP_MAX_BLOCK_SIZE); - coap_set_payload(response, response->payload, - MIN(response->payload_len, - COAP_MAX_BLOCK_SIZE)); - } /* blockwise transfer handling */ - } /* no errors/hooks */ - /* successful service callback */ - /* serialize response */ - } - if(erbium_status_code == NO_ERROR) { - if((transaction->packet_len = coap_serialize_message(response, - transaction-> - packet)) == - 0) { - erbium_status_code = PACKET_SERIALIZATION_ERROR; - } - } - } else { - erbium_status_code = NOT_IMPLEMENTED_5_01; - coap_error_message = "NoServiceCallbck"; /* no 'a' to fit into 16 bytes */ - } /* if(service callback) */ - } else { - erbium_status_code = SERVICE_UNAVAILABLE_5_03; - coap_error_message = "NoFreeTraBuffer"; - } /* if(transaction buffer) */ - - /* handle responses */ - } else { - - if(message->type == COAP_TYPE_CON && message->code == 0) { - PRINTF("Received Ping\n"); - erbium_status_code = PING_RESPONSE; - } else if(message->type == COAP_TYPE_ACK) { - /* transactions are closed through lookup below */ - PRINTF("Received ACK\n"); - } else if(message->type == COAP_TYPE_RST) { - PRINTF("Received RST\n"); - /* cancel possible subscriptions */ - coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport, message->mid); + /* Check response code before doing observe! */ + if(request->code == COAP_GET) { + coap_observe_handler(NULL, request, response); } - if((transaction = coap_get_transaction_by_mid(message->mid))) { - /* free transaction memory before callback, as it may create a new transaction */ - restful_response_handler callback = transaction->callback; - void *callback_data = transaction->callback_data; - - coap_clear_transaction(transaction); - - /* check if someone registered for the response */ - if(callback) { - callback(callback_data, message); - } - } - /* if(ACKed transaction) */ - transaction = NULL; - -#if COAP_OBSERVE_CLIENT - /* if observe notification */ - if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) - && IS_OPTION(message, COAP_OPTION_OBSERVE)) { - PRINTF("Observe [%u]\n", message->observe); - coap_handle_notification(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - message); - } -#endif /* COAP_OBSERVE_CLIENT */ - } /* request or response */ - } /* parsed correctly */ - - /* if(parsed correctly) */ - if(erbium_status_code == NO_ERROR) { - if(transaction) { - coap_send_transaction(transaction); + return status; } - } else if(erbium_status_code == MANUAL_RESPONSE) { - PRINTF("Clearing transaction for manual response"); - coap_clear_transaction(transaction); - } else { - coap_message_type_t reply_type = COAP_TYPE_ACK; - - PRINTF("ERROR %u: %s\n", erbium_status_code, coap_error_message); - coap_clear_transaction(transaction); - - if(erbium_status_code == PING_RESPONSE) { - erbium_status_code = 0; - reply_type = COAP_TYPE_RST; - } else if(erbium_status_code >= 192) { - /* set to sendable error code */ - erbium_status_code = INTERNAL_SERVER_ERROR_5_00; - /* reuse input buffer for error message */ - } - coap_init_message(message, reply_type, erbium_status_code, - message->mid); - coap_set_payload(message, coap_error_message, - strlen(coap_error_message)); - coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - uip_appdata, coap_serialize_message(message, - uip_appdata)); } } + return COAP_HANDLER_STATUS_CONTINUE; +} +/*---------------------------------------------------------------------------*/ +static CC_INLINE coap_handler_status_t +call_service(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) +{ + coap_handler_status_t status; + status = coap_call_handlers(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + return status; + } + status = invoke_coap_resource_service(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + return status; + } - /* if(new data) */ - return erbium_status_code; -} -/*---------------------------------------------------------------------------*/ -void -coap_init_engine(void) -{ - process_start(&coap_engine, NULL); -} -/*---------------------------------------------------------------------------*/ -void -coap_set_service_callback(service_callback_t callback) -{ - service_cbk = callback; -} -/*---------------------------------------------------------------------------*/ -rest_resource_flags_t -coap_get_rest_method(void *packet) -{ - return (rest_resource_flags_t)(1 << - (((coap_packet_t *)packet)->code - 1)); + coap_set_status_code(response, NOT_FOUND_4_04); + + return COAP_HANDLER_STATUS_CONTINUE; } + /*---------------------------------------------------------------------------*/ /*- Server Part -------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* the discover resource is automatically included for CoAP */ -extern resource_t res_well_known_core; -#ifdef WITH_DTLS -extern resource_t res_dtls; -#endif +extern coap_resource_t res_well_known_core; /*---------------------------------------------------------------------------*/ -PROCESS_THREAD(coap_engine, ev, data) +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +int +coap_receive(const coap_endpoint_t *src, + uint8_t *payload, uint16_t payload_length) { - PROCESS_BEGIN(); - PRINTF("Starting %s receiver...\n", coap_rest_implementation.name); + /* static declaration reduces stack peaks and program code size */ + static coap_message_t message[1]; /* this way the message can be treated as pointer as usual */ + static coap_message_t response[1]; + coap_transaction_t *transaction = NULL; + coap_handler_status_t status; - rest_activate_resource(&res_well_known_core, ".well-known/core"); + coap_status_code = coap_parse_message(message, payload, payload_length); + coap_set_src_endpoint(message, src); - coap_register_as_transaction_handler(); - coap_init_connection(SERVER_LISTEN_PORT); + if(coap_status_code == NO_ERROR) { - while(1) { - PROCESS_YIELD(); + /*TODO duplicates suppression, if required by application */ - if(ev == tcpip_event) { - coap_receive(); - } else if(ev == PROCESS_EVENT_TIMER) { - /* retransmissions are handled here */ - coap_check_transactions(); + LOG_DBG(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, + message->type, message->token_len, message->code, message->mid); + LOG_DBG(" URL:"); + LOG_DBG_COAP_STRING(message->uri_path, message->uri_path_len); + LOG_DBG_("\n"); + LOG_DBG(" Payload: "); + LOG_DBG_COAP_STRING((const char *)message->payload, message->payload_len); + LOG_DBG_("\n"); + + /* handle requests */ + if(message->code >= COAP_GET && message->code <= COAP_DELETE) { + + /* use transaction buffer for response to confirmable request */ + if((transaction = coap_new_transaction(message->mid, src))) { + uint32_t block_num = 0; + uint16_t block_size = COAP_MAX_BLOCK_SIZE; + uint32_t block_offset = 0; + int32_t new_offset = 0; + + /* prepare response */ + if(message->type == COAP_TYPE_CON) { + /* reliable CON requests are answered with an ACK */ + coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, + message->mid); + } else { + /* unreliable NON requests are answered with a NON as well */ + coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, + coap_get_mid()); + /* mirror token */ + } + if(message->token_len) { + coap_set_token(response, message->token, message->token_len); + /* get offset for blockwise transfers */ + } + if(coap_get_header_block2 + (message, &block_num, NULL, &block_size, &block_offset)) { + LOG_DBG("Blockwise: block request %"PRIu32" (%u/%u) @ %"PRIu32" bytes\n", + block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); + block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE); + new_offset = block_offset; + } + + /* call CoAP framework and check if found and allowed */ + status = call_service(message, response, + transaction->message + COAP_MAX_HEADER_SIZE, + block_size, &new_offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + + if(coap_status_code == NO_ERROR) { + + /* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */ + + /* resource is unaware of Block1 */ + if(coap_is_option(message, COAP_OPTION_BLOCK1) + && response->code < BAD_REQUEST_4_00 + && !coap_is_option(response, COAP_OPTION_BLOCK1)) { + LOG_DBG("Block1 NOT IMPLEMENTED\n"); + + coap_status_code = NOT_IMPLEMENTED_5_01; + coap_error_message = "NoBlock1Support"; + + /* client requested Block2 transfer */ + } else if(coap_is_option(message, COAP_OPTION_BLOCK2)) { + + /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ + if(new_offset == block_offset) { + LOG_DBG("Blockwise: unaware resource with payload length %u/%u\n", + response->payload_len, block_size); + if(block_offset >= response->payload_len) { + LOG_DBG("handle_incoming_data(): block_offset >= response->payload_len\n"); + + response->code = BAD_OPTION_4_02; + coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ + } else { + coap_set_header_block2(response, block_num, + response->payload_len - + block_offset > block_size, + block_size); + coap_set_payload(response, + response->payload + block_offset, + MIN(response->payload_len - + block_offset, block_size)); + } /* if(valid offset) */ + + /* resource provides chunk-wise data */ + } else { + LOG_DBG("Blockwise: blockwise resource, new offset %"PRId32"\n", + new_offset); + coap_set_header_block2(response, block_num, + new_offset != -1 + || response->payload_len > + block_size, block_size); + + if(response->payload_len > block_size) { + coap_set_payload(response, response->payload, + block_size); + } + } /* if(resource aware of blockwise) */ + + /* Resource requested Block2 transfer */ + } else if(new_offset != 0) { + LOG_DBG("Blockwise: no block option for blockwise resource, using block size %u\n", + COAP_MAX_BLOCK_SIZE); + + coap_set_header_block2(response, 0, new_offset != -1, + COAP_MAX_BLOCK_SIZE); + coap_set_payload(response, response->payload, + MIN(response->payload_len, + COAP_MAX_BLOCK_SIZE)); + } /* blockwise transfer handling */ + } /* no errors/hooks */ + /* successful service callback */ + /* serialize response */ + } + if(coap_status_code == NO_ERROR) { + if((transaction->message_len = coap_serialize_message(response, + transaction-> + message)) == + 0) { + coap_status_code = PACKET_SERIALIZATION_ERROR; + } + } + } else { + coap_status_code = SERVICE_UNAVAILABLE_5_03; + coap_error_message = "NoFreeTraBuffer"; + } /* if(transaction buffer) */ + + /* handle responses */ + } else { + + if(message->type == COAP_TYPE_CON && message->code == 0) { + LOG_INFO("Received Ping\n"); + coap_status_code = PING_RESPONSE; + } else if(message->type == COAP_TYPE_ACK) { + /* transactions are closed through lookup below */ + LOG_DBG("Received ACK\n"); + } else if(message->type == COAP_TYPE_RST) { + LOG_INFO("Received RST\n"); + /* cancel possible subscriptions */ + coap_remove_observer_by_mid(src, message->mid); + } + + if((transaction = coap_get_transaction_by_mid(message->mid))) { + /* free transaction memory before callback, as it may create a new transaction */ + coap_resource_response_handler_t callback = transaction->callback; + void *callback_data = transaction->callback_data; + + coap_clear_transaction(transaction); + + /* check if someone registered for the response */ + if(callback) { + callback(callback_data, message); + } + } + /* if(ACKed transaction) */ + transaction = NULL; + +#if COAP_OBSERVE_CLIENT + /* if observe notification */ + if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) + && coap_is_option(message, COAP_OPTION_OBSERVE)) { + LOG_DBG("Observe [%"PRId32"]\n", message->observe); + coap_handle_notification(src, message); + } +#endif /* COAP_OBSERVE_CLIENT */ + } /* request or response */ + } /* parsed correctly */ + + /* if(parsed correctly) */ + if(coap_status_code == NO_ERROR) { + if(transaction) { + coap_send_transaction(transaction); } - } /* while (1) */ + } else if(coap_status_code == MANUAL_RESPONSE) { + LOG_DBG("Clearing transaction for manual response"); + coap_clear_transaction(transaction); + } else { + coap_message_type_t reply_type = COAP_TYPE_ACK; - PROCESS_END(); + LOG_WARN("ERROR %u: %s\n", coap_status_code, coap_error_message); + coap_clear_transaction(transaction); + + if(coap_status_code == PING_RESPONSE) { + coap_status_code = 0; + reply_type = COAP_TYPE_RST; + } else if(coap_status_code >= 192) { + /* set to sendable error code */ + coap_status_code = INTERNAL_SERVER_ERROR_5_00; + /* reuse input buffer for error message */ + } + coap_init_message(message, reply_type, coap_status_code, + message->mid); + coap_set_payload(message, coap_error_message, + strlen(coap_error_message)); + coap_sendto(src, payload, coap_serialize_message(message, payload)); + } + + /* if(new data) */ + return coap_status_code; } /*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ void -coap_blocking_request_callback(void *callback_data, void *response) +coap_engine_init(void) { - struct request_state_t *state = (struct request_state_t *)callback_data; - - state->response = (coap_packet_t *)response; - process_poll(state->process); -} -/*---------------------------------------------------------------------------*/ -PT_THREAD(coap_blocking_request - (struct request_state_t *state, process_event_t ev, - uip_ipaddr_t *remote_ipaddr, uint16_t remote_port, - coap_packet_t *request, - blocking_response_handler request_callback)) -{ - PT_BEGIN(&state->pt); - - static uint8_t more; - static uint32_t res_block; - static uint8_t block_error; - - state->block_num = 0; - state->response = NULL; - state->process = PROCESS_CURRENT(); - - more = 0; - res_block = 0; - block_error = 0; - - do { - request->mid = coap_get_mid(); - if((state->transaction = coap_new_transaction(request->mid, remote_ipaddr, - remote_port))) { - state->transaction->callback = coap_blocking_request_callback; - state->transaction->callback_data = state; - - if(state->block_num > 0) { - coap_set_header_block2(request, state->block_num, 0, - REST_MAX_CHUNK_SIZE); - } - state->transaction->packet_len = coap_serialize_message(request, - state-> - transaction-> - packet); - - coap_send_transaction(state->transaction); - PRINTF("Requested #%lu (MID %u)\n", state->block_num, request->mid); - - PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL); - - if(!state->response) { - PRINTF("Server not responding\n"); - PT_EXIT(&state->pt); - } - - coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); - - PRINTF("Received #%lu%s (%u bytes)\n", res_block, more ? "+" : "", - state->response->payload_len); - - if(res_block == state->block_num) { - request_callback(state->response); - ++(state->block_num); - } else { - PRINTF("WRONG BLOCK %lu/%lu\n", res_block, state->block_num); - ++block_error; - } - } else { - PRINTF("Could not allocate transaction buffer"); - PT_EXIT(&state->pt); - } - } while(more && block_error < COAP_MAX_ATTEMPTS); - - PT_END(&state->pt); -} -/*---------------------------------------------------------------------------*/ -/*- REST Engine Interface ---------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -const struct rest_implementation coap_rest_implementation = { - "CoAP-18", - - coap_init_engine, - coap_set_service_callback, - - coap_get_header_uri_path, - coap_get_rest_method, - coap_set_status_code, - - coap_get_header_content_format, - coap_set_header_content_format, - coap_get_header_accept, - coap_get_header_size2, - coap_set_header_size2, - coap_get_header_max_age, - coap_set_header_max_age, - coap_set_header_etag, - coap_get_header_if_match, - coap_get_header_if_none_match, - coap_get_header_uri_host, - coap_set_header_location_path, - - coap_get_payload, - coap_set_payload, - - coap_get_header_uri_query, - coap_get_query_variable, - coap_get_post_variable, - - coap_notify_observers, - coap_observe_handler, - - { - CONTENT_2_05, - CREATED_2_01, - CHANGED_2_04, - DELETED_2_02, - VALID_2_03, - BAD_REQUEST_4_00, - UNAUTHORIZED_4_01, - BAD_OPTION_4_02, - FORBIDDEN_4_03, - NOT_FOUND_4_04, - METHOD_NOT_ALLOWED_4_05, - NOT_ACCEPTABLE_4_06, - REQUEST_ENTITY_TOO_LARGE_4_13, - UNSUPPORTED_MEDIA_TYPE_4_15, - INTERNAL_SERVER_ERROR_5_00, - NOT_IMPLEMENTED_5_01, - BAD_GATEWAY_5_02, - SERVICE_UNAVAILABLE_5_03, - GATEWAY_TIMEOUT_5_04, - PROXYING_NOT_SUPPORTED_5_05 - }, - - { - TEXT_PLAIN, - TEXT_XML, - TEXT_CSV, - TEXT_HTML, - IMAGE_GIF, - IMAGE_JPEG, - IMAGE_PNG, - IMAGE_TIFF, - AUDIO_RAW, - VIDEO_RAW, - APPLICATION_LINK_FORMAT, - APPLICATION_XML, - APPLICATION_OCTET_STREAM, - APPLICATION_RDF_XML, - APPLICATION_SOAP_XML, - APPLICATION_ATOM_XML, - APPLICATION_XMPP_XML, - APPLICATION_EXI, - APPLICATION_FASTINFOSET, - APPLICATION_SOAP_FASTINFOSET, - APPLICATION_JSON, - APPLICATION_X_OBIX_BINARY + /* avoid initializing twice */ + if(is_initialized) { + LOG_DBG("already running - double initialization?\n"); + return; } -}; + is_initialized = 1; + + LOG_INFO("Starting CoAP engine...\n"); + + list_init(coap_handlers); + list_init(coap_resource_services); + list_init(coap_resource_periodic_services); + + coap_activate_resource(&res_well_known_core, ".well-known/core"); + + coap_transport_init(); + coap_init_connection(); +} /*---------------------------------------------------------------------------*/ +/** + * \brief Makes a resource available under the given URI path + * \param resource A pointer to a resource implementation + * \param path The URI path string for this resource + * + * The resource implementation must be imported first using the + * extern keyword. The build system takes care of compiling every + * *.c file in the ./resources/ sub-directory (see example Makefile). + */ +void +coap_activate_resource(coap_resource_t *resource, const char *path) +{ + coap_periodic_resource_t *periodic; + resource->url = path; + list_add(coap_resource_services, resource); + + LOG_INFO("Activating: %s\n", resource->url); + + /* Only add periodic resources with a periodic_handler and a period > 0. */ + if(resource->flags & IS_PERIODIC && resource->periodic + && resource->periodic->periodic_handler + && resource->periodic->period) { + LOG_DBG("Periodic resource: %p (%s)\n", resource->periodic, path); + list_add(coap_resource_periodic_services, resource->periodic); + periodic = resource->periodic; + coap_timer_set_callback(&periodic->periodic_timer, process_callback); + coap_timer_set_user_data(&periodic->periodic_timer, resource); + coap_timer_set(&periodic->periodic_timer, periodic->period); + } +} +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +coap_resource_t * +coap_get_first_resource(void) +{ + return list_head(coap_resource_services); +} +/*---------------------------------------------------------------------------*/ +coap_resource_t * +coap_get_next_resource(coap_resource_t *resource) +{ + return list_item_next(resource); +} +/*---------------------------------------------------------------------------*/ +static int +invoke_coap_resource_service(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset) +{ + uint8_t found = 0; + uint8_t allowed = 1; + + coap_resource_t *resource = NULL; + const char *url = NULL; + int url_len, res_url_len; + + url_len = coap_get_header_uri_path(request, &url); + for(resource = list_head(coap_resource_services); + resource; resource = resource->next) { + + /* if the web service handles that kind of requests and urls matches */ + res_url_len = strlen(resource->url); + if((url_len == res_url_len + || (url_len > res_url_len + && (resource->flags & HAS_SUB_RESOURCES) + && url[res_url_len] == '/')) + && strncmp(resource->url, url, res_url_len) == 0) { + coap_resource_flags_t method = coap_get_method_type(request); + found = 1; + + LOG_INFO("/%s, method %u, resource->flags %u\n", resource->url, + (uint16_t)method, resource->flags); + + if((method & METHOD_GET) && resource->get_handler != NULL) { + /* call handler function */ + resource->get_handler(request, response, buffer, buffer_size, offset); + } else if((method & METHOD_POST) && resource->post_handler != NULL) { + /* call handler function */ + resource->post_handler(request, response, buffer, buffer_size, + offset); + } else if((method & METHOD_PUT) && resource->put_handler != NULL) { + /* call handler function */ + resource->put_handler(request, response, buffer, buffer_size, offset); + } else if((method & METHOD_DELETE) && resource->delete_handler != NULL) { + /* call handler function */ + resource->delete_handler(request, response, buffer, buffer_size, + offset); + } else { + allowed = 0; + coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05); + } + break; + } + } + if(!found) { + coap_set_status_code(response, NOT_FOUND_4_04); + } else if(allowed) { + /* final handler for special flags */ + if(resource->flags & IS_OBSERVABLE) { + coap_observe_handler(resource, request, response); + } + } + return found & allowed; +} +/*---------------------------------------------------------------------------*/ +/* This callback occurs when t is expired */ +static void +process_callback(coap_timer_t *t) +{ + coap_resource_t *resource; + resource = coap_timer_get_user_data(t); + if(resource != NULL && (resource->flags & IS_PERIODIC) + && resource->periodic != NULL && resource->periodic->period) { + LOG_DBG("Periodic: timer expired for /%s (period: %"PRIu32")\n", + resource->url, resource->periodic->period); + + if(!is_initialized) { + /* CoAP has not yet been initialized. */ + } else if(resource->periodic->periodic_handler) { + /* Call the periodic_handler function. */ + resource->periodic->periodic_handler(); + } + + coap_timer_set(t, resource->periodic->period); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-engine.h b/os/net/app-layer/coap/coap-engine.h index 8b3ae1d2c..140ed0211 100644 --- a/os/net/app-layer/coap/coap-engine.h +++ b/os/net/app-layer/coap/coap-engine.h @@ -31,56 +31,148 @@ /** * \file - * CoAP implementation for the REST Engine. + * CoAP engine implementation. * \author * Matthias Kovatsch */ -#ifndef ER_COAP_ENGINE_H_ -#define ER_COAP_ENGINE_H_ +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_ENGINE_H_ +#define COAP_ENGINE_H_ + +typedef struct coap_resource_s coap_resource_t; +typedef struct coap_periodic_resource_s coap_periodic_resource_t; -#include "pt.h" #include "coap.h" +#include "coap-timer.h" + +typedef enum { + COAP_HANDLER_STATUS_CONTINUE, + COAP_HANDLER_STATUS_PROCESSED +} coap_handler_status_t; + +typedef coap_handler_status_t +(* coap_handler_callback_t)(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset); + +typedef struct coap_handler coap_handler_t; + +struct coap_handler { + coap_handler_t *next; + coap_handler_callback_t handler; +}; + +#define COAP_HANDLER(name, handler) \ + coap_handler_t name = { NULL, handler } + +void coap_add_handler(coap_handler_t *handler); +void coap_remove_handler(coap_handler_t *handler); + +void coap_engine_init(void); + +int coap_receive(const coap_endpoint_t *src, + uint8_t *payload, uint16_t payload_length); + +coap_handler_status_t coap_call_handlers(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, + uint16_t buffer_size, + int32_t *offset); +/*---------------------------------------------------------------------------*/ +/* signatures of handler functions */ +typedef void (* coap_resource_handler_t)(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, + uint16_t preferred_size, + int32_t *offset); +typedef void (* coap_resource_periodic_handler_t)(void); +typedef void (* coap_resource_response_handler_t)(void *data, + coap_message_t *response); +typedef void (* coap_resource_trigger_handler_t)(void); + +/* data structure representing a resource in CoAP */ +struct coap_resource_s { + coap_resource_t *next; /* for LIST, points to next resource defined */ + const char *url; /*handled URL */ + coap_resource_flags_t flags; /* handled CoAP methods */ + const char *attributes; /* link-format attributes */ + coap_resource_handler_t get_handler; /* handler function */ + coap_resource_handler_t post_handler; /* handler function */ + coap_resource_handler_t put_handler; /* handler function */ + coap_resource_handler_t delete_handler; /* handler function */ + union { + coap_periodic_resource_t *periodic; /* special data depending on flags */ + coap_resource_trigger_handler_t trigger; + coap_resource_trigger_handler_t resume; + }; +}; + +struct coap_periodic_resource_s { + uint32_t period; + coap_timer_t periodic_timer; + const coap_resource_periodic_handler_t periodic_handler; +}; + +/* + * Macro to define a CoAP resource. + * Resources are statically defined for the sake of efficiency and better memory management. + */ +#define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ + coap_resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } + +#define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ + coap_resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } + +#define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \ + coap_resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } } + +#define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \ + coap_resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } } + +/* + * Macro to define a periodic resource. + * The corresponding [name]_periodic_handler() function will be called every period. + * For instance polling a sensor and publishing a changed value to subscribed clients would be done there. + */ +#define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \ + static coap_periodic_resource_t periodic_##name = { period, { 0 }, periodic_handler }; \ + coap_resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } } + +/*---------------------------------------------------------------------------*/ +/** + * + * \brief Resources wanted to be accessible should be activated with the following code. + * \param resource + * A CoAP resource defined through the RESOURCE macros. + * \param path + * The local URI path where to provide the resource. + */ +void coap_activate_resource(coap_resource_t *resource, const char *path); +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the first of registered CoAP resources. + * \return The first registered CoAP resource or NULL if none exists. + */ +coap_resource_t *coap_get_first_resource(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the next registered CoAP resource. + * \return The next resource or NULL if no more exists. + */ +coap_resource_t *coap_get_next_resource(coap_resource_t *resource); +/*---------------------------------------------------------------------------*/ + #include "coap-transactions.h" #include "coap-observe.h" #include "coap-separate.h" #include "coap-observe-client.h" +#include "coap-transport.h" -#define SERVER_LISTEN_PORT UIP_HTONS(COAP_SERVER_PORT) - -typedef coap_packet_t rest_request_t; -typedef coap_packet_t rest_response_t; - -void coap_init_engine(void); - -/*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -struct request_state_t { - struct pt pt; - struct process *process; - coap_transaction_t *transaction; - coap_packet_t *response; - uint32_t block_num; -}; - -typedef void (*blocking_response_handler)(void *response); - -PT_THREAD(coap_blocking_request - (struct request_state_t *state, process_event_t ev, - uip_ipaddr_t *remote_ipaddr, uint16_t remote_port, - coap_packet_t *request, - blocking_response_handler request_callback)); - -#define COAP_BLOCKING_REQUEST(server_addr, server_port, request, chunk_handler) \ - { \ - static struct request_state_t request_state; \ - PT_SPAWN(process_pt, &request_state.pt, \ - coap_blocking_request(&request_state, ev, \ - server_addr, server_port, \ - request, chunk_handler) \ - ); \ - } -/*---------------------------------------------------------------------------*/ - -#endif /* ER_COAP_ENGINE_H_ */ +#endif /* COAP_ENGINE_H_ */ +/** @} */ diff --git a/os/services/lwm2m/oma-tlv-writer.c b/os/net/app-layer/coap/coap-keystore-simple.c similarity index 57% rename from os/services/lwm2m/oma-tlv-writer.c rename to os/net/app-layer/coap/coap-keystore-simple.c index 2f26a69f6..1eb8737e9 100644 --- a/os/services/lwm2m/oma-tlv-writer.c +++ b/os/net/app-layer/coap/coap-keystore-simple.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2017, RISE SICS AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,61 +29,69 @@ */ /** - * \addtogroup oma-lwm2m - * @{ - * + * \file + * A simple keystore with fixed credentials. + * \author + * Niclas Finne + * Joakim Eriksson */ /** - * \file - * Implementation of the Contiki OMA LWM2M TLV writer - * \author - * Joakim Eriksson - * Niclas Finne + * \addtogroup coap-keystore + * @{ */ -#include "lwm2m-object.h" -#include "oma-tlv.h" +#include "coap-endpoint.h" +#include "coap-keystore.h" +#include + +#ifdef WITH_DTLS +#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY +#ifdef COAP_DTLS_PSK_DEFAULT_KEY /*---------------------------------------------------------------------------*/ -static size_t -write_boolean_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int value) +static int +get_default_psk_info(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info) { - return oma_tlv_write_int32(ctx->resource_id, value != 0 ? 1 : 0, - outbuf, outlen); + if(info != NULL) { + if(info->identity == NULL || info->identity_len == 0) { + /* Identity requested */ + info->identity = (uint8_t *)COAP_DTLS_PSK_DEFAULT_IDENTITY; + info->identity_len = strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY); + return 1; + } + if(info->identity_len != strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY) || + memcmp(info->identity, COAP_DTLS_PSK_DEFAULT_IDENTITY, + info->identity_len) != 0) { + /* Identity not matching */ + return 0; + } + info->key = (uint8_t *)COAP_DTLS_PSK_DEFAULT_KEY; + info->key_len = strlen(COAP_DTLS_PSK_DEFAULT_KEY); + return 1; + } + return 0; } -/*---------------------------------------------------------------------------*/ -static size_t -write_int_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int32_t value) -{ - return oma_tlv_write_int32(ctx->resource_id, value, outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -static size_t -write_float32fix_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, - size_t outlen, int32_t value, int bits) -{ - return oma_tlv_write_float32(ctx->resource_id, value, bits, outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -static size_t -write_string_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - const char *value, size_t stringlen) -{ - oma_tlv_t tlv; - tlv.type = OMA_TLV_TYPE_RESOURCE; - tlv.value = (uint8_t *) value; - tlv.length = (uint32_t) stringlen; - tlv.id = ctx->resource_id; - return oma_tlv_write(&tlv, outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -const lwm2m_writer_t oma_tlv_writer = { - write_int_tlv, - write_string_tlv, - write_float32fix_tlv, - write_boolean_tlv +static const coap_keystore_t simple_key_store = { + .coap_get_psk_info = get_default_psk_info }; /*---------------------------------------------------------------------------*/ +#endif /* COAP_DTLS_PSK_DEFAULT_KEY */ +#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */ +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +void +coap_keystore_simple_init(void) +{ +#ifdef WITH_DTLS +#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY +#ifdef COAP_DTLS_PSK_DEFAULT_KEY + + coap_set_keystore(&simple_key_store); + +#endif /* COAP_DTLS_PSK_DEFAULT_KEY */ +#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */ +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/net/app-layer/coap/coap-keystore-simple.h b/os/net/app-layer/coap/coap-keystore-simple.h new file mode 100644 index 000000000..2252002d4 --- /dev/null +++ b/os/net/app-layer/coap/coap-keystore-simple.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +/** + * \file + * A simple keystore with fixed credentials. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap-keystore + * @{ + */ + +#ifndef COAP_KEYSTORE_SIMPLE_H_ +#define COAP_KEYSTORE_SIMPLE_H_ + +/** + * \brief Registers a simple CoAP DTLS keystore with fixed pre-shared key + * credentials. + * + * The credentials can be configured in project-conf.h as shown in the + * following example: + * + * ~~~~~~~~~~~~~~~{.c} + * #define COAP_DTLS_PSK_DEFAULT_IDENTITY "user" + * #define COAP_DTLS_PSK_DEFAULT_KEY "password" + * ~~~~~~~~~~~~~~~ + */ +void coap_keystore_simple_init(void); + +#endif /* COAP_KEYSTORE_SIMPLE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-keystore.h b/os/net/app-layer/coap/coap-keystore.h new file mode 100644 index 000000000..6a3763d5a --- /dev/null +++ b/os/net/app-layer/coap/coap-keystore.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017, 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +/** + * \file + * API for CoAP keystore + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-keystore CoAP keystore API + * @{ + * + * The CoAP keystore API defines a common interface for retrieving + * authorization information for CoAP/DTLS. + */ + +#ifndef COAP_KEYSTORE_H_ +#define COAP_KEYSTORE_H_ + +#include "coap-endpoint.h" + +/** + * The structure of a CoAP pre-shared key info. + */ +typedef struct { + const uint8_t *identity_hint; + uint16_t identity_hint_len; + const uint8_t *identity; + uint16_t identity_len; + const uint8_t *key; + uint16_t key_len; +} coap_keystore_psk_entry_t; + +/** + * The structure of a CoAP keystore. + * + * The keystore implementation provides a function callback for each type of + * authorization supported. The API currently only specifies a function + * callback for pre-shared keys. + */ +typedef struct { + int (* coap_get_psk_info)(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info); +} coap_keystore_t; + +/** + * \brief Set the CoAP keystore to use by CoAP. + * \param keystore A pointer to a CoAP keystore. + */ +void coap_set_keystore(const coap_keystore_t *keystore); + +#endif /* COAP_KEYSTORE_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-log.c b/os/net/app-layer/coap/coap-log.c new file mode 100644 index 000000000..36f3bc016 --- /dev/null +++ b/os/net/app-layer/coap/coap-log.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, 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 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. + */ + +/** + * \file + * Log support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap + * @{ + */ + +#include "coap-log.h" +/*---------------------------------------------------------------------------*/ +void +coap_log_string(const char *text, size_t len) +{ + int i; + if(text == NULL) { + LOG_OUTPUT("(NULL STR)"); + return; + } + + for(i = 0; i < len && *text != '\0'; i++, text++) { + LOG_OUTPUT("%c", *text); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-log.h b/os/net/app-layer/coap/coap-log.h new file mode 100644 index 000000000..2e6a0a359 --- /dev/null +++ b/os/net/app-layer/coap/coap-log.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017, 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 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. + */ + +/** + * \file + * Log support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_LOG_H_ +#define COAP_LOG_H_ + +#include "contiki.h" + +#ifdef COAP_LOG_CONF_PATH +#include COAP_LOG_CONF_PATH +#else /* COAP_LOG_CONF_PATH */ +#include "sys/log.h" +#endif /* COAP_LOG_CONF_PATH */ + +#include "coap-endpoint.h" + +/* CoAP endpoint */ +#define LOG_COAP_EP(level, endpoint) do { \ + if(level <= (LOG_LEVEL)) { \ + coap_endpoint_log(endpoint); \ + } \ + } while (0) + +#define LOG_ERR_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_ERR, endpoint) +#define LOG_WARN_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_WARN, endpoint) +#define LOG_INFO_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_INFO, endpoint) +#define LOG_DBG_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_DBG, endpoint) + +/* CoAP strings */ +#define LOG_COAP_STRING(level, text, len) do { \ + if(level <= (LOG_LEVEL)) { \ + coap_log_string(text, len); \ + } \ + } while (0) + +#define LOG_ERR_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_ERR, text, len) +#define LOG_WARN_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_WARN, text, len) +#define LOG_INFO_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_INFO, text, len) +#define LOG_DBG_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_DBG, text, len) + +/** + * \brief Logs a CoAP string that has a length but might not be 0-terminated. + * \param text The CoAP string + * \param len The number of characters in the CoAP string + */ +void coap_log_string(const char *text, size_t len); + +#endif /* COAP_LOG_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe-client.c b/os/net/app-layer/coap/coap-observe-client.c index 84edec98e..af1e89f14 100644 --- a/os/net/app-layer/coap/coap-observe-client.c +++ b/os/net/app-layer/coap/coap-observe-client.c @@ -37,57 +37,42 @@ * Daniele Alessandrelli */ -#include -#include +/** + * \addtogroup coap + * @{ + */ #include "coap.h" #include "coap-observe-client.h" +#include "sys/cc.h" +#include "lib/memb.h" +#include "lib/list.h" +#include +#include /* Compile this code only if client-side support for CoAP Observe is required */ #if COAP_OBSERVE_CLIENT -#define DEBUG 1 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \ - "%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \ - ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \ - ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \ - ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \ - ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \ - ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \ - ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \ - ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \ - ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", \ - (lladdr)->addr[0], (lladdr)->addr[1], \ - (lladdr)->addr[2], (lladdr)->addr[3], \ - (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-observe-client" +#define LOG_LEVEL LOG_LEVEL_COAP MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES); LIST(obs_subjects_list); /*----------------------------------------------------------------------------*/ static size_t -get_token(void *packet, const uint8_t **token) +get_token(coap_message_t *coap_pkt, const uint8_t **token) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - *token = coap_pkt->token; return coap_pkt->token_len; } /*----------------------------------------------------------------------------*/ static int -set_token(void *packet, const uint8_t *token, size_t token_len) +set_token(coap_message_t *coap_pkt, const uint8_t *token, size_t token_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); @@ -95,7 +80,7 @@ set_token(void *packet, const uint8_t *token, size_t token_len) } /*----------------------------------------------------------------------------*/ coap_observee_t * -coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, +coap_obs_add_observee(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *url, notification_callback_t notification_callback, void *data) @@ -103,20 +88,18 @@ coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, coap_observee_t *o; /* Remove existing observe relationship, if any. */ - coap_obs_remove_observee_by_url(addr, port, url); + coap_obs_remove_observee_by_url(endpoint, url); o = memb_alloc(&obs_subjects_memb); if(o) { o->url = url; - uip_ipaddr_copy(&o->addr, addr); - o->port = port; + coap_endpoint_copy(&o->endpoint, endpoint); o->token_len = token_len; memcpy(o->token, token, token_len); /* o->last_mid = 0; */ o->notification_callback = notification_callback; o->data = data; - /* stimer_set(&o->refresh_timer, COAP_OBSERVING_REFRESH_INTERVAL); */ - PRINTF("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_DBG("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); list_add(obs_subjects_list, o); } @@ -126,8 +109,8 @@ coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, void coap_obs_remove_observee(coap_observee_t *o) { - PRINTF("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_DBG("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); memb_free(&obs_subjects_memb, o); list_remove(obs_subjects_list, o); } @@ -139,7 +122,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len) for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Looking for token 0x%02X%02X\n", token[0], token[1]); + LOG_DBG("Looking for token 0x%02X%02X\n", token[0], token[1]); if(obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { return obs; @@ -150,7 +133,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len) } /*----------------------------------------------------------------------------*/ int -coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, +coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len) { int removed = 0; @@ -158,9 +141,8 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); - if(uip_ipaddr_cmp(&obs->addr, addr) - && obs->port == port + LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { coap_obs_remove_observee(obs); @@ -171,7 +153,7 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ int -coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, +coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, const char *url) { int removed = 0; @@ -179,9 +161,8 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Remove check URL %s\n", url); - if(uip_ipaddr_cmp(&obs->addr, addr) - && obs->port == port + LOG_DBG("Remove check URL %s\n", url); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) { coap_obs_remove_observee(obs); removed++; @@ -191,34 +172,31 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ static void -simple_reply(coap_message_type_t type, uip_ip6addr_t *addr, uint16_t port, - coap_packet_t *notification) +simple_reply(coap_message_type_t type, const coap_endpoint_t *endpoint, + coap_message_t *notification) { - static coap_packet_t response[1]; + static coap_message_t response[1]; size_t len; coap_init_message(response, type, NO_ERROR, notification->mid); - len = coap_serialize_message(response, uip_appdata); - coap_send_message(addr, port, uip_appdata, len); + len = coap_serialize_message(response, coap_databuf()); + coap_sendto(endpoint, coap_databuf(), len); } /*----------------------------------------------------------------------------*/ static coap_notification_flag_t -classify_notification(void *response, int first) +classify_notification(coap_message_t *response, int first) { - coap_packet_t *pkt; - - pkt = (coap_packet_t *)response; - if(!pkt) { - PRINTF("no response\n"); + if(!response) { + LOG_DBG("no response\n"); return NO_REPLY_FROM_SERVER; } - PRINTF("server replied\n"); - if(!IS_RESPONSE_CODE_2_XX(pkt)) { - PRINTF("error response code\n"); + LOG_DBG("server replied\n"); + if(!IS_RESPONSE_CODE_2_XX(response)) { + LOG_DBG("error response code\n"); return ERROR_RESPONSE_CODE; } - if(!IS_OPTION(pkt, COAP_OPTION_OBSERVE)) { - PRINTF("server does not support observe\n"); + if(!coap_is_option(response, COAP_OPTION_OBSERVE)) { + LOG_DBG("server does not support observe\n"); return OBSERVE_NOT_SUPPORTED; } if(first) { @@ -228,35 +206,33 @@ classify_notification(void *response, int first) } /*----------------------------------------------------------------------------*/ void -coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, - coap_packet_t *notification) +coap_handle_notification(const coap_endpoint_t *endpoint, + coap_message_t *notification) { - coap_packet_t *pkt; const uint8_t *token; int token_len; coap_observee_t *obs; coap_notification_flag_t flag; uint32_t observe; - PRINTF("coap_handle_notification()\n"); - pkt = (coap_packet_t *)notification; - token_len = get_token(pkt, &token); - PRINTF("Getting token\n"); + LOG_DBG("coap_handle_notification()\n"); + token_len = get_token(notification, &token); + LOG_DBG("Getting token\n"); if(0 == token_len) { - PRINTF("Error while handling coap observe notification: " - "no token in message\n"); + LOG_DBG("Error while handling coap observe notification: " + "no token in message\n"); return; } - PRINTF("Getting observee info\n"); + LOG_DBG("Getting observee info\n"); obs = coap_get_obs_subject_by_token(token, token_len); if(NULL == obs) { - PRINTF("Error while handling coap observe notification: " - "no matching token found\n"); - simple_reply(COAP_TYPE_RST, addr, port, notification); + LOG_DBG("Error while handling coap observe notification: " + "no matching token found\n"); + simple_reply(COAP_TYPE_RST, endpoint, notification); return; } if(notification->type == COAP_TYPE_CON) { - simple_reply(COAP_TYPE_ACK, addr, port, notification); + simple_reply(COAP_TYPE_ACK, endpoint, notification); } if(obs->notification_callback != NULL) { flag = classify_notification(notification, 0); @@ -265,7 +241,7 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, if(flag == NOTIFICATION_OK) { coap_get_header_observe(notification, &observe); if(observe == obs->last_observe) { - PRINTF("Discarding duplicate\n"); + LOG_DBG("Discarding duplicate\n"); return; } obs->last_observe = observe; @@ -275,13 +251,13 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ static void -handle_obs_registration_response(void *data, void *response) +handle_obs_registration_response(void *data, coap_message_t *response) { coap_observee_t *obs; notification_callback_t notification_callback; coap_notification_flag_t flag; - PRINTF("handle_obs_registration_response(): "); + LOG_DBG("handle_obs_registration_response()\n"); obs = (coap_observee_t *)data; notification_callback = obs->notification_callback; flag = classify_notification(response, 1); @@ -305,11 +281,11 @@ coap_generate_token(uint8_t **token_ptr) } /*----------------------------------------------------------------------------*/ coap_observee_t * -coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri, +coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, notification_callback_t notification_callback, void *data) { - coap_packet_t request[1]; + coap_message_t request[1]; coap_transaction_t *t; uint8_t *token; uint8_t token_len; @@ -321,22 +297,23 @@ coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri, coap_set_header_observe(request, 0); token_len = coap_generate_token(&token); set_token(request, token, token_len); - t = coap_new_transaction(request->mid, addr, port); + t = coap_new_transaction(request->mid, endpoint); if(t) { - obs = coap_obs_add_observee(addr, port, (uint8_t *)token, token_len, uri, + obs = coap_obs_add_observee(endpoint, (uint8_t *)token, token_len, uri, notification_callback, data); if(obs) { t->callback = handle_obs_registration_response; t->callback_data = obs; - t->packet_len = coap_serialize_message(request, t->packet); + t->message_len = coap_serialize_message(request, t->message); coap_send_transaction(t); } else { - PRINTF("Could not allocate obs_subject resource buffer"); + LOG_DBG("Could not allocate obs_subject resource buffer\n"); coap_clear_transaction(t); } } else { - PRINTF("Could not allocate transaction buffer"); + LOG_DBG("Could not allocate transaction buffer\n"); } return obs; } #endif /* COAP_OBSERVE_CLIENT */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe-client.h b/os/net/app-layer/coap/coap-observe-client.h index c0ea0c5a2..79625caff 100644 --- a/os/net/app-layer/coap/coap-observe-client.h +++ b/os/net/app-layer/coap/coap-observe-client.h @@ -37,6 +37,11 @@ * Daniele Alessandrelli */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_OBSERVING_CLIENT_H_ #define COAP_OBSERVING_CLIENT_H_ @@ -79,8 +84,7 @@ typedef void (*notification_callback_t)(coap_observee_t *subject, struct coap_observee_s { coap_observee_t *next; /* for LIST */ - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; const char *url; uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; @@ -90,7 +94,7 @@ struct coap_observee_s { }; /*----------------------------------------------------------------------------*/ -coap_observee_t *coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, +coap_observee_t *coap_obs_add_observee(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *url, notification_callback_t @@ -101,17 +105,17 @@ void coap_obs_remove_observee(coap_observee_t *o); coap_observee_t *coap_obs_get_observee_by_token(const uint8_t *token, size_t token_len); -int coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, +int coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len); -int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, +int coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, const char *url); -void coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, - coap_packet_t *notification); +void coap_handle_notification(const coap_endpoint_t *endpoint, + coap_message_t *notification); -coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr, - uint16_t port, char *uri, +coap_observee_t *coap_obs_request_registration(const coap_endpoint_t *endpoint, + char *uri, notification_callback_t notification_callback, void *data); @@ -119,3 +123,4 @@ coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr, uint8_t coap_generate_token(uint8_t **token_ptr); #endif /* COAP_OBSERVING_CLIENT_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe.c b/os/net/app-layer/coap/coap-observe.c index 2237e4e25..ac336fbd8 100644 --- a/os/net/app-layer/coap/coap-observe.c +++ b/os/net/app-layer/coap/coap-observe.c @@ -36,21 +36,22 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #include #include #include "coap-observe.h" +#include "coap-engine.h" +#include "lib/memb.h" +#include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-observe" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ MEMB(observers_memb, coap_observer_t, COAP_MAX_OBSERVERS); @@ -59,11 +60,11 @@ LIST(observers_list); /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ static coap_observer_t * -add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, +add_observer(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *uri, int uri_len) { /* Remove existing observe relationship, if any. */ - coap_remove_observer_by_uri(addr, port, uri); + coap_remove_observer_by_uri(endpoint, uri); coap_observer_t *o = memb_alloc(&observers_memb); @@ -74,15 +75,14 @@ add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, } memcpy(o->url, uri, max); o->url[max] = 0; - uip_ipaddr_copy(&o->addr, addr); - o->port = port; + coap_endpoint_copy(&o->endpoint, endpoint); o->token_len = token_len; memcpy(o->token, token, token_len); o->last_mid = 0; - PRINTF("Adding observer (%u/%u) for /%s [0x%02X%02X]\n", - list_length(observers_list) + 1, COAP_MAX_OBSERVERS, - o->url, o->token[0], o->token[1]); + LOG_INFO("Adding observer (%u/%u) for /%s [0x%02X%02X]\n", + list_length(observers_list) + 1, COAP_MAX_OBSERVERS, + o->url, o->token[0], o->token[1]); list_add(observers_list, o); } @@ -94,25 +94,25 @@ add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, void coap_remove_observer(coap_observer_t *o) { - PRINTF("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_INFO("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); memb_free(&observers_memb, o); list_remove(observers_list, o); } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port) +coap_remove_observer_by_client(const coap_endpoint_t *endpoint) { int removed = 0; coap_observer_t *obs = NULL; + LOG_DBG("Remove check client "); + LOG_DBG_COAP_EP(endpoint); + LOG_DBG_("\n"); for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check client "); - PRINT6ADDR(addr); - PRINTF(":%u\n", port); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port) { + if(coap_endpoint_cmp(&obs->endpoint, endpoint)) { coap_remove_observer(obs); removed++; } @@ -121,7 +121,7 @@ coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port) } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, +coap_remove_observer_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len) { int removed = 0; @@ -129,8 +129,8 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port + LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { coap_remove_observer(obs); @@ -141,7 +141,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, +coap_remove_observer_by_uri(const coap_endpoint_t *endpoint, const char *uri) { int removed = 0; @@ -149,9 +149,9 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check URL %p\n", uri); - if((addr == NULL - || (uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port)) + LOG_DBG("Remove check URL %p\n", uri); + if((endpoint == NULL + || (coap_endpoint_cmp(&obs->endpoint, endpoint))) && (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) { coap_remove_observer(obs); removed++; @@ -161,15 +161,15 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) +coap_remove_observer_by_mid(const coap_endpoint_t *endpoint, uint16_t mid) { int removed = 0; coap_observer_t *obs = NULL; for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check MID %u\n", mid); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port + LOG_DBG("Remove check MID %u\n", mid); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->last_mid == mid) { coap_remove_observer(obs); removed++; @@ -181,29 +181,40 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) /*- Notification ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void -coap_notify_observers(resource_t *resource) +coap_notify_observers(coap_resource_t *resource) { coap_notify_observers_sub(resource, NULL); } +/* Can be used either for sub - or when there is not resource - just + a handler */ void -coap_notify_observers_sub(resource_t *resource, const char *subpath) +coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) { /* build notification */ - coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */ - coap_packet_t request[1]; /* this way the packet can be treated as pointer as usual */ + coap_message_t notification[1]; /* this way the message can be treated as pointer as usual */ + coap_message_t request[1]; /* this way the message can be treated as pointer as usual */ coap_observer_t *obs = NULL; int url_len, obs_url_len; char url[COAP_OBSERVER_URL_LEN]; + uint8_t sub_ok = 0; - url_len = strlen(resource->url); - strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1); - if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) { - strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1); + if(resource != NULL) { + url_len = strlen(resource->url); + strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1); + if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) { + strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1); + } + } else if(subpath != NULL) { + strncpy(url, subpath, COAP_OBSERVER_URL_LEN - 1); + } else { + /* No resource, no subpath */ + return; } + /* Ensure url is null terminated because strncpy does not guarantee this */ url[COAP_OBSERVER_URL_LEN - 1] = '\0'; /* url now contains the notify URL that needs to match the observer */ - PRINTF("Observe: Notification from %s\n", url); + LOG_INFO("Notification from %s\n", url); coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0); /* create a "fake" request for the URI */ @@ -212,30 +223,35 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) /* iterate over observers */ url_len = strlen(url); + /* Assumes lazy evaluation... */ + sub_ok = (resource == NULL) || (resource->flags & HAS_SUB_RESOURCES); for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { obs_url_len = strlen(obs->url); /* Do a match based on the parent/sub-resource match so that it is possible to do parent-node observe */ + + /***** TODO fix here so that we handle the notofication correctly ******/ + /* All the new-style ... is assuming that the URL might be within */ if((obs_url_len == url_len || (obs_url_len > url_len - && (resource->flags & HAS_SUB_RESOURCES) + && sub_ok && obs->url[url_len] == '/')) && strncmp(url, obs->url, url_len) == 0) { coap_transaction_t *transaction = NULL; /*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */ - if((transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port))) { + if((transaction = coap_new_transaction(coap_get_mid(), &obs->endpoint))) { if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) { - PRINTF(" Force Confirmable for\n"); + LOG_DBG(" Force Confirmable for\n"); notification->type = COAP_TYPE_CON; } - PRINTF(" Observer "); - PRINT6ADDR(&obs->addr); - PRINTF(":%u\n", obs->port); + LOG_DBG(" Observer "); + LOG_DBG_COAP_EP(&obs->endpoint); + LOG_DBG_("\n"); /* update last MID for RST matching */ obs->last_mid = transaction->mid; @@ -243,9 +259,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) /* prepare response */ notification->mid = transaction->mid; - resource->get_handler(request, notification, - transaction->packet + COAP_MAX_HEADER_SIZE, - REST_MAX_CHUNK_SIZE, NULL); + /* Either old style get_handler or the full handler */ + if(coap_call_handlers(request, notification, transaction->message + + COAP_MAX_HEADER_SIZE, COAP_MAX_CHUNK_SIZE, + NULL) > 0) { + LOG_DBG("Notification on new handlers\n"); + } else { + if(resource != NULL) { + resource->get_handler(request, notification, + transaction->message + COAP_MAX_HEADER_SIZE, + COAP_MAX_CHUNK_SIZE, NULL); + } else { + /* What to do here? */ + notification->code = BAD_REQUEST_4_00; + } + } if(notification->code < BAD_REQUEST_4_00) { coap_set_header_observe(notification, (obs->obs_counter)++); @@ -254,8 +282,8 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) } coap_set_token(notification, obs->token, obs->token_len); - transaction->packet_len = - coap_serialize_message(notification, transaction->packet); + transaction->message_len = + coap_serialize_message(notification, transaction->message); coap_send_transaction(transaction); } @@ -264,16 +292,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) } /*---------------------------------------------------------------------------*/ void -coap_observe_handler(resource_t *resource, void *request, void *response) +coap_observe_handler(coap_resource_t *resource, coap_message_t *coap_req, + coap_message_t *coap_res) { - coap_packet_t *const coap_req = (coap_packet_t *)request; - coap_packet_t *const coap_res = (coap_packet_t *)response; + const coap_endpoint_t *src_ep; coap_observer_t *obs; + LOG_DBG("CoAP observer handler rsc: %d\n", resource != NULL); + if(coap_req->code == COAP_GET && coap_res->code < 128) { /* GET request and response without error code */ - if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) { - if(coap_req->observe == 0) { - obs = add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, + if(coap_is_option(coap_req, COAP_OPTION_OBSERVE)) { + src_ep = coap_get_src_endpoint(coap_req); + if(src_ep == NULL) { + /* No source endpoint, can not add */ + } else if(coap_req->observe == 0) { + obs = add_observer(src_ep, coap_req->token, coap_req->token_len, coap_req->uri_path, coap_req->uri_path_len); if(obs) { @@ -300,11 +333,11 @@ coap_observe_handler(resource_t *resource, void *request, void *response) } else if(coap_req->observe == 1) { /* remove client if it is currently observe */ - coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport, coap_req->token, - coap_req->token_len); + coap_remove_observer_by_token(src_ep, + coap_req->token, coap_req->token_len); } } } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe.h b/os/net/app-layer/coap/coap-observe.h index 7ff2bb502..c276522c5 100644 --- a/os/net/app-layer/coap/coap-observe.h +++ b/os/net/app-layer/coap/coap-observe.h @@ -36,53 +36,49 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_OBSERVE_H_ #define COAP_OBSERVE_H_ #include "coap.h" #include "coap-transactions.h" -#include "stimer.h" +#include "coap-engine.h" #define COAP_OBSERVER_URL_LEN 20 -typedef struct coap_observable { - uint32_t observe_clock; - struct stimer orphan_timer; - list_t observers; - coap_packet_t notification; - uint8_t buffer[COAP_MAX_PACKET_SIZE + 1]; -} coap_observable_t; - typedef struct coap_observer { struct coap_observer *next; /* for LIST */ char url[COAP_OBSERVER_URL_LEN]; - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; uint16_t last_mid; int32_t obs_counter; - struct etimer retrans_timer; + coap_timer_t retrans_timer; uint8_t retrans_counter; } coap_observer_t; -list_t coap_get_observers(void); void coap_remove_observer(coap_observer_t *o); -int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port); -int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_client(const coap_endpoint_t *ep); +int coap_remove_observer_by_token(const coap_endpoint_t *ep, uint8_t *token, size_t token_len); -int coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_uri(const coap_endpoint_t *ep, const char *uri); -int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_mid(const coap_endpoint_t *ep, uint16_t mid); -void coap_notify_observers(resource_t *resource); -void coap_notify_observers_sub(resource_t *resource, const char *subpath); +void coap_notify_observers(coap_resource_t *resource); +void coap_notify_observers_sub(coap_resource_t *resource, const char *subpath); -void coap_observe_handler(resource_t *resource, void *request, - void *response); +void coap_observe_handler(coap_resource_t *resource, coap_message_t *request, + coap_message_t *response); #endif /* COAP_OBSERVE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-res-well-known-core.c b/os/net/app-layer/coap/coap-res-well-known-core.c index 117e362ab..2893925c9 100644 --- a/os/net/app-layer/coap/coap-res-well-known-core.c +++ b/os/net/app-layer/coap/coap-res-well-known-core.c @@ -36,20 +36,19 @@ * Matthias Kovatsch */ -#include -#include "coap-engine.h" +/** + * \addtogroup coap + * @{ + */ -#define DEBUG 0 -#if DEBUG +#include "coap-engine.h" +#include #include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-res-well-known-core" +#define LOG_LEVEL LOG_LEVEL_COAP #define ADD_CHAR_IF_POSSIBLE(char) \ if(strpos >= *offset && bufpos < preferred_size) { \ @@ -67,7 +66,7 @@ + (*offset - (int32_t)strpos > 0 ? \ *offset - (int32_t)strpos : 0)); \ if(bufpos op preferred_size) { \ - PRINTF("res: BREAK at %s (%p)\n", string, resource); \ + LOG_DBG("BREAK at %s (%p)\n", string, resource); \ break; \ } \ } \ @@ -76,14 +75,15 @@ /*---------------------------------------------------------------------------*/ /*- Resource Handlers -------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -void -well_known_core_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +static void +well_known_core_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, + int32_t *offset) { size_t strpos = 0; /* position in overall string (which is larger than the buffer) */ size_t bufpos = 0; /* position within buffer (bytes written) */ size_t tmplen = 0; - resource_t *resource = NULL; + coap_resource_t *resource = NULL; #if COAP_LINK_FORMAT_FILTERING /* For filtering. */ @@ -101,7 +101,9 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, ++value; len -= strlen(filter) + 1; - PRINTF("Filter %s = %.*s\n", filter, len, value); + LOG_DBG("Filter %s = ", filter); + LOG_DBG_COAP_STRING(value, len); + LOG_DBG_("\n"); if(strcmp(filter, "href") == 0 && value[0] == '/') { ++value; @@ -111,10 +113,10 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, lastchar = value[len - 1]; value[len - 1] = '\0'; } -#endif +#endif /* COAP_LINK_FORMAT_FILTERING */ - for(resource = (resource_t *)list_head(rest_get_resources()); resource; - resource = resource->next) { + for(resource = coap_get_first_resource(); resource; + resource = coap_get_next_resource(resource)) { #if COAP_LINK_FORMAT_FILTERING /* Filtering */ if(len) { @@ -135,7 +137,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, end = strchr(attrib, '"'); } - PRINTF("Filter: res has attrib %s (%s)\n", attrib, value); + LOG_DBG("Filter: res has attrib %s (%s)\n", attrib, value); found = attrib; while((found = strstr(found, value)) != NULL) { if(found > end) { @@ -150,17 +152,17 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, if(found == NULL) { continue; } - PRINTF("Filter: res has prefix %s\n", found); + LOG_DBG("Filter: res has prefix %s\n", found); if(lastchar != '*' && (found[len] != '"' && found[len] != ' ' && found[len] != '\0')) { continue; } - PRINTF("Filter: res has match\n"); + LOG_DBG("Filter: res has match\n"); } #endif - PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource, - strpos, (long)*offset, bufpos); + LOG_DBG("/%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource, + strpos, (long)*offset, bufpos); if(strpos > 0) { ADD_CHAR_IF_POSSIBLE(','); @@ -177,28 +179,30 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, /* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */ if(bufpos > preferred_size && strpos - bufpos > *offset) { - PRINTF("res: BREAK at %s (%p)\n", resource->url, resource); + LOG_DBG("BREAK at %s (%p)\n", resource->url, resource); break; } } if(bufpos > 0) { - PRINTF("BUF %zu: %.*s\n", bufpos, (int)bufpos, (char *)buffer); + LOG_DBG("BUF %zu: ", bufpos); + LOG_DBG_COAP_STRING((char *)buffer, bufpos); + LOG_DBG_("\n"); coap_set_payload(response, buffer, bufpos); coap_set_header_content_format(response, APPLICATION_LINK_FORMAT); } else if(strpos > 0) { - PRINTF("well_known_core_handler(): bufpos<=0\n"); + LOG_DBG("well_known_core_handler(): bufpos<=0\n"); coap_set_status_code(response, BAD_OPTION_4_02); coap_set_payload(response, "BlockOutOfScope", 15); } if(resource == NULL) { - PRINTF("res: DONE\n"); + LOG_DBG("DONE\n"); *offset = -1; } else { - PRINTF("res: MORE at %s (%p)\n", resource->url, resource); + LOG_DBG("MORE at %s (%p)\n", resource->url, resource); *offset += preferred_size; } } @@ -206,3 +210,4 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, RESOURCE(res_well_known_core, "ct=40", well_known_core_get_handler, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index 03f95c411..318a4e53d 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -36,23 +36,21 @@ * Matthias Kovatsch */ -#include "sys/cc.h" -#include -#include +/** + * \addtogroup coap + * @{ + */ + +#include "coap.h" #include "coap-separate.h" #include "coap-transactions.h" +#include "sys/cc.h" +#include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-separate" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ /*- Separate Response API ---------------------------------------------------*/ @@ -69,13 +67,13 @@ void coap_separate_reject() { /* TODO: Accept string pointer for custom error message */ - erbium_status_code = SERVICE_UNAVAILABLE_5_03; + coap_status_code = SERVICE_UNAVAILABLE_5_03; coap_error_message = "AlreadyInUse"; } /*----------------------------------------------------------------------------*/ /** * \brief Initiate a separate response with an empty ACK - * \param request The request to accept + * \param coap_req The request to accept * \param separate_store A pointer to the data structure that will store the * relevant information for the response * @@ -85,29 +83,33 @@ coap_separate_reject() * then retry later. */ void -coap_separate_accept(void *request, coap_separate_t *separate_store) +coap_separate_accept(coap_message_t *coap_req, coap_separate_t *separate_store) { - coap_packet_t *const coap_req = (coap_packet_t *)request; coap_transaction_t *const t = coap_get_transaction_by_mid(coap_req->mid); - PRINTF("Separate ACCEPT: /%.*s MID %u\n", coap_req->uri_path_len, - coap_req->uri_path, coap_req->mid); + LOG_DBG("Separate ACCEPT: /"); + LOG_DBG_COAP_STRING(coap_req->uri_path, coap_req->uri_path_len); + LOG_DBG_(" MID %u\n", coap_req->mid); if(t) { /* send separate ACK for CON */ if(coap_req->type == COAP_TYPE_CON) { - coap_packet_t ack[1]; + coap_message_t ack[1]; + const coap_endpoint_t *ep; - /* ACK with empty code (0) */ - coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); - /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */ - coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - (uip_appdata), coap_serialize_message(ack, - uip_appdata)); + ep = coap_get_src_endpoint(coap_req); + if(ep == NULL) { + LOG_ERR("ERROR: no endpoint in request\n"); + } else { + /* ACK with empty code (0) */ + coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); + /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */ + coap_sendto(ep, coap_databuf(), + coap_serialize_message(ack, coap_databuf())); + } } - /* store remote address */ - uip_ipaddr_copy(&separate_store->addr, &t->addr); - separate_store->port = t->port; + /* store remote endpoint address */ + coap_endpoint_copy(&separate_store->endpoint, &t->endpoint); /* store correct response type */ separate_store->type = @@ -124,15 +126,15 @@ coap_separate_accept(void *request, coap_separate_t *separate_store) separate_store->block2_size = coap_req->block2_size > 0 ? MIN(COAP_MAX_BLOCK_SIZE, coap_req->block2_size) : COAP_MAX_BLOCK_SIZE; /* signal the engine to skip automatic response and clear transaction by engine */ - erbium_status_code = MANUAL_RESPONSE; + coap_status_code = MANUAL_RESPONSE; } else { - PRINTF("ERROR: Response transaction for separate request not found!\n"); - erbium_status_code = INTERNAL_SERVER_ERROR_5_00; + LOG_ERR("ERROR: Response transaction for separate request not found!\n"); + coap_status_code = INTERNAL_SERVER_ERROR_5_00; } } /*----------------------------------------------------------------------------*/ void -coap_separate_resume(void *response, coap_separate_t *separate_store, +coap_separate_resume(coap_message_t *response, coap_separate_t *separate_store, uint8_t code) { coap_init_message(response, separate_store->type, code, @@ -147,3 +149,4 @@ coap_separate_resume(void *response, coap_separate_t *separate_store, } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-separate.h b/os/net/app-layer/coap/coap-separate.h index 1a89ed434..97cbdbf92 100644 --- a/os/net/app-layer/coap/coap-separate.h +++ b/os/net/app-layer/coap/coap-separate.h @@ -36,15 +36,20 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_SEPARATE_H_ #define COAP_SEPARATE_H_ #include "coap.h" +#include "coap-engine.h" typedef struct coap_separate { - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; coap_message_type_t type; uint16_t mid; @@ -59,11 +64,14 @@ typedef struct coap_separate { uint16_t block2_size; } coap_separate_t; -int coap_separate_handler(resource_t *resource, void *request, - void *response); +int coap_separate_handler(coap_resource_t *resource, coap_message_t *request, + coap_message_t *response); void coap_separate_reject(void); -void coap_separate_accept(void *request, coap_separate_t *separate_store); -void coap_separate_resume(void *response, coap_separate_t *separate_store, +void coap_separate_accept(coap_message_t *request, + coap_separate_t *separate_store); +void coap_separate_resume(coap_message_t *response, + coap_separate_t *separate_store, uint8_t code); #endif /* COAP_SEPARATE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer-default.c b/os/net/app-layer/coap/coap-timer-default.c new file mode 100644 index 000000000..ad1b30d28 --- /dev/null +++ b/os/net/app-layer/coap/coap-timer-default.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT 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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP timer driver implementation based on Contiki etimers + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap-timer + * @{ + * + * \defgroup coap-timer-default CoAP timer for Contiki-NG + * @{ + * + * This is an implementation of CoAP timer for Contiki-NG. + */ + +#include "coap-timer.h" +#include "sys/clock.h" +#include "sys/etimer.h" +#include "sys/process.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-timer-default" +#define LOG_LEVEL LOG_LEVEL_NONE + +PROCESS(coap_timer_process, "coap timer process"); + +static uint64_t current_time; +static struct etimer timer; +/*---------------------------------------------------------------------------*/ +static void +update_timer(void) +{ + uint64_t remaining; + remaining = coap_timer_time_to_next_expiration(); + LOG_DBG("remaining %lu msec\n", (unsigned long)remaining); + if(remaining == 0) { + /* Run as soon as possible */ + process_poll(&coap_timer_process); + } else { + remaining *= CLOCK_SECOND; + remaining /= 1000; + if(remaining > CLOCK_SECOND * 60) { + /* Make sure the CoAP timer clock is updated at least once per minute */ + remaining = CLOCK_SECOND * 60; + } else if(remaining < 1) { + /* Wait minimum one system clock tick */ + remaining = 1; + } + etimer_set(&timer, (clock_time_t)remaining); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_timer_process, ev, data) +{ + PROCESS_BEGIN(); + + etimer_set(&timer, CLOCK_SECOND); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER || + ev == PROCESS_EVENT_POLL); + + if(coap_timer_run()) { + /* Needs to run again */ + process_poll(&coap_timer_process); + } else { + update_timer(); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +static uint64_t +uptime(void) +{ + static clock_time_t last; + clock_time_t now; + uint64_t diff; + + now = clock_time(); + diff = (clock_time_t)(now - last); + if(diff > 0) { + current_time += (diff * 1000) / CLOCK_SECOND; + last = now; + } + return current_time; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + process_start(&coap_timer_process, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +update(void) +{ + process_poll(&coap_timer_process); +} +/*---------------------------------------------------------------------------*/ +const coap_timer_driver_t coap_timer_default_driver = { + .init = init, + .uptime = uptime, + .update = update, +}; +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer.c b/os/net/app-layer/coap/coap-timer.c new file mode 100644 index 000000000..06a65c7f6 --- /dev/null +++ b/os/net/app-layer/coap/coap-timer.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT 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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP timer implementation. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap-timer + * @{ + */ + +#include "coap-timer.h" +#include "lib/list.h" +#include "sys/cc.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-timer" +#define LOG_LEVEL LOG_LEVEL_NONE + +LIST(timer_list); +static uint8_t is_initialized; +/*---------------------------------------------------------------------------*/ +static void +add_timer(coap_timer_t *timer) +{ + coap_timer_t *n, *l, *p; + + if(!is_initialized) { + /* The coap_timer system has not yet been initialized */ + coap_timer_init(); + } + + LOG_DBG("adding timer %p at %lu\n", timer, + (unsigned long)timer->expiration_time); + + p = list_head(timer_list); + + /* Make sure the timer is not already added to the timer list */ + list_remove(timer_list, timer); + + for(l = NULL, n = list_head(timer_list); n != NULL; l = n, n = n->next) { + if(timer->expiration_time < n->expiration_time) { + list_insert(timer_list, l, timer); + timer = NULL; + break; + } + } + + if(timer != NULL) { + list_insert(timer_list, l, timer); + } + + if(p != list_head(timer_list)) { + /* The next timer to expire has changed so we need to notify the driver */ + COAP_TIMER_DRIVER.update(); + } +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_stop(coap_timer_t *timer) +{ + LOG_DBG("stopping timer %p\n", timer); + + /* Mark timer as expired right now */ + timer->expiration_time = coap_timer_uptime(); + + list_remove(timer_list, timer); +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_set(coap_timer_t *timer, uint64_t time) +{ + timer->expiration_time = coap_timer_uptime() + time; + add_timer(timer); +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_reset(coap_timer_t *timer, uint64_t time) +{ + timer->expiration_time += time; + add_timer(timer); +} +/*---------------------------------------------------------------------------*/ +uint64_t +coap_timer_time_to_next_expiration(void) +{ + uint64_t now; + coap_timer_t *next; + + next = list_head(timer_list); + if(next == NULL) { + /* No pending timers - return a time in the future */ + return 60000; + } + + now = coap_timer_uptime(); + if(now < next->expiration_time) { + return next->expiration_time - now; + } + /* The next timer should already have expired */ + return 0; +} +/*---------------------------------------------------------------------------*/ +int +coap_timer_run(void) +{ + uint64_t now; + coap_timer_t *next; + + /* Always get the current time because it might trigger clock updates */ + now = coap_timer_uptime(); + + next = list_head(timer_list); + if(next == NULL) { + /* No pending timers */ + return 0; + } + + if(next->expiration_time <= now) { + LOG_DBG("timer %p expired at %lu\n", next, (unsigned long)now); + + /* This timer should expire now */ + list_remove(timer_list, next); + + if(next->callback) { + next->callback(next); + } + + /* The next timer has changed */ + COAP_TIMER_DRIVER.update(); + + /* Check if there is another pending timer */ + next = list_head(timer_list); + if(next != NULL && next->expiration_time <= coap_timer_uptime()) { + /* Need to run again */ + return 1; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_init(void) +{ + if(is_initialized) { + return; + } + is_initialized = 1; + list_init(timer_list); + if(COAP_TIMER_DRIVER.init) { + COAP_TIMER_DRIVER.init(); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer.h b/os/net/app-layer/coap/coap-timer.h new file mode 100644 index 000000000..0461232ba --- /dev/null +++ b/os/net/app-layer/coap/coap-timer.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT 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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP timer API. + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-timer CoAP timer API + * @{ + * + * The CoAP timer API defines a common interface for CoAP timer and time functionality. + */ + +#ifndef COAP_TIMER_H_ +#define COAP_TIMER_H_ + +#include "contiki.h" +#include + +typedef struct coap_timer coap_timer_t; +struct coap_timer { + coap_timer_t *next; + void (* callback)(coap_timer_t *); + void *user_data; + uint64_t expiration_time; +}; + +typedef struct { + void (* init)(void); + uint64_t (* uptime)(void); + void (* update)(void); +} coap_timer_driver_t; + +#ifndef COAP_TIMER_DRIVER +#ifdef COAP_TIMER_CONF_DRIVER +#define COAP_TIMER_DRIVER COAP_TIMER_CONF_DRIVER +#else /* COAP_TIMER_CONF_DRIVER */ +#define COAP_TIMER_DRIVER coap_timer_default_driver +#endif /* COAP_TIMER_CONF_DRIVER */ +#endif /* COAP_TIMER_DRIVER */ + +extern const coap_timer_driver_t COAP_TIMER_DRIVER; + +/** + * \brief Get the time since boot in milliseconds. + * \return The number of milliseconds since boot. + */ +static inline uint64_t +coap_timer_uptime(void) +{ + return COAP_TIMER_DRIVER.uptime(); +} + +/** + * \brief Get the time since boot in seconds. + * \return The number of seconds since boot. + */ +static inline uint32_t +coap_timer_seconds(void) +{ + return (uint32_t)(COAP_TIMER_DRIVER.uptime() / 1000); +} + +/** + * \brief Set a callback function to be called when a CoAP timer expires. + * + * \param timer A pointer to a CoAP timer. + * \param callback A callback function. + */ +static inline void +coap_timer_set_callback(coap_timer_t *timer, void (* callback)(coap_timer_t *)) +{ + timer->callback = callback; +} + +/** + * \brief Get user data that has been attached to a CoAP timer. + * + * \param timer A pointer to a CoAP timer. + * \return An opaque pointer to user data or NULL if no user data is + * attached to the timer. + */ +static inline void * +coap_timer_get_user_data(coap_timer_t *timer) +{ + return timer->user_data; +} + +/** + * \brief Attach user data to a CoAP timer. + * + * \param timer A pointer to a CoAP timer. + * \param data An opaque pointer to user data. + */ +static inline void +coap_timer_set_user_data(coap_timer_t *timer, void *data) +{ + timer->user_data = data; +} + +/** + * \brief Check if a CoAP timer has expired. + * + * \param timer A pointer to a CoAP timer. + * \return Non-zero if the timer has expired, zero otherwise. + */ +static inline int +coap_timer_expired(const coap_timer_t *timer) +{ + return timer->expiration_time <= coap_timer_uptime(); +} + +/** + * \brief Stop a pending CoAP timer. + * + * After this function has been called, the timer will be expired + * and will not call the callback function. + * + * \param timer A pointer to a CoAP timer. + */ +void coap_timer_stop(coap_timer_t *timer); + +/** + * \brief Set a CoAP timer to expire after the specified time. + * + * \param timer A pointer to a CoAP timer. + * \param time The time until the timer expires. + */ +void coap_timer_set(coap_timer_t *timer, uint64_t time); + +/** + * \brief Reset a CoAP timer to expire a specified time after the + * last expiration time. + * + * This function sets the CoAP timer to expire the specified time + * after the previous expiration time. If the new expiration time + * has already passed, the timer will expire as soon as possible. + * + * If the timer has not yet expired when this function is called, + * the time until the timer expires will be extended by the + * specified time. + * + * \param timer A pointer to a CoAP timer. + * \param time The time after previous expiration the timer expires. + */ +void coap_timer_reset(coap_timer_t *timer, uint64_t time); + +/** + * Get the time until next CoAP timer expires or 0 if there already exists + * expired timers that have not yet been processed. This function is normally + * never called by application code. + * + * Returns the time to next CoAP timer expires or 0 if unprocessed expired + * timers exists. Returns a time in the future if there are no timers pending. + */ +uint64_t coap_timer_time_to_next_expiration(void); + +/** + * This function must be called periodically by the CoAP timer driver to + * process any expired CoAP timers. This function is normally never called by + * application code. + * + * Returns non-zero if it needs to run again to process more timers. + */ +int coap_timer_run(void); + +/** + * This function initializes the CoAP timer library. It is automatically + * called at first use of a CoAP timer. This function is normally never called + * by application code. + */ +void coap_timer_init(void); + +#endif /* COAP_TIMER_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-transactions.c b/os/net/app-layer/coap/coap-transactions.c index 613557f4d..652737b94 100644 --- a/os/net/app-layer/coap/coap-transactions.c +++ b/os/net/app-layer/coap/coap-transactions.c @@ -36,39 +36,47 @@ * Matthias Kovatsch */ -#include "contiki.h" -#include "contiki-net.h" +/** + * \addtogroup coap + * @{ + */ + #include "coap-transactions.h" #include "coap-observe.h" +#include "coap-timer.h" +#include "lib/memb.h" +#include "lib/list.h" +#include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-transactions" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ MEMB(transactions_memb, coap_transaction_t, COAP_MAX_OPEN_TRANSACTIONS); LIST(transactions_list); -static struct process *transaction_handler_process = NULL; +/*---------------------------------------------------------------------------*/ +static void +coap_retransmit_transaction(coap_timer_t *nt) +{ + coap_transaction_t *t = coap_timer_get_user_data(nt); + if(t == NULL) { + LOG_DBG("No retransmission data in coap_timer!\n"); + return; + } + ++(t->retrans_counter); + LOG_DBG("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); + coap_send_transaction(t); +} +/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -void -coap_register_as_transaction_handler() -{ - transaction_handler_process = PROCESS_CURRENT(); -} coap_transaction_t * -coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) +coap_new_transaction(uint16_t mid, const coap_endpoint_t *endpoint) { coap_transaction_t *t = memb_alloc(&transactions_memb); @@ -77,8 +85,7 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) t->retrans_counter = 0; /* save client address */ - uip_ipaddr_copy(&t->addr, addr); - t->port = port; + coap_endpoint_copy(&t->endpoint, endpoint); list_add(transactions_list, t); /* list itself makes sure same element is not added twice */ } @@ -89,43 +96,40 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) void coap_send_transaction(coap_transaction_t *t) { - PRINTF("Sending transaction %u\n", t->mid); + LOG_DBG("Sending transaction %u\n", t->mid); - coap_send_message(&t->addr, t->port, t->packet, t->packet_len); + coap_sendto(&t->endpoint, t->message, t->message_len); if(COAP_TYPE_CON == - ((COAP_HEADER_TYPE_MASK & t->packet[0]) >> COAP_HEADER_TYPE_POSITION)) { + ((COAP_HEADER_TYPE_MASK & t->message[0]) >> COAP_HEADER_TYPE_POSITION)) { if(t->retrans_counter < COAP_MAX_RETRANSMIT) { /* not timed out yet */ - PRINTF("Keeping transaction %u\n", t->mid); + LOG_DBG("Keeping transaction %u\n", t->mid); if(t->retrans_counter == 0) { - t->retrans_timer.timer.interval = - COAP_RESPONSE_TIMEOUT_TICKS + (random_rand() - % - (clock_time_t) + coap_timer_set_callback(&t->retrans_timer, coap_retransmit_transaction); + coap_timer_set_user_data(&t->retrans_timer, t); + t->retrans_interval = + COAP_RESPONSE_TIMEOUT_TICKS + (rand() % COAP_RESPONSE_TIMEOUT_BACKOFF_MASK); - PRINTF("Initial interval %f\n", - (float)t->retrans_timer.timer.interval / CLOCK_SECOND); + LOG_DBG("Initial interval %lu msec\n", + (unsigned long)t->retrans_interval); } else { - t->retrans_timer.timer.interval <<= 1; /* double */ - PRINTF("Doubled (%u) interval %f\n", t->retrans_counter, - (float)t->retrans_timer.timer.interval / CLOCK_SECOND); + t->retrans_interval <<= 1; /* double */ + LOG_DBG("Doubled (%u) interval %lu s\n", t->retrans_counter, + (unsigned long)(t->retrans_interval / 1000)); } - PROCESS_CONTEXT_BEGIN(transaction_handler_process); - etimer_restart(&t->retrans_timer); /* interval updated above */ - PROCESS_CONTEXT_END(transaction_handler_process); - - t = NULL; + /* interval updated above */ + coap_timer_set(&t->retrans_timer, t->retrans_interval); } else { /* timed out */ - PRINTF("Timeout\n"); - restful_response_handler callback = t->callback; + LOG_DBG("Timeout\n"); + coap_resource_response_handler_t callback = t->callback; void *callback_data = t->callback_data; /* handle observers */ - coap_remove_observer_by_client(&t->addr, t->port); + coap_remove_observer_by_client(&t->endpoint); coap_clear_transaction(t); @@ -142,13 +146,14 @@ void coap_clear_transaction(coap_transaction_t *t) { if(t) { - PRINTF("Freeing transaction %u: %p\n", t->mid, t); + LOG_DBG("Freeing transaction %u: %p\n", t->mid, t); - etimer_stop(&t->retrans_timer); + coap_timer_stop(&t->retrans_timer); list_remove(transactions_list, t); memb_free(&transactions_memb, t); } } +/*---------------------------------------------------------------------------*/ coap_transaction_t * coap_get_transaction_by_mid(uint16_t mid) { @@ -156,24 +161,11 @@ coap_get_transaction_by_mid(uint16_t mid) for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) { if(t->mid == mid) { - PRINTF("Found transaction for MID %u: %p\n", t->mid, t); + LOG_DBG("Found transaction for MID %u: %p\n", t->mid, t); return t; } } return NULL; } /*---------------------------------------------------------------------------*/ -void -coap_check_transactions() -{ - coap_transaction_t *t = NULL; - - for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) { - if(etimer_expired(&t->retrans_timer)) { - ++(t->retrans_counter); - PRINTF("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); - coap_send_transaction(t); - } - } -} -/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-transactions.h b/os/net/app-layer/coap/coap-transactions.h index 49e35c0f2..65334b4eb 100644 --- a/os/net/app-layer/coap/coap-transactions.h +++ b/os/net/app-layer/coap/coap-transactions.h @@ -36,45 +36,48 @@ * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_TRANSACTIONS_H_ #define COAP_TRANSACTIONS_H_ #include "coap.h" +#include "coap-engine.h" +#include "coap-timer.h" /* * Modulo mask (thus +1) for a random number to get the tick number for the random * retransmission time between COAP_RESPONSE_TIMEOUT and COAP_RESPONSE_TIMEOUT*COAP_RESPONSE_RANDOM_FACTOR. */ -#define COAP_RESPONSE_TIMEOUT_TICKS (CLOCK_SECOND * COAP_RESPONSE_TIMEOUT) -#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (long)((CLOCK_SECOND * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1 +#define COAP_RESPONSE_TIMEOUT_TICKS (1000 * COAP_RESPONSE_TIMEOUT) +#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (uint32_t)(((1000 * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1) /* container for transactions with message buffer and retransmission info */ typedef struct coap_transaction { struct coap_transaction *next; /* for LIST */ uint16_t mid; - struct etimer retrans_timer; + coap_timer_t retrans_timer; + uint32_t retrans_interval; uint8_t retrans_counter; - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; - restful_response_handler callback; + coap_resource_response_handler_t callback; void *callback_data; - uint16_t packet_len; - uint8_t packet[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent + uint16_t message_len; + uint8_t message[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent * Use snprintf(buf, len+1, "", ...) to completely fill payload */ } coap_transaction_t; -void coap_register_as_transaction_handler(void); - -coap_transaction_t *coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, - uint16_t port); +coap_transaction_t *coap_new_transaction(uint16_t mid, const coap_endpoint_t *ep); void coap_send_transaction(coap_transaction_t *t); void coap_clear_transaction(coap_transaction_t *t); coap_transaction_t *coap_get_transaction_by_mid(uint16_t mid); -void coap_check_transactions(void); - #endif /* COAP_TRANSACTIONS_H_ */ +/** @} */ diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java b/os/net/app-layer/coap/coap-transport.h similarity index 51% rename from tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java rename to os/net/app-layer/coap/coap-transport.h index ea111795a..3de6f71dc 100644 --- a/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java +++ b/os/net/app-layer/coap/coap-transport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Swedish Institute of Computer Science. + * Copyright (c) 2016-2018, SICS, Swedish ICT AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,33 +25,60 @@ * 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. - * - * - * ----------------------------------------------------------------- - * - * Visualizer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ */ -package org.contikios.contiki.collect; - -import java.awt.Component; - /** - * + * \file + * API for CoAP transport + * \author + * Niclas Finne + * Joakim Eriksson */ -public interface Visualizer { - public String getCategory(); - public String getTitle(); - public Component getPanel(); - public void nodesSelected(Node[] node); - public void nodeAdded(Node node); - public void nodeDataReceived(SensorData sensorData); - public void clearNodeData(); +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-transport CoAP transport API + * @{ + * + * The CoAP transport API defines a common interface for sending/receiving + * CoAP messages. + */ -} +#ifndef COAP_TRANSPORT_H_ +#define COAP_TRANSPORT_H_ + +#include "coap-endpoint.h" + +/** + * \brief Returns a common data buffer that can be used when + * generating CoAP messages for transmission. The buffer + * size is at least COAP_MAX_PACKET_SIZE bytes. + * + * In Contiki-NG, this corresponds to the uIP buffer. + * + * \return A pointer to a data buffer where a CoAP message can be stored. + */ +uint8_t *coap_databuf(void); + +/** + * \brief Send a message to the specified CoAP endpoint + * \param ep A pointer to a CoAP endpoint + * \param data A pointer to data to send + * \param len The size of the data to send + * \return The number of bytes sent or negative if an error occurred. + */ +int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len); + +/** + * \brief Initialize the CoAP transport. + * + * This function initializes the CoAP transport implementation and + * should only be called by the CoAP engine. + */ +void coap_transport_init(void); + +#endif /* COAP_TRANSPORT_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c new file mode 100644 index 000000000..ed881ca8b --- /dev/null +++ b/os/net/app-layer/coap/coap-uip.c @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT 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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP transport implementation for uIPv6 + * \author + * Niclas Finne + * Joakim Eriksson + */ + +/** + * \addtogroup coap-transport + * @{ + * + * \defgroup coap-uip CoAP transport implementation for uIP + * @{ + * + * This is an implementation of CoAP transport and CoAP endpoint over uIP + * with DTLS support. + */ + +#include "contiki.h" +#include "net/ipv6/uip-udp-packet.h" +#include "net/ipv6/uiplib.h" +#include "coap.h" +#include "coap-engine.h" +#include "coap-endpoint.h" +#include "coap-transport.h" +#include "coap-transactions.h" +#include "coap-constants.h" +#include "coap-keystore.h" +#include "coap-keystore-simple.h" + +#if UIP_CONF_IPV6_RPL +#include "rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-uip" +#define LOG_LEVEL LOG_LEVEL_COAP + +#ifdef WITH_DTLS +#include "tinydtls.h" +#include "dtls.h" +#endif /* WITH_DTLS */ + +/* sanity check for configured values */ +#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN) +#error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE" +#endif + +#define SERVER_LISTEN_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define SERVER_LISTEN_SECURE_PORT UIP_HTONS(COAP_DEFAULT_SECURE_PORT) + +/* direct access into the buffer */ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#if NETSTACK_CONF_WITH_IPV6 +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#else +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) +#endif + +#ifdef WITH_DTLS +static dtls_handler_t cb; +static dtls_context_t *dtls_context = NULL; + +static const coap_keystore_t *dtls_keystore = NULL; +static struct uip_udp_conn *dtls_conn = NULL; +#endif /* WITH_DTLS */ + +PROCESS(coap_engine, "CoAP Engine"); + +static struct uip_udp_conn *udp_conn = NULL; + +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_log(const coap_endpoint_t *ep) +{ + if(ep == NULL) { + LOG_OUTPUT("(NULL EP)"); + return; + } + if(ep->secure) { + LOG_OUTPUT("coaps://["); + } else { + LOG_OUTPUT("coap://["); + } + log_6addr(&ep->ipaddr); + LOG_OUTPUT("]:%u", uip_ntohs(ep->port)); +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_print(const coap_endpoint_t *ep) +{ + if(ep == NULL) { + printf("(NULL EP)"); + return; + } + if(ep->secure) { + printf("coaps://["); + } else { + printf("coap://["); + } + uiplib_ipaddr_print(&ep->ipaddr); + printf("]:%u", uip_ntohs(ep->port)); +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep) +{ + int n; + if(buf == NULL || size == 0) { + return 0; + } + if(ep == NULL) { + n = snprintf(buf, size - 1, "(NULL EP)"); + } else { + if(ep->secure) { + n = snprintf(buf, size - 1, "coaps://["); + } else { + n = snprintf(buf, size - 1, "coap://["); + } + if(n < size - 1) { + n += uiplib_ipaddr_snprint(&buf[n], size - n - 1, &ep->ipaddr); + } + if(n < size - 1) { + n += snprintf(&buf[n], size -n - 1, "]:%u", uip_ntohs(ep->port)); + } + } + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_copy(coap_endpoint_t *destination, + const coap_endpoint_t *from) +{ + uip_ipaddr_copy(&destination->ipaddr, &from->ipaddr); + destination->port = from->port; + destination->secure = from->secure; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) +{ + if(!uip_ipaddr_cmp(&e1->ipaddr, &e2->ipaddr)) { + return 0; + } + return e1->port == e2->port && e1->secure == e2->secure; +} +/*---------------------------------------------------------------------------*/ +static int +index_of(const char *data, int offset, int len, uint8_t c) +{ + if(offset < 0) { + return offset; + } + for(; offset < len; offset++) { + if(data[offset] == c) { + return offset; + } + } + return -1; +} +/*---------------------------------------------------------------------------*/ +static int +get_port(const char *inbuf, size_t len, uint32_t *value) +{ + int i; + *value = 0; + for(i = 0; i < len; i++) { + if(inbuf[i] >= '0' && inbuf[i] <= '9') { + *value = *value * 10 + (inbuf[i] - '0'); + } else { + break; + } + } + return i; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) +{ + /* Only IPv6 supported */ + int start = index_of(text, 0, size, '['); + int end = index_of(text, start, size, ']'); + int secure = strncmp((const char *)text, "coaps:", 6) == 0; + uint32_t port; + if(start > 0 && end > start && + uiplib_ipaddrconv((const char *)&text[start], &ep->ipaddr)) { + if(text[end + 1] == ':' && + get_port(text + end + 2, size - end - 2, &port)) { + ep->port = UIP_HTONS(port); + } else if(secure) { + /** + * Secure CoAP should use a different port but for now + * the same port is used. + */ + LOG_DBG("Using secure port (coaps)\n"); + ep->port = SERVER_LISTEN_SECURE_PORT; + ep->secure = 1; + } else { + ep->port = SERVER_LISTEN_PORT; + ep->secure = 0; + } + return 1; + } else { + if(uiplib_ipaddrconv((const char *)&text, &ep->ipaddr)) { + ep->port = SERVER_LISTEN_PORT; + ep->secure = 0; + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static const coap_endpoint_t * +get_src_endpoint(uint8_t secure) +{ + static coap_endpoint_t src; + uip_ipaddr_copy(&src.ipaddr, &UIP_IP_BUF->srcipaddr); + src.port = UIP_UDP_BUF->srcport; + src.secure = secure; + return &src; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_secure(const coap_endpoint_t *ep) +{ + return ep->secure; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_connected(const coap_endpoint_t *ep) +{ +#if UIP_CONF_IPV6_RPL +#ifndef CONTIKI_TARGET_NATIVE + if(rpl_get_any_dag() == NULL) { + return 0; + } +#endif +#endif /* UIP_CONF_IPV6_RPL */ + +#ifdef WITH_DTLS + if(ep != NULL && ep->secure != 0) { + dtls_peer_t *peer; + if(dtls_context == NULL) { + return 0; + } + peer = dtls_get_peer(dtls_context, ep); + if(peer != NULL) { + /* only if handshake is done! */ + LOG_DBG("DTLS peer state for "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_(" is %d (%sconnected)\n", peer->state, + dtls_peer_is_connected(peer) ? "" : "not "); + return dtls_peer_is_connected(peer); + } else { + LOG_DBG("DTLS did not find peer "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); + return 0; + } + } +#endif /* WITH_DTLS */ + + /* Assume connected */ + return 1; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_connect(coap_endpoint_t *ep) +{ + if(ep->secure == 0) { + LOG_DBG("connect to "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); + return 1; + } + +#ifdef WITH_DTLS + LOG_DBG("DTLS connect to "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); + + /* setup all address info here... should be done to connect */ + if(dtls_context) { + dtls_connect(dtls_context, ep); + return 1; + } +#endif /* WITH_DTLS */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_disconnect(coap_endpoint_t *ep) +{ +#ifdef WITH_DTLS + if(ep && ep->secure && dtls_context) { + dtls_close(dtls_context, ep); + } +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +uint8_t * +coap_databuf(void) +{ + return uip_appdata; +} +/*---------------------------------------------------------------------------*/ +void +coap_transport_init(void) +{ + process_start(&coap_engine, NULL); +#ifdef WITH_DTLS + dtls_init(); + +#if COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE + coap_keystore_simple_init(); +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE */ + +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +static void +process_secure_data(void) +{ + LOG_INFO("receiving secure UDP datagram from ["); + LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); + LOG_INFO_("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + uip_datalen()); + + if(dtls_context) { + dtls_handle_message(dtls_context, (coap_endpoint_t *)get_src_endpoint(1), + uip_appdata, uip_datalen()); + } +} +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +static void +process_data(void) +{ + LOG_INFO("receiving UDP datagram from ["); + LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); + LOG_INFO_("]:%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + uip_datalen()); + + coap_receive(get_src_endpoint(0), uip_appdata, uip_datalen()); +} +/*---------------------------------------------------------------------------*/ +int +coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t length) +{ + if(ep == NULL) { + LOG_WARN("failed to send - no endpoint\n"); + return -1; + } + + if(!coap_endpoint_is_connected(ep)) { + LOG_WARN("endpoint "); + LOG_WARN_COAP_EP(ep); + LOG_WARN_(" not connected - dropping packet\n"); + return -1; + } + +#ifdef WITH_DTLS + if(coap_endpoint_is_secure(ep)) { + if(dtls_context) { + int ret; + + ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length); + LOG_INFO("sent DTLS to "); + LOG_INFO_COAP_EP(ep); + if(ret < 0) { + LOG_INFO_(" - error %d\n", ret); + } else { + LOG_INFO_(" %d/%u bytes\n", ret, length); + } + return ret; + } else { + LOG_WARN("no DTLS context\n"); + return -1; + } + } +#endif /* WITH_DTLS */ + + uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port); + LOG_INFO("sent to "); + LOG_INFO_COAP_EP(ep); + LOG_INFO_(" %u bytes\n", length); + return length; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_engine, ev, data) +{ + PROCESS_BEGIN(); + + /* new connection with remote host */ + udp_conn = udp_new(NULL, 0, NULL); + udp_bind(udp_conn, SERVER_LISTEN_PORT); + LOG_INFO("Listening on port %u\n", uip_ntohs(udp_conn->lport)); + +#ifdef WITH_DTLS + /* create new context with app-data */ + dtls_conn = udp_new(NULL, 0, NULL); + if(dtls_conn != NULL) { + udp_bind(dtls_conn, SERVER_LISTEN_SECURE_PORT); + LOG_INFO("DTLS listening on port %u\n", uip_ntohs(dtls_conn->lport)); + dtls_context = dtls_new_context(dtls_conn); + } + if(!dtls_context) { + LOG_WARN("DTLS: cannot create context\n"); + } else { + dtls_set_handler(dtls_context, &cb); + } +#endif /* WITH_DTLS */ + + while(1) { + PROCESS_YIELD(); + + if(ev == tcpip_event) { + if(uip_newdata()) { +#ifdef WITH_DTLS + if(uip_udp_conn == dtls_conn) { + process_secure_data(); + continue; + } +#endif /* WITH_DTLS */ + process_data(); + } + } + } /* while (1) */ + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ + +/* DTLS */ +#ifdef WITH_DTLS + +/* This is input coming from the DTLS code - e.g. de-crypted input from + the other side - peer */ +static int +input_from_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + size_t i; + + if(LOG_DBG_ENABLED) { + LOG_DBG("received DTLS data:"); + for(i = 0; i < len; i++) { + LOG_DBG_("%c", data[i]); + } + LOG_DBG_("\n"); + LOG_DBG("Hex:"); + for(i = 0; i < len; i++) { + LOG_DBG_("%02x", data[i]); + } + LOG_DBG_("\n"); + } + + /* Ensure that the endpoint is tagged as secure */ + session->secure = 1; + + coap_receive(session, data, len); + + return 0; +} + +/* This is output from the DTLS code to be sent to peer (encrypted) */ +static int +output_to_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx); + LOG_DBG("output_to DTLS peer ["); + LOG_DBG_6ADDR(&session->ipaddr); + LOG_DBG_("]:%u %ld bytes\n", uip_ntohs(session->port), (long)len); + uip_udp_packet_sendto(udp_connection, data, len, + &session->ipaddr, session->port); + return len; +} + +/* This defines the key-store set API since we hookup DTLS here */ +void +coap_set_keystore(const coap_keystore_t *keystore) +{ + dtls_keystore = keystore; +} + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *ctx, + const session_t *session, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) +{ + coap_keystore_psk_entry_t ks; + + if(dtls_keystore == NULL) { + LOG_DBG("--- No key store available ---\n"); + return 0; + } + + memset(&ks, 0, sizeof(ks)); + LOG_DBG("---===>>> Getting the Key or ID <<<===---\n"); + switch(type) { + case DTLS_PSK_IDENTITY: + if(id && id_len) { + ks.identity_hint = id; + ks.identity_hint_len = id_len; + LOG_DBG("got psk_identity_hint: '"); + LOG_DBG_COAP_STRING((const char *)id, id_len); + LOG_DBG_("'\n"); + } + + if(dtls_keystore->coap_get_psk_info) { + /* we know that session is a coap endpoint */ + dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.identity == NULL || ks.identity_len == 0) { + LOG_DBG("no psk_identity found\n"); + return 0; + } + + if(result_length < ks.identity_len) { + LOG_DBG("cannot return psk_identity -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.identity, ks.identity_len); + LOG_DBG("psk_identity with %u bytes found\n", ks.identity_len); + return ks.identity_len; + + case DTLS_PSK_KEY: + if(dtls_keystore->coap_get_psk_info) { + ks.identity = id; + ks.identity_len = id_len; + /* we know that session is a coap endpoint */ + dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.key == NULL || ks.key_len == 0) { + LOG_DBG("PSK for unknown id requested, exiting\n"); + return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); + } + + if(result_length < ks.key_len) { + LOG_DBG("cannot return psk -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.key, ks.key_len); + LOG_DBG("psk with %u bytes found\n", ks.key_len); + return ks.key_len; + + default: + LOG_WARN("unsupported key store request type: %d\n", type); + } + + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); +} + + +static dtls_handler_t cb = { + .write = output_to_peer, + .read = input_from_peer, + .event = NULL, +#ifdef DTLS_PSK + .get_psk_info = get_psk_info, +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + /* .get_ecdsa_key = get_ecdsa_key, */ + /* .verify_ecdsa_key = verify_ecdsa_key */ +#endif /* DTLS_ECC */ +}; + +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap.c b/os/net/app-layer/coap/coap.c index bcec49cee..42a2d5cef 100644 --- a/os/net/app-layer/coap/coap.c +++ b/os/net/app-layer/coap/coap.c @@ -34,37 +34,36 @@ * An implementation of the Constrained Application Protocol (RFC). * \author * Matthias Kovatsch + * + * Joakim Eriksson, joakim.eriksson@ri.se + * Niclas Finne, niclas.finne@ri.se */ +/** + * \addtogroup coap + * @{ + */ + + #include -#include -#include "contiki.h" +#include #include "sys/cc.h" -#include "contiki-net.h" #include "coap.h" #include "coap-transactions.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static struct uip_udp_conn *udp_conn = NULL; static uint16_t current_mid = 0; -coap_status_t erbium_status_code = NO_ERROR; -char *coap_error_message = ""; +coap_status_t coap_status_code = NO_ERROR; +const char *coap_error_message = ""; /*---------------------------------------------------------------------------*/ /*- Local helper functions --------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -127,7 +126,7 @@ coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer) buffer[++written] = (length - 13); } - PRINTF("WRITTEN %zu B opt header\n", 1 + written); + LOG_DBG("WRITTEN %zu B opt header\n", 1 + written); return ++written; } @@ -150,8 +149,8 @@ coap_serialize_int_option(unsigned int number, unsigned int current_number, if(0xFFFFFFFF & value) { ++i; } - PRINTF("OPTION %u (delta %u, len %zu)\n", number, number - current_number, - i); + LOG_DBG("OPTION %u (delta %u, len %zu)\n", number, number - current_number, + i); i = coap_set_option_header(number - current_number, i, buffer); @@ -177,8 +176,9 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, { size_t i = 0; - PRINTF("ARRAY type %u, len %zu, full [%.*s]\n", number, length, - (int)length, array); + LOG_DBG("ARRAY type %u, len %zu, full [", number, length); + LOG_DBG_COAP_STRING((const char *)array, length); + LOG_DBG_("]\n"); if(split_char != '\0') { int j; @@ -187,7 +187,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, size_t temp_length; for(j = 0; j <= length + 1; ++j) { - PRINTF("STEP %u/%zu (%c)\n", j, length, array[j]); + LOG_DBG("STEP %u/%zu (%c)\n", j, length, array[j]); if(array[j] == split_char || j == length) { part_end = array + j; temp_length = part_end - part_start; @@ -197,9 +197,10 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, memcpy(&buffer[i], part_start, temp_length); i += temp_length; - PRINTF("OPTION type %u, delta %u, len %zu, part [%.*s]\n", number, - number - current_number, i, (int)temp_length, part_start); - + LOG_DBG("OPTION type %u, delta %u, len %zu, part [", number, + number - current_number, i); + LOG_DBG_COAP_STRING((const char *)part_start, temp_length); + LOG_DBG_("]\n"); ++j; /* skip the splitter */ current_number = number; part_start = array + j; @@ -210,8 +211,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, memcpy(&buffer[i], array, length); i += length; - PRINTF("OPTION type %u, delta %u, len %zu\n", number, - number - current_number, length); + LOG_DBG("OPTION type %u, delta %u, len %zu\n", number, + number - current_number, length); } return i; @@ -276,15 +277,10 @@ coap_get_variable(const char *buffer, size_t length, const char *name, /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void -coap_init_connection(uint16_t port) +coap_init_connection(void) { - /* new connection with remote host */ - udp_conn = udp_new(NULL, 0, NULL); - udp_bind(udp_conn, port); - PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport)); - /* initialize transaction ID */ - current_mid = random_rand(); + current_mid = rand(); } /*---------------------------------------------------------------------------*/ uint16_t @@ -294,13 +290,11 @@ coap_get_mid() } /*---------------------------------------------------------------------------*/ void -coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid) +coap_init_message(coap_message_t *coap_pkt, coap_message_type_t type, + uint8_t code, uint16_t mid) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - /* Important thing */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); + memset(coap_pkt, 0, sizeof(coap_message_t)); coap_pkt->type = type; coap_pkt->code = code; @@ -308,9 +302,8 @@ coap_init_message(void *packet, coap_message_type_t type, uint8_t code, } /*---------------------------------------------------------------------------*/ size_t -coap_serialize_message(void *packet, uint8_t *buffer) +coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; uint8_t *option; unsigned int current_number = 0; @@ -318,7 +311,7 @@ coap_serialize_message(void *packet, uint8_t *buffer) coap_pkt->buffer = buffer; coap_pkt->version = 1; - PRINTF("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); + LOG_DBG("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); /* set header fields */ coap_pkt->buffer[0] = 0x00; @@ -332,27 +325,27 @@ coap_serialize_message(void *packet, uint8_t *buffer) coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8); coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid); - /* empty packet, dont need to do more stuff */ + /* empty message, dont need to do more stuff */ if(!coap_pkt->code) { - PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer); + LOG_DBG_("-Done serializing empty message at %p-\n", coap_pkt->buffer); return 4; } /* set Token */ - PRINTF("Token (len %u)", coap_pkt->token_len); + LOG_DBG_("Token (len %u)", coap_pkt->token_len); option = coap_pkt->buffer + COAP_HEADER_LEN; for(current_number = 0; current_number < coap_pkt->token_len; ++current_number) { - PRINTF(" %02X", coap_pkt->token[current_number]); + LOG_DBG_(" %02X", coap_pkt->token[current_number]); *option = coap_pkt->token[current_number]; ++option; } - PRINTF("-\n"); + LOG_DBG_("-\n"); /* Serialize options */ current_number = 0; - PRINTF("-Serializing options at %p-\n", option); + LOG_DBG("-Serializing options at %p-\n", option); /* The options must be serialized in the order of their number */ COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match, "If-Match"); @@ -370,7 +363,7 @@ coap_serialize_message(void *packet, uint8_t *buffer) "Location-Path"); COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/', "Uri-Path"); - PRINTF("Serialize content format: %d\n", coap_pkt->content_format); + LOG_DBG("Serialize content format: %d\n", coap_pkt->content_format); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format, "Content-Format"); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age"); @@ -388,7 +381,7 @@ coap_serialize_message(void *packet, uint8_t *buffer) "Proxy-Scheme"); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1, "Size1"); - PRINTF("-Done serializing at %p----\n", option); + LOG_DBG("-Done serializing at %p----\n", option); /* Pack payload */ if((option - coap_pkt->buffer) <= COAP_MAX_HEADER_SIZE) { @@ -405,49 +398,26 @@ coap_serialize_message(void *packet, uint8_t *buffer) return 0; } - PRINTF("-Done %u B (header len %u, payload len %u)-\n", - (unsigned int)(coap_pkt->payload_len + option - buffer), - (unsigned int)(option - buffer), - (unsigned int)coap_pkt->payload_len); + LOG_DBG("-Done %u B (header len %u, payload len %u)-\n", + (unsigned int)(coap_pkt->payload_len + option - buffer), + (unsigned int)(option - buffer), + (unsigned int)coap_pkt->payload_len); - PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", - coap_pkt->buffer[0], - coap_pkt->buffer[1], - coap_pkt->buffer[2], - coap_pkt->buffer[3], - coap_pkt->buffer[4], - coap_pkt->buffer[5], coap_pkt->buffer[6], coap_pkt->buffer[7] - ); + LOG_DBG("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", + coap_pkt->buffer[0], coap_pkt->buffer[1], coap_pkt->buffer[2], + coap_pkt->buffer[3], coap_pkt->buffer[4], coap_pkt->buffer[5], + coap_pkt->buffer[6], coap_pkt->buffer[7]); - return (option - buffer) + coap_pkt->payload_len; /* packet length */ -} -/*---------------------------------------------------------------------------*/ -void -coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, - uint16_t length) -{ - /* configure connection to reply to client */ - uip_ipaddr_copy(&udp_conn->ripaddr, addr); - udp_conn->rport = port; - - uip_udp_packet_send(udp_conn, data, length); - - PRINTF("-sent UDP datagram (%u)-\n", length); - - /* restore server socket to allow data from any node */ - memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr)); - udp_conn->rport = 0; + return (option - buffer) + coap_pkt->payload_len; /* message length */ } /*---------------------------------------------------------------------------*/ coap_status_t -coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) +coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; + /* initialize message */ + memset(coap_pkt, 0, sizeof(coap_message_t)); - /* initialize packet */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); - - /* pointer to packet bytes */ + /* pointer to message bytes */ coap_pkt->buffer = data; /* parse header fields */ @@ -473,11 +443,11 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) uint8_t *current_option = data + COAP_HEADER_LEN; memcpy(coap_pkt->token, current_option, coap_pkt->token_len); - PRINTF("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1], - coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4], - coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7] - ); /*FIXME always prints 8 bytes */ + LOG_DBG("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1], + coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4], + coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7] + ); /* FIXME always prints 8 bytes */ /* parse options */ memset(coap_pkt->options, 0, sizeof(coap_pkt->options)); @@ -493,9 +463,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->payload = ++current_option; coap_pkt->payload_len = data_len - (coap_pkt->payload - data); - /* also for receiving, the Erbium upper bound is REST_MAX_CHUNK_SIZE */ - if(coap_pkt->payload_len > REST_MAX_CHUNK_SIZE) { - coap_pkt->payload_len = REST_MAX_CHUNK_SIZE; + /* also for receiving, the Erbium upper bound is COAP_MAX_CHUNK_SIZE */ + if(coap_pkt->payload_len > COAP_MAX_CHUNK_SIZE) { + coap_pkt->payload_len = COAP_MAX_CHUNK_SIZE; /* null-terminate payload */ } coap_pkt->payload[coap_pkt->payload_len] = '\0'; @@ -531,72 +501,74 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) if(current_option + option_length > data + data_len) { /* Malformed CoAP - out of bounds */ - PRINTF("BAD REQUEST: options outside data packet: %u > %u\n", - (unsigned)(current_option + option_length - data), data_len); + LOG_WARN("BAD REQUEST: options outside data message: %u > %u\n", + (unsigned)(current_option + option_length - data), data_len); return BAD_REQUEST_4_00; } - option_number += option_delta; + option_number += option_delta; if(option_number > COAP_OPTION_SIZE1) { /* Malformed CoAP - out of bounds */ - PRINTF("BAD REQUEST: option number too large: %u\n", option_number); + LOG_WARN("BAD REQUEST: option number too large: %u\n", option_number); return BAD_REQUEST_4_00; } - PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta, - option_length); + LOG_DBG("OPTION %u (delta %u, len %zu): ", option_number, option_delta, + option_length); - SET_OPTION(coap_pkt, option_number); + coap_set_option(coap_pkt, option_number); switch(option_number) { case COAP_OPTION_CONTENT_FORMAT: coap_pkt->content_format = coap_parse_int_option(current_option, option_length); - PRINTF("Content-Format [%u]\n", coap_pkt->content_format); + LOG_DBG_("Content-Format [%u]\n", coap_pkt->content_format); break; case COAP_OPTION_MAX_AGE: coap_pkt->max_age = coap_parse_int_option(current_option, option_length); - PRINTF("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age); + LOG_DBG_("Max-Age [%"PRIu32"]\n", coap_pkt->max_age); break; case COAP_OPTION_ETAG: coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length); memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len); - PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], - coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], - coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] - ); /*FIXME always prints 8 bytes */ + LOG_DBG_("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], + coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], + coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] + ); /*FIXME always prints 8 bytes */ break; case COAP_OPTION_ACCEPT: coap_pkt->accept = coap_parse_int_option(current_option, option_length); - PRINTF("Accept [%u]\n", coap_pkt->accept); + LOG_DBG_("Accept [%u]\n", coap_pkt->accept); break; case COAP_OPTION_IF_MATCH: /* TODO support multiple ETags */ coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length); memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len); - PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->if_match_len, coap_pkt->if_match[0], - coap_pkt->if_match[1], coap_pkt->if_match[2], - coap_pkt->if_match[3], coap_pkt->if_match[4], - coap_pkt->if_match[5], coap_pkt->if_match[6], - coap_pkt->if_match[7] - ); /* FIXME always prints 8 bytes */ + LOG_DBG_("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->if_match_len, coap_pkt->if_match[0], + coap_pkt->if_match[1], coap_pkt->if_match[2], + coap_pkt->if_match[3], coap_pkt->if_match[4], + coap_pkt->if_match[5], coap_pkt->if_match[6], + coap_pkt->if_match[7] + ); /* FIXME always prints 8 bytes */ break; case COAP_OPTION_IF_NONE_MATCH: coap_pkt->if_none_match = 1; - PRINTF("If-None-Match\n"); + LOG_DBG_("If-None-Match\n"); break; case COAP_OPTION_PROXY_URI: #if COAP_PROXY_OPTION_PROCESSING coap_pkt->proxy_uri = (char *)current_option; coap_pkt->proxy_uri_len = option_length; -#endif - PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", (int)coap_pkt->proxy_uri_len, - coap_pkt->proxy_uri); +#endif /* COAP_PROXY_OPTION_PROCESSING */ + LOG_DBG_("Proxy-Uri NOT IMPLEMENTED ["); + LOG_DBG_COAP_STRING(coap_pkt->proxy_uri, coap_pkt->proxy_uri_len); + LOG_DBG_("]\n"); + coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; break; @@ -605,8 +577,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->proxy_scheme = (char *)current_option; coap_pkt->proxy_scheme_len = option_length; #endif - PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n", - (int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme); + LOG_DBG_("Proxy-Scheme NOT IMPLEMENTED ["); + LOG_DBG_COAP_STRING(coap_pkt->proxy_scheme, coap_pkt->proxy_scheme_len); + LOG_DBG_("]\n"); coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; break; @@ -614,51 +587,58 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) case COAP_OPTION_URI_HOST: coap_pkt->uri_host = (char *)current_option; coap_pkt->uri_host_len = option_length; - PRINTF("Uri-Host [%.*s]\n", (int)coap_pkt->uri_host_len, - coap_pkt->uri_host); + LOG_DBG_("Uri-Host ["); + LOG_DBG_COAP_STRING(coap_pkt->uri_host, coap_pkt->uri_host_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_URI_PORT: coap_pkt->uri_port = coap_parse_int_option(current_option, option_length); - PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port); + LOG_DBG_("Uri-Port [%u]\n", coap_pkt->uri_port); break; case COAP_OPTION_URI_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, '/'); - PRINTF("Uri-Path [%.*s]\n", (int)coap_pkt->uri_path_len, coap_pkt->uri_path); + LOG_DBG_("Uri-Path ["); + LOG_DBG_COAP_STRING(coap_pkt->uri_path, coap_pkt->uri_path_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_URI_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&'); - PRINTF("Uri-Query [%.*s]\n", (int)coap_pkt->uri_query_len, - coap_pkt->uri_query); + LOG_DBG_("Uri-Query["); + LOG_DBG_COAP_STRING(coap_pkt->uri_query, coap_pkt->uri_query_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_LOCATION_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_path), &(coap_pkt->location_path_len), current_option, option_length, '/'); - PRINTF("Location-Path [%.*s]\n", (int)coap_pkt->location_path_len, - coap_pkt->location_path); + + LOG_DBG_("Location-Path ["); + LOG_DBG_COAP_STRING(coap_pkt->location_path, coap_pkt->location_path_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_LOCATION_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&'); - PRINTF("Location-Query [%.*s]\n", (int)coap_pkt->location_query_len, - coap_pkt->location_query); + LOG_DBG_("Location-Query ["); + LOG_DBG_COAP_STRING(coap_pkt->location_query, coap_pkt->location_query_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_OBSERVE: coap_pkt->observe = coap_parse_int_option(current_option, option_length); - PRINTF("Observe [%lu]\n", (unsigned long)coap_pkt->observe); + LOG_DBG_("Observe [%"PRId32"]\n", coap_pkt->observe); break; case COAP_OPTION_BLOCK2: coap_pkt->block2_num = coap_parse_int_option(current_option, @@ -668,9 +648,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F) << (coap_pkt->block2_num & 0x07); coap_pkt->block2_num >>= 4; - PRINTF("Block2 [%lu%s (%u B/blk)]\n", - (unsigned long)coap_pkt->block2_num, - coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); + LOG_DBG_("Block2 [%lu%s (%u B/blk)]\n", + (unsigned long)coap_pkt->block2_num, + coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); break; case COAP_OPTION_BLOCK1: coap_pkt->block1_num = coap_parse_int_option(current_option, @@ -680,20 +660,20 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F) << (coap_pkt->block1_num & 0x07); coap_pkt->block1_num >>= 4; - PRINTF("Block1 [%lu%s (%u B/blk)]\n", - (unsigned long)coap_pkt->block1_num, - coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); + LOG_DBG_("Block1 [%lu%s (%u B/blk)]\n", + (unsigned long)coap_pkt->block1_num, + coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); break; case COAP_OPTION_SIZE2: coap_pkt->size2 = coap_parse_int_option(current_option, option_length); - PRINTF("Size2 [%lu]\n", (unsigned long)coap_pkt->size2); + LOG_DBG_("Size2 [%"PRIu32"]\n", coap_pkt->size2); break; case COAP_OPTION_SIZE1: coap_pkt->size1 = coap_parse_int_option(current_option, option_length); - PRINTF("Size1 [%lu]\n", (unsigned long)coap_pkt->size1); + LOG_DBG_("Size1 [%"PRIu32"]\n", coap_pkt->size1); break; default: - PRINTF("unknown (%u)\n", option_number); + LOG_DBG_("unknown (%u)\n", option_number); /* check if critical (odd) */ if(option_number & 1) { coap_error_message = "Unsupported critical option"; @@ -703,29 +683,27 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) current_option += option_length; } /* for */ - PRINTF("-Done parsing-------\n"); + LOG_DBG("-Done parsing-------\n"); return NO_ERROR; } /*---------------------------------------------------------------------------*/ -/*- REST Engine API ---------------------------------------------------------*/ +/*- CoAP Engine API ---------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_query_variable(void *packet, const char *name, const char **output) +coap_get_query_variable(coap_message_t *coap_pkt, + const char *name, const char **output) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { + if(coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len, name, output); } return 0; } int -coap_get_post_variable(void *packet, const char *name, const char **output) +coap_get_post_variable(coap_message_t *coap_pkt, + const char *name, const char **output) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(coap_pkt->payload_len) { return coap_get_variable((const char *)coap_pkt->payload, coap_pkt->payload_len, name, output); @@ -734,10 +712,10 @@ coap_get_post_variable(void *packet, const char *name, const char **output) } /*---------------------------------------------------------------------------*/ int -coap_set_status_code(void *packet, unsigned int code) +coap_set_status_code(coap_message_t *message, unsigned int code) { if(code <= 0xFF) { - ((coap_packet_t *)packet)->code = (uint8_t)code; + message->code = (uint8_t)code; return 1; } else { return 0; @@ -745,329 +723,280 @@ coap_set_status_code(void *packet, unsigned int code) } /*---------------------------------------------------------------------------*/ int -coap_set_token(void *packet, const uint8_t *token, size_t token_len) +coap_set_token(coap_message_t *coap_pkt, const uint8_t *token, size_t token_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); return coap_pkt->token_len; } /*---------------------------------------------------------------------------*/ -/*- CoAP REST Implementation API --------------------------------------------*/ +/*- CoAP Implementation API -------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_header_content_format(void *packet, unsigned int *format) +coap_get_header_content_format(coap_message_t *coap_pkt, unsigned int *format) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { return 0; } *format = coap_pkt->content_format; return 1; } int -coap_set_header_content_format(void *packet, unsigned int format) +coap_set_header_content_format(coap_message_t *coap_pkt, unsigned int format) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->content_format = format; - SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT); + coap_set_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_accept(void *packet, unsigned int *accept) +coap_get_header_accept(coap_message_t *coap_pkt, unsigned int *accept) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_ACCEPT)) { return 0; } *accept = coap_pkt->accept; return 1; } int -coap_set_header_accept(void *packet, unsigned int accept) +coap_set_header_accept(coap_message_t *coap_pkt, unsigned int accept) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->accept = accept; - SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT); + coap_set_option(coap_pkt, COAP_OPTION_ACCEPT); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_max_age(void *packet, uint32_t *age) +coap_get_header_max_age(coap_message_t *coap_pkt, uint32_t *age) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_MAX_AGE)) { *age = COAP_DEFAULT_MAX_AGE; } else { *age = coap_pkt->max_age; } return 1; } int -coap_set_header_max_age(void *packet, uint32_t age) +coap_set_header_max_age(coap_message_t *coap_pkt, uint32_t age) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->max_age = age; - SET_OPTION(coap_pkt, COAP_OPTION_MAX_AGE); + coap_set_option(coap_pkt, COAP_OPTION_MAX_AGE); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_etag(void *packet, const uint8_t **etag) +coap_get_header_etag(coap_message_t *coap_pkt, const uint8_t **etag) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { return 0; } *etag = coap_pkt->etag; return coap_pkt->etag_len; } int -coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len) +coap_set_header_etag(coap_message_t *coap_pkt, const uint8_t *etag, size_t etag_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->etag, etag, coap_pkt->etag_len); - SET_OPTION(coap_pkt, COAP_OPTION_ETAG); + coap_set_option(coap_pkt, COAP_OPTION_ETAG); return coap_pkt->etag_len; } /*---------------------------------------------------------------------------*/ /*FIXME support multiple ETags */ int -coap_get_header_if_match(void *packet, const uint8_t **etag) +coap_get_header_if_match(coap_message_t *coap_pkt, const uint8_t **etag) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_IF_MATCH)) { return 0; } *etag = coap_pkt->if_match; return coap_pkt->if_match_len; } int -coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len) +coap_set_header_if_match(coap_message_t *coap_pkt, const uint8_t *etag, size_t etag_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len); - SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH); + coap_set_option(coap_pkt, COAP_OPTION_IF_MATCH); return coap_pkt->if_match_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_if_none_match(void *packet) +coap_get_header_if_none_match(coap_message_t *message) { - return IS_OPTION((coap_packet_t *)packet, - COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; + return coap_is_option(message, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; } int -coap_set_header_if_none_match(void *packet) +coap_set_header_if_none_match(coap_message_t *message) { - SET_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH); + coap_set_option(message, COAP_OPTION_IF_NONE_MATCH); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_proxy_uri(void *packet, const char **uri) +coap_get_header_proxy_uri(coap_message_t *coap_pkt, const char **uri) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_PROXY_URI)) { return 0; } *uri = coap_pkt->proxy_uri; return coap_pkt->proxy_uri_len; } int -coap_set_header_proxy_uri(void *packet, const char *uri) +coap_set_header_proxy_uri(coap_message_t *coap_pkt, const char *uri) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - /*TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide coap-conf define */ + /* TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide coap-conf define */ coap_pkt->proxy_uri = uri; coap_pkt->proxy_uri_len = strlen(uri); - SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI); + coap_set_option(coap_pkt, COAP_OPTION_PROXY_URI); return coap_pkt->proxy_uri_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_host(void *packet, const char **host) +coap_get_header_uri_host(coap_message_t *coap_pkt, const char **host) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_HOST)) { return 0; } *host = coap_pkt->uri_host; return coap_pkt->uri_host_len; } int -coap_set_header_uri_host(void *packet, const char *host) +coap_set_header_uri_host(coap_message_t *coap_pkt, const char *host) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->uri_host = host; coap_pkt->uri_host_len = strlen(host); - SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST); + coap_set_option(coap_pkt, COAP_OPTION_URI_HOST); return coap_pkt->uri_host_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_path(void *packet, const char **path) +coap_get_header_uri_path(coap_message_t *coap_pkt, const char **path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_PATH)) { return 0; } *path = coap_pkt->uri_path; return coap_pkt->uri_path_len; } int -coap_set_header_uri_path(void *packet, const char *path) +coap_set_header_uri_path(coap_message_t *coap_pkt, const char *path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(path[0] == '/') + while(path[0] == '/') { ++path; + } coap_pkt->uri_path = path; coap_pkt->uri_path_len = strlen(path); - SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH); + coap_set_option(coap_pkt, COAP_OPTION_URI_PATH); return coap_pkt->uri_path_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_query(void *packet, const char **query) +coap_get_header_uri_query(coap_message_t *coap_pkt, const char **query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { return 0; } *query = coap_pkt->uri_query; return coap_pkt->uri_query_len; } int -coap_set_header_uri_query(void *packet, const char *query) +coap_set_header_uri_query(coap_message_t *coap_pkt, const char *query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(query[0] == '?') + while(query[0] == '?') { ++query; + } coap_pkt->uri_query = query; coap_pkt->uri_query_len = strlen(query); - SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); + coap_set_option(coap_pkt, COAP_OPTION_URI_QUERY); return coap_pkt->uri_query_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_path(void *packet, const char **path) +coap_get_header_location_path(coap_message_t *coap_pkt, const char **path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_PATH)) { return 0; } *path = coap_pkt->location_path; return coap_pkt->location_path_len; } int -coap_set_header_location_path(void *packet, const char *path) +coap_set_header_location_path(coap_message_t *coap_pkt, const char *path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - char *query; - while(path[0] == '/') + while(path[0] == '/') { ++path; + } if((query = strchr(path, '?'))) { - coap_set_header_location_query(packet, query + 1); + coap_set_header_location_query(coap_pkt, query + 1); coap_pkt->location_path_len = query - path; } else { coap_pkt->location_path_len = strlen(path); } coap_pkt->location_path = path; if(coap_pkt->location_path_len > 0) { - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH); + coap_set_option(coap_pkt, COAP_OPTION_LOCATION_PATH); } return coap_pkt->location_path_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_query(void *packet, const char **query) +coap_get_header_location_query(coap_message_t *coap_pkt, const char **query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { return 0; } *query = coap_pkt->location_query; return coap_pkt->location_query_len; } int -coap_set_header_location_query(void *packet, const char *query) +coap_set_header_location_query(coap_message_t *coap_pkt, const char *query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(query[0] == '?') + while(query[0] == '?') { ++query; + } coap_pkt->location_query = query; coap_pkt->location_query_len = strlen(query); - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY); + coap_set_option(coap_pkt, COAP_OPTION_LOCATION_QUERY); return coap_pkt->location_query_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_observe(void *packet, uint32_t *observe) +coap_get_header_observe(coap_message_t *coap_pkt, uint32_t *observe) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { return 0; } *observe = coap_pkt->observe; return 1; } int -coap_set_header_observe(void *packet, uint32_t observe) +coap_set_header_observe(coap_message_t *coap_pkt, uint32_t observe) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->observe = observe; - SET_OPTION(coap_pkt, COAP_OPTION_OBSERVE); + coap_set_option(coap_pkt, COAP_OPTION_OBSERVE); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, +coap_get_header_block2(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK2)) { return 0; } /* pointers may be NULL to get only specific block parameters */ @@ -1086,11 +1015,9 @@ coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block2(void *packet, uint32_t num, uint8_t more, +coap_set_header_block2(coap_message_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(size < 16) { return 0; } @@ -1104,17 +1031,15 @@ coap_set_header_block2(void *packet, uint32_t num, uint8_t more, coap_pkt->block2_more = more ? 1 : 0; coap_pkt->block2_size = size; - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK2); + coap_set_option(coap_pkt, COAP_OPTION_BLOCK2); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, +coap_get_header_block1(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK1)) { return 0; } /* pointers may be NULL to get only specific block parameters */ @@ -1133,11 +1058,9 @@ coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block1(void *packet, uint32_t num, uint8_t more, +coap_set_header_block1(coap_message_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(size < 16) { return 0; } @@ -1151,57 +1074,47 @@ coap_set_header_block1(void *packet, uint32_t num, uint8_t more, coap_pkt->block1_more = more; coap_pkt->block1_size = size; - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK1); + coap_set_option(coap_pkt, COAP_OPTION_BLOCK1); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_size2(void *packet, uint32_t *size) +coap_get_header_size2(coap_message_t *coap_pkt, uint32_t *size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE2)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE2)) { return 0; } *size = coap_pkt->size2; return 1; } int -coap_set_header_size2(void *packet, uint32_t size) +coap_set_header_size2(coap_message_t *coap_pkt, uint32_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->size2 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE2); + coap_set_option(coap_pkt, COAP_OPTION_SIZE2); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_size1(void *packet, uint32_t *size) +coap_get_header_size1(coap_message_t *coap_pkt, uint32_t *size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE1)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE1)) { return 0; } *size = coap_pkt->size1; return 1; } int -coap_set_header_size1(void *packet, uint32_t size) +coap_set_header_size1(coap_message_t *coap_pkt, uint32_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->size1 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE1); + coap_set_option(coap_pkt, COAP_OPTION_SIZE1); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_payload(void *packet, const uint8_t **payload) +coap_get_payload(coap_message_t *coap_pkt, const uint8_t **payload) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(coap_pkt->payload) { *payload = coap_pkt->payload; return coap_pkt->payload_len; @@ -1211,13 +1124,12 @@ coap_get_payload(void *packet, const uint8_t **payload) } } int -coap_set_payload(void *packet, const void *payload, size_t length) +coap_set_payload(coap_message_t *coap_pkt, const void *payload, size_t length) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->payload = (uint8_t *)payload; - coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length); + coap_pkt->payload_len = MIN(COAP_MAX_CHUNK_SIZE, length); return coap_pkt->payload_len; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap.h b/os/net/app-layer/coap/coap.h index 616f67d5c..8d9aed61c 100644 --- a/os/net/app-layer/coap/coap.h +++ b/os/net/app-layer/coap/coap.h @@ -31,53 +31,51 @@ /** * \file - * An implementation of the Constrained Application Protocol (RFC). + * An implementation of the Constrained Application Protocol (RFC 7252). * \author * Matthias Kovatsch */ -#ifndef ER_COAP_H_ -#define ER_COAP_H_ +/** + * \addtogroup apps + * @{ + * + * \defgroup coap An implementation of CoAP + * @{ + * + * This is an implementation of the Constrained Application Protocol + */ + +#ifndef COAP_H_ +#define COAP_H_ #include /* for size_t */ -#include "contiki-net.h" #include "coap-constants.h" #include "coap-conf.h" +#include "coap-transport.h" -/* sanity check for configured values */ -#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + REST_MAX_CHUNK_SIZE) -#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN) -#error "UIP_CONF_BUFFER_SIZE too small for REST_MAX_CHUNK_SIZE" -#endif +/** + * \brief The max size of the CoAP messages + */ +#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + COAP_MAX_CHUNK_SIZE) -/* use Erbium CoAP for the REST Engine. Must come before include of rest-engine.h. */ -#define REST coap_rest_implementation -#include "rest-engine.h" - -/* REST_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */ +/* COAP_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */ #ifndef COAP_MAX_BLOCK_SIZE -#define COAP_MAX_BLOCK_SIZE (REST_MAX_CHUNK_SIZE < 32 ? 16 : \ - (REST_MAX_CHUNK_SIZE < 64 ? 32 : \ - (REST_MAX_CHUNK_SIZE < 128 ? 64 : \ - (REST_MAX_CHUNK_SIZE < 256 ? 128 : \ - (REST_MAX_CHUNK_SIZE < 512 ? 256 : \ - (REST_MAX_CHUNK_SIZE < 1024 ? 512 : \ - (REST_MAX_CHUNK_SIZE < 2048 ? 1024 : 2048))))))) +#define COAP_MAX_BLOCK_SIZE (COAP_MAX_CHUNK_SIZE < 32 ? 16 : \ + (COAP_MAX_CHUNK_SIZE < 64 ? 32 : \ + (COAP_MAX_CHUNK_SIZE < 128 ? 64 : \ + (COAP_MAX_CHUNK_SIZE < 256 ? 128 : \ + (COAP_MAX_CHUNK_SIZE < 512 ? 256 : \ + (COAP_MAX_CHUNK_SIZE < 1024 ? 512 : \ + (COAP_MAX_CHUNK_SIZE < 2048 ? 1024 : 2048))))))) #endif /* COAP_MAX_BLOCK_SIZE */ -/* direct access into the buffer */ -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) - /* bitmap for set options */ -enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 }; - -#define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE)) -#define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) +#define COAP_OPTION_MAP_SIZE (sizeof(uint8_t) * 8) /* parsed message struct */ typedef struct { - uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */ + uint8_t *buffer; /* pointer to CoAP header / incoming message buffer / memory to serialize message */ uint8_t version; coap_message_type_t type; @@ -87,7 +85,7 @@ typedef struct { uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; - uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */ + uint8_t options[COAP_OPTION_SIZE1 / COAP_OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */ uint16_t content_format; /* parse options once and store; allows setting options in random order */ uint32_t max_age; @@ -124,20 +122,39 @@ typedef struct { const char *uri_query; uint8_t if_none_match; + const coap_endpoint_t *src_ep; + uint16_t payload_len; uint8_t *payload; -} coap_packet_t; +} coap_message_t; + +static inline int +coap_set_option(coap_message_t *message, unsigned int opt) +{ + if(opt > COAP_OPTION_SIZE1) { + return 0; + } + message->options[opt / COAP_OPTION_MAP_SIZE] |= 1 << (opt % COAP_OPTION_MAP_SIZE); + return 1; +} + +static inline int +coap_is_option(const coap_message_t *message, unsigned int opt) +{ + return (opt <= COAP_OPTION_SIZE1) && + (message->options[opt / COAP_OPTION_MAP_SIZE] & (1 << (opt % COAP_OPTION_MAP_SIZE))) != 0; +} /* option format serialization */ #define COAP_SERIALIZE_INT_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " [%u]\n", (unsigned int)coap_pkt->field); \ option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \ current_number = number; \ } #define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \ coap_pkt->field[0], \ coap_pkt->field[1], \ coap_pkt->field[2], \ @@ -150,110 +167,138 @@ typedef struct { option += coap_serialize_array_option(number, current_number, option, coap_pkt->field, coap_pkt->field##_len, '\0'); \ current_number = number; \ } -#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%.*s]\n", (int)coap_pkt->field##_len, coap_pkt->field); \ +#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " ["); \ + LOG_DBG_COAP_STRING(coap_pkt->field, coap_pkt->field##_len); \ + LOG_DBG_("]\n"); \ option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \ current_number = number; \ } #define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) \ - { \ - PRINTF(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ uint32_t block = coap_pkt->field##_num << 4; \ if(coap_pkt->field##_more) { block |= 0x8; } \ block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \ - PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \ + LOG_DBG(text " encoded: 0x%lX\n", (unsigned long)block); \ option += coap_serialize_int_option(number, current_number, option, block); \ current_number = number; \ } /* to store error code and human-readable payload */ -extern coap_status_t erbium_status_code; -extern char *coap_error_message; +extern coap_status_t coap_status_code; +extern const char *coap_error_message; -void coap_init_connection(uint16_t port); +void coap_init_connection(void); uint16_t coap_get_mid(void); -void coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid); -size_t coap_serialize_message(void *packet, uint8_t *buffer); -void coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, - uint16_t length); -coap_status_t coap_parse_message(void *request, uint8_t *data, +void coap_init_message(coap_message_t *message, coap_message_type_t type, + uint8_t code, uint16_t mid); +size_t coap_serialize_message(coap_message_t *message, uint8_t *buffer); +coap_status_t coap_parse_message(coap_message_t *request, uint8_t *data, uint16_t data_len); -int coap_get_query_variable(void *packet, const char *name, +int coap_get_query_variable(coap_message_t *message, const char *name, const char **output); -int coap_get_post_variable(void *packet, const char *name, +int coap_get_post_variable(coap_message_t *message, const char *name, const char **output); +static inline coap_resource_flags_t +coap_get_method_type(coap_message_t *message) +{ + return (coap_resource_flags_t)(1 << (message->code - 1)); +} + +static inline const coap_endpoint_t * +coap_get_src_endpoint(coap_message_t *request) +{ + return request->src_ep; +} + +static inline void +coap_set_src_endpoint(coap_message_t *request, const coap_endpoint_t *ep) +{ + request->src_ep = ep; +} /*---------------------------------------------------------------------------*/ -int coap_set_status_code(void *packet, unsigned int code); +int coap_set_status_code(coap_message_t *message, unsigned int code); -int coap_set_token(void *packet, const uint8_t *token, size_t token_len); +int coap_set_token(coap_message_t *message, const uint8_t *token, + size_t token_len); -int coap_get_header_content_format(void *packet, unsigned int *format); -int coap_set_header_content_format(void *packet, unsigned int format); +int coap_get_header_content_format(coap_message_t *message, unsigned int *format); +int coap_set_header_content_format(coap_message_t *message, unsigned int format); -int coap_get_header_accept(void *packet, unsigned int *accept); -int coap_set_header_accept(void *packet, unsigned int accept); +int coap_get_header_accept(coap_message_t *message, unsigned int *accept); +int coap_set_header_accept(coap_message_t *message, unsigned int accept); -int coap_get_header_max_age(void *packet, uint32_t *age); -int coap_set_header_max_age(void *packet, uint32_t age); +int coap_get_header_max_age(coap_message_t *message, uint32_t *age); +int coap_set_header_max_age(coap_message_t *message, uint32_t age); -int coap_get_header_etag(void *packet, const uint8_t **etag); -int coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len); +int coap_get_header_etag(coap_message_t *message, const uint8_t **etag); +int coap_set_header_etag(coap_message_t *message, const uint8_t *etag, + size_t etag_len); -int coap_get_header_if_match(void *packet, const uint8_t **etag); -int coap_set_header_if_match(void *packet, const uint8_t *etag, +int coap_get_header_if_match(coap_message_t *message, const uint8_t **etag); +int coap_set_header_if_match(coap_message_t *message, const uint8_t *etag, size_t etag_len); -int coap_get_header_if_none_match(void *packet); -int coap_set_header_if_none_match(void *packet); +int coap_get_header_if_none_match(coap_message_t *message); +int coap_set_header_if_none_match(coap_message_t *message); -int coap_get_header_proxy_uri(void *packet, const char **uri); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_uri(void *packet, const char *uri); +/* in-place string might not be 0-terminated. */ +int coap_get_header_proxy_uri(coap_message_t *message, const char **uri); +int coap_set_header_proxy_uri(coap_message_t *message, const char *uri); -int coap_get_header_proxy_scheme(void *packet, const char **scheme); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_scheme(void *packet, const char *scheme); +/* in-place string might not be 0-terminated. */ +int coap_get_header_proxy_scheme(coap_message_t *message, const char **scheme); +int coap_set_header_proxy_scheme(coap_message_t *message, const char *scheme); -int coap_get_header_uri_host(void *packet, const char **host); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_host(void *packet, const char *host); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_host(coap_message_t *message, const char **host); +int coap_set_header_uri_host(coap_message_t *message, const char *host); -int coap_get_header_uri_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_path(void *packet, const char *path); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_path(coap_message_t *message, const char **path); +int coap_set_header_uri_path(coap_message_t *message, const char *path); -int coap_get_header_uri_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_query(void *packet, const char *query); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_query(coap_message_t *message, const char **query); +int coap_set_header_uri_query(coap_message_t *message, const char *query); -int coap_get_header_location_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_path(void *packet, const char *path); /* also splits optional query into Location-Query option. */ +/* in-place string might not be 0-terminated. */ +int coap_get_header_location_path(coap_message_t *message, const char **path); +/* also splits optional query into Location-Query option. */ +int coap_set_header_location_path(coap_message_t *message, const char *path); -int coap_get_header_location_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_query(void *packet, const char *query); +/* in-place string might not be 0-terminated. */ +int coap_get_header_location_query(coap_message_t *message, const char **query); +int coap_set_header_location_query(coap_message_t *message, const char *query); -int coap_get_header_observe(void *packet, uint32_t *observe); -int coap_set_header_observe(void *packet, uint32_t observe); +int coap_get_header_observe(coap_message_t *message, uint32_t *observe); +int coap_set_header_observe(coap_message_t *message, uint32_t observe); -int coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block2(coap_message_t *message, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block2(void *packet, uint32_t num, uint8_t more, +int coap_set_header_block2(coap_message_t *message, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block1(coap_message_t *message, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block1(void *packet, uint32_t num, uint8_t more, +int coap_set_header_block1(coap_message_t *message, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_size2(void *packet, uint32_t *size); -int coap_set_header_size2(void *packet, uint32_t size); +int coap_get_header_size2(coap_message_t *message, uint32_t *size); +int coap_set_header_size2(coap_message_t *message, uint32_t size); -int coap_get_header_size1(void *packet, uint32_t *size); -int coap_set_header_size1(void *packet, uint32_t size); +int coap_get_header_size1(coap_message_t *message, uint32_t *size); +int coap_set_header_size1(coap_message_t *message, uint32_t size); -int coap_get_payload(void *packet, const uint8_t **payload); -int coap_set_payload(void *packet, const void *payload, size_t length); +int coap_get_payload(coap_message_t *message, const uint8_t **payload); +int coap_set_payload(coap_message_t *message, const void *payload, size_t length); -#endif /* ER_COAP_H_ */ +#endif /* COAP_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/rest-constants.h b/os/net/app-layer/coap/rest-constants.h deleted file mode 100644 index addc0970b..000000000 --- a/os/net/app-layer/coap/rest-constants.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * Constants for the REST Engine (Erbium). - * \author - * Matthias Kovatsch - */ - -#ifndef REST_CONSTANTS_H_ -#define REST_CONSTANTS_H_ - -/** - * Generic status codes that are mapped to either HTTP or CoAP codes. - */ -struct rest_implementation_status { - const unsigned int OK; /* CONTENT_2_05, OK_200 */ - const unsigned int CREATED; /* CREATED_2_01, CREATED_201 */ - const unsigned int CHANGED; /* CHANGED_2_04, NO_CONTENT_204 */ - const unsigned int DELETED; /* DELETED_2_02, NO_CONTENT_204 */ - const unsigned int NOT_MODIFIED; /* VALID_2_03, NOT_MODIFIED_304 */ - - const unsigned int BAD_REQUEST; /* BAD_REQUEST_4_00, BAD_REQUEST_400 */ - const unsigned int UNAUTHORIZED; /* UNAUTHORIZED_4_01, UNAUTHORIZED_401 */ - const unsigned int BAD_OPTION; /* BAD_OPTION_4_02, BAD_REQUEST_400 */ - const unsigned int FORBIDDEN; /* FORBIDDEN_4_03, FORBIDDEN_403 */ - const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */ - const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */ - const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */ - const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */ - const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */ - - const unsigned int INTERNAL_SERVER_ERROR; /* INTERNAL_SERVER_ERROR_5_00, INTERNAL_SERVER_ERROR_500 */ - const unsigned int NOT_IMPLEMENTED; /* NOT_IMPLEMENTED_5_01, NOT_IMPLEMENTED_501 */ - const unsigned int BAD_GATEWAY; /* BAD_GATEWAY_5_02, BAD_GATEWAY_502 */ - const unsigned int SERVICE_UNAVAILABLE; /* SERVICE_UNAVAILABLE_5_03, SERVICE_UNAVAILABLE_503 */ - const unsigned int GATEWAY_TIMEOUT; /* GATEWAY_TIMEOUT_5_04, GATEWAY_TIMEOUT_504 */ - const unsigned int PROXYING_NOT_SUPPORTED; /* PROXYING_NOT_SUPPORTED_5_05, INTERNAL_SERVER_ERROR_500 */ -}; - -/** - * List of Content-Formats which are Internet Media Types plus encoding. - * TODO This should be a constant enum taken from CoAP for both CoAP and HTTP. - */ -struct rest_implementation_type { - unsigned int TEXT_PLAIN; - unsigned int TEXT_XML; - unsigned int TEXT_CSV; - unsigned int TEXT_HTML; - unsigned int IMAGE_GIF; - unsigned int IMAGE_JPEG; - unsigned int IMAGE_PNG; - unsigned int IMAGE_TIFF; - unsigned int AUDIO_RAW; - unsigned int VIDEO_RAW; - unsigned int APPLICATION_LINK_FORMAT; - unsigned int APPLICATION_XML; - unsigned int APPLICATION_OCTET_STREAM; - unsigned int APPLICATION_RDF_XML; - unsigned int APPLICATION_SOAP_XML; - unsigned int APPLICATION_ATOM_XML; - unsigned int APPLICATION_XMPP_XML; - unsigned int APPLICATION_EXI; - unsigned int APPLICATION_FASTINFOSET; - unsigned int APPLICATION_SOAP_FASTINFOSET; - unsigned int APPLICATION_JSON; - unsigned int APPLICATION_X_OBIX_BINARY; -}; - -/** - * Resource flags for allowed methods and special functionalities. - */ -typedef enum { - NO_FLAGS = 0, - - /* methods to handle */ - METHOD_GET = (1 << 0), - METHOD_POST = (1 << 1), - METHOD_PUT = (1 << 2), - METHOD_DELETE = (1 << 3), - - /* special flags */ - HAS_SUB_RESOURCES = (1 << 4), - IS_SEPARATE = (1 << 5), - IS_OBSERVABLE = (1 << 6), - IS_PERIODIC = (1 << 7) -} rest_resource_flags_t; - -#endif /* REST_CONSTANTS_H_ */ diff --git a/os/net/app-layer/coap/rest-engine.c b/os/net/app-layer/coap/rest-engine.c deleted file mode 100644 index cec590012..000000000 --- a/os/net/app-layer/coap/rest-engine.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * An abstraction layer for RESTful Web services (Erbium). - * Inspired by RESTful Contiki by Dogan Yazar. - * \author - * Matthias Kovatsch - */ - -#include -#include -#include "contiki.h" -#include "rest-engine.h" - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -PROCESS(rest_engine_process, "REST Engine"); -/*---------------------------------------------------------------------------*/ -LIST(restful_services); -LIST(restful_periodic_services); -/*---------------------------------------------------------------------------*/ -/*- REST Engine API ---------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -/** - * \brief Initializes and starts the REST Engine process - * - * This function must be called by server processes before any resources are - * registered through rest_activate_resource(). - */ -void -rest_init_engine(void) -{ - /* avoid initializing twice */ - static uint8_t initialized = 0; - - if(initialized) { - PRINTF("REST engine process already running - double initialization?\n"); - return; - } - initialized = 1; - - list_init(restful_services); - - REST.set_service_callback(rest_invoke_restful_service); - - /* Start the RESTful server implementation. */ - REST.init(); - - /*Start REST engine process */ - process_start(&rest_engine_process, NULL); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Makes a resource available under the given URI path - * \param resource A pointer to a resource implementation - * \param path The URI path string for this resource - * - * The resource implementation must be imported first using the - * extern keyword. The build system takes care of compiling every - * *.c file in the ./resources/ sub-directory (see example Makefile). - */ -void -rest_activate_resource(resource_t *resource, char *path) -{ - resource->url = path; - list_add(restful_services, resource); - - PRINTF("Activating: %s\n", resource->url); - - /* Only add periodic resources with a periodic_handler and a period > 0. */ - if(resource->flags & IS_PERIODIC && resource->periodic->periodic_handler - && resource->periodic->period) { - PRINTF("Periodic resource: %p (%s)\n", resource->periodic, - resource->periodic->resource->url); - list_add(restful_periodic_services, resource->periodic); - if(process_is_running(&rest_engine_process)) { - PRINTF("Periodic: Set timer for /%s to %lu\n", - resource->url, resource->periodic->period); - PROCESS_CONTEXT_BEGIN(&rest_engine_process); - etimer_set(&resource->periodic->periodic_timer, - resource->periodic->period); - PROCESS_CONTEXT_END(&rest_engine_process); - } - } -} -/*---------------------------------------------------------------------------*/ -/*- Internal API ------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -list_t -rest_get_resources(void) -{ - return restful_services; -} -/*---------------------------------------------------------------------------*/ -int -rest_invoke_restful_service(void *request, void *response, uint8_t *buffer, - uint16_t buffer_size, int32_t *offset) -{ - uint8_t found = 0; - uint8_t allowed = 1; - - resource_t *resource = NULL; - const char *url = NULL; - int url_len, res_url_len; - - url_len = REST.get_url(request, &url); - for(resource = (resource_t *)list_head(restful_services); - resource; resource = resource->next) { - - /* if the web service handles that kind of requests and urls matches */ - res_url_len = strlen(resource->url); - if((url_len == res_url_len - || (url_len > res_url_len - && (resource->flags & HAS_SUB_RESOURCES) - && url[res_url_len] == '/')) - && strncmp(resource->url, url, res_url_len) == 0) { - found = 1; - rest_resource_flags_t method = REST.get_method_type(request); - - PRINTF("/%s, method %u, resource->flags %u\n", resource->url, - (uint16_t)method, resource->flags); - - if((method & METHOD_GET) && resource->get_handler != NULL) { - /* call handler function */ - resource->get_handler(request, response, buffer, buffer_size, offset); - } else if((method & METHOD_POST) && resource->post_handler != NULL) { - /* call handler function */ - resource->post_handler(request, response, buffer, buffer_size, - offset); - } else if((method & METHOD_PUT) && resource->put_handler != NULL) { - /* call handler function */ - resource->put_handler(request, response, buffer, buffer_size, offset); - } else if((method & METHOD_DELETE) && resource->delete_handler != NULL) { - /* call handler function */ - resource->delete_handler(request, response, buffer, buffer_size, - offset); - } else { - allowed = 0; - REST.set_response_status(response, REST.status.METHOD_NOT_ALLOWED); - } - break; - } - } - if(!found) { - REST.set_response_status(response, REST.status.NOT_FOUND); - } else if(allowed) { - /* final handler for special flags */ - if(resource->flags & IS_OBSERVABLE) { - REST.subscription_handler(resource, request, response); - } - } - return found & allowed; -} -/*-----------------------------------------------------------------------------------*/ -PROCESS_THREAD(rest_engine_process, ev, data) -{ - PROCESS_BEGIN(); - - /* pause to let REST server finish adding resources. */ - PROCESS_PAUSE(); - - /* initialize the PERIODIC_RESOURCE timers, which will be handled by this process. */ - periodic_resource_t *periodic_resource = NULL; - - for(periodic_resource = - (periodic_resource_t *)list_head(restful_periodic_services); - periodic_resource; periodic_resource = periodic_resource->next) { - if(periodic_resource->periodic_handler && periodic_resource->period) { - PRINTF("Periodic: Set timer for /%s to %lu\n", - periodic_resource->resource->url, periodic_resource->period); - etimer_set(&periodic_resource->periodic_timer, - periodic_resource->period); - } - } - while(1) { - PROCESS_WAIT_EVENT(); - - if(ev == PROCESS_EVENT_TIMER) { - for(periodic_resource = - (periodic_resource_t *)list_head(restful_periodic_services); - periodic_resource; periodic_resource = periodic_resource->next) { - if(periodic_resource->period - && etimer_expired(&periodic_resource->periodic_timer)) { - - PRINTF("Periodic: etimer expired for /%s (period: %lu)\n", - periodic_resource->resource->url, periodic_resource->period); - - /* Call the periodic_handler function, which was checked during adding to list. */ - (periodic_resource->periodic_handler)(); - - etimer_reset(&periodic_resource->periodic_timer); - } - } - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/rest-engine.h b/os/net/app-layer/coap/rest-engine.h deleted file mode 100644 index cf9faa734..000000000 --- a/os/net/app-layer/coap/rest-engine.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * An abstraction layer for RESTful Web services (Erbium). - * Inspired by RESTful Contiki by Dogan Yazar. - * \author - * Matthias Kovatsch - */ - -#ifndef REST_ENGINE_H_ -#define REST_ENGINE_H_ - -#include -#include "contiki.h" -#include "contiki-lib.h" -#include "rest-constants.h" - -/* NOTE: this will be removed - now it is always set to erbium CoAP implementation */ -#define REST coap_rest_implementation - -/* - * The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer. - * Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks. - */ -#ifndef REST_MAX_CHUNK_SIZE -#define REST_MAX_CHUNK_SIZE 64 -#endif - -struct resource_s; -struct periodic_resource_s; - -/* signatures of handler functions */ -typedef void (*restful_handler)(void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); -typedef void (*restful_final_handler)(struct resource_s *resource, - void *request, void *response); -typedef void (*restful_periodic_handler)(void); -typedef void (*restful_response_handler)(void *data, void *response); -typedef void (*restful_trigger_handler)(void); - -/* signature of the rest-engine service function */ -typedef int (*service_callback_t)(void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); - -/* data structure representing a resource in REST */ -struct resource_s { - struct resource_s *next; /* for LIST, points to next resource defined */ - const char *url; /*handled URL */ - rest_resource_flags_t flags; /* handled RESTful methods */ - const char *attributes; /* link-format attributes */ - restful_handler get_handler; /* handler function */ - restful_handler post_handler; /* handler function */ - restful_handler put_handler; /* handler function */ - restful_handler delete_handler; /* handler function */ - union { - struct periodic_resource_s *periodic; /* special data depending on flags */ - restful_trigger_handler trigger; - restful_trigger_handler resume; - }; -}; -typedef struct resource_s resource_t; - -struct periodic_resource_s { - struct periodic_resource_s *next; /* for LIST, points to next resource defined */ - const resource_t *resource; - uint32_t period; - struct etimer periodic_timer; - const restful_periodic_handler periodic_handler; -}; -typedef struct periodic_resource_s periodic_resource_t; - -/* - * Macro to define a RESTful resource. - * Resources are statically defined for the sake of efficiency and better memory management. - */ -#define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ - resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } - -#define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ - resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } - -#define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \ - resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } } - -#define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \ - resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } } - -/* - * Macro to define a periodic resource. - * The corresponding [name]_periodic_handler() function will be called every period. - * For instance polling a sensor and publishing a changed value to subscribed clients would be done there. - * The subscriber list will be maintained by the final_handler rest_subscription_handler() (see rest-mapping header file). - */ -#define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \ - periodic_resource_t periodic_##name; \ - resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } }; \ - periodic_resource_t periodic_##name = { NULL, &name, period, { { 0 } }, periodic_handler }; - -struct rest_implementation { - char *name; - - /** Initialize the REST implementation. */ - void (*init)(void); - - /** Register the RESTful service callback at implementation. */ - void (*set_service_callback)(service_callback_t callback); - - /** Get request URI path. */ - int (*get_url)(void *request, const char **url); - - /** Get the method of a request. */ - rest_resource_flags_t (*get_method_type)(void *request); - - /** Set the status code of a response. */ - int (*set_response_status)(void *response, unsigned int code); - - /** Get the content-type of a request. */ - int (*get_header_content_type)(void *request, - unsigned int *content_format); - - /** Set the Content-Type of a response. */ - int (*set_header_content_type)(void *response, - unsigned int content_format); - - /** Get the Accept types of a request. */ - int (*get_header_accept)(void *request, unsigned int *accept); - - /** Get the Length option of a request. */ - int (*get_header_length)(void *request, uint32_t *size); - - /** Set the Length option of a response. */ - int (*set_header_length)(void *response, uint32_t size); - - /** Get the Max-Age option of a request. */ - int (*get_header_max_age)(void *request, uint32_t *age); - - /** Set the Max-Age option of a response. */ - int (*set_header_max_age)(void *response, uint32_t age); - - /** Set the ETag option of a response. */ - int (*set_header_etag)(void *response, const uint8_t *etag, - size_t length); - - /** Get the If-Match option of a request. */ - int (*get_header_if_match)(void *request, const uint8_t **etag); - - /** Get the If-Match option of a request. */ - int (*get_header_if_none_match)(void *request); - - /** Get the Host option of a request. */ - int (*get_header_host)(void *request, const char **host); - - /** Set the location option of a response. */ - int (*set_header_location)(void *response, const char *location); - - /** Get the payload option of a request. */ - int (*get_request_payload)(void *request, const uint8_t **payload); - - /** Set the payload option of a response. */ - int (*set_response_payload)(void *response, const void *payload, - size_t length); - - /** Get the query string of a request. */ - int (*get_query)(void *request, const char **value); - - /** Get the value of a request query key-value pair. */ - int (*get_query_variable)(void *request, const char *name, - const char **value); - - /** Get the value of a request POST key-value pair. */ - int (*get_post_variable)(void *request, const char *name, - const char **value); - - /** Send the payload to all subscribers of the resource at url. */ - void (*notify_subscribers)(resource_t *resource); - - /** The handler for resource subscriptions. */ - restful_final_handler subscription_handler; - - /* REST status codes. */ - const struct rest_implementation_status status; - - /* REST content-types. */ - const struct rest_implementation_type type; -}; - -/* instance of REST implementation */ -extern const struct rest_implementation REST; - -/* - * To be called by HTTP/COAP server as a callback function when a new service request appears. - * This function dispatches the corresponding RESTful service. - */ -int rest_invoke_restful_service(void *request, void *response, - uint8_t *buffer, uint16_t buffer_size, - int32_t *offset); -/*---------------------------------------------------------------------------*/ -/** - * \brief Initializes REST framework and starts the HTTP or CoAP process. - */ -void rest_init_engine(void); -/*---------------------------------------------------------------------------*/ -/** - * - * \brief Resources wanted to be accessible should be activated with the following code. - * \param resource - * A RESTful resource defined through the RESOURCE macros. - * \param path - * The local URI path where to provide the resource. - */ -void rest_activate_resource(resource_t *resource, char *path); -/*---------------------------------------------------------------------------*/ -/** - * \brief Returns the list of registered RESTful resources. - * \return The resource list. - */ -list_t rest_get_resources(void); -/*---------------------------------------------------------------------------*/ - -#endif /*REST_ENGINE_H_ */ diff --git a/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support b/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support new file mode 100644 index 000000000..ac8a5aff4 --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support @@ -0,0 +1 @@ +${info Building with tinyDTLS - see $(CONTIKI)/$(TINYDTLS_PATH)/LICENSE} diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h new file mode 100644 index 000000000..9265583e5 --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +/** + * \file + * DTLS support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef DTLS_SUPPORT_CONF_H_ +#define DTLS_SUPPORT_CONF_H_ + +/* Use same log level as CoAP as default */ +#define LOG_LEVEL_DTLS LOG_LEVEL_COAP + +#define DTLS_LOG_CONF_PATH "coap-log.h" + +#include "coap-endpoint.h" + +typedef coap_endpoint_t session_t; + +#include "sys/ctimer.h" +#include + +typedef struct { + struct ctimer retransmit_timer; +} dtls_support_context_state_t; + +#define DTLS_SUPPORT_CONF_CONTEXT_STATE dtls_support_context_state_t + +#define DTLS_TICKS_PER_SECOND CLOCK_SECOND + +typedef clock_time_t dtls_tick_t; + +#define HAVE_ASSERT_H 1 + +#endif /* DTLS_SUPPORT_CONF_H_ */ diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support.c b/os/net/app-layer/coap/tinydtls-support/dtls-support.c new file mode 100644 index 000000000..ad960b718 --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support.c @@ -0,0 +1,187 @@ +/* + * 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. + */ + +/** + * \file + * DTLS support for CoAP + * \author + * Niclas Finne + * Joakim Eriksson + */ + +#include "dtls-support.h" +#include "lib/random.h" +#include +#include + +/* Log configuration */ +#define LOG_MODULE "dtls-support" +#define LOG_LEVEL LOG_LEVEL_DTLS +#include "dtls-log.h" +#include "coap-log.h" + +static dtls_context_t the_dtls_context; +static dtls_cipher_context_t cipher_context; +static uint8_t lock_context = 0; +/*---------------------------------------------------------------------------*/ +dtls_context_t * +dtls_context_acquire(void) +{ + if(lock_context) { + return NULL; + } + lock_context = 1; + LOG_DBG("Allocated context\n"); + return &the_dtls_context; +} +/*---------------------------------------------------------------------------*/ +void +dtls_context_release(dtls_context_t *context) +{ + if(context == &the_dtls_context) { + lock_context = 0; + } +} +/*---------------------------------------------------------------------------*/ +dtls_cipher_context_t * +dtls_cipher_context_acquire(void) +{ + return &cipher_context; +} +/*---------------------------------------------------------------------------*/ +void +dtls_cipher_context_release(dtls_cipher_context_t *c) +{ +} +/*---------------------------------------------------------------------------*/ +void +dtls_ticks(dtls_tick_t *t) +{ + *t = clock_time(); +} +/*---------------------------------------------------------------------------*/ +int +dtls_fill_random(uint8_t *buf, size_t len) +{ + int i; + if(buf) { + for(i = 0; i < len; i++) { + buf[i] = random_rand() & 0xff; + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* message retransmission */ +/*---------------------------------------------------------------------------*/ +static void +dtls_retransmit_callback(void *ptr) +{ + dtls_context_t *ctx; + clock_time_t now; + clock_time_t next; + + ctx = ptr; + now = clock_time(); + /* Just one retransmission per timer scheduling */ + dtls_check_retransmit(ctx, &next, 0); + + /* need to set timer to some value even if no nextpdu is available */ + if(next != 0) { + ctimer_set(&ctx->support.retransmit_timer, + next <= now ? 1 : next - now, + dtls_retransmit_callback, ctx); + } +} +/*---------------------------------------------------------------------------*/ +void +dtls_set_retransmit_timer(dtls_context_t *ctx, unsigned int timeout) +{ + ctimer_set(&ctx->support.retransmit_timer, timeout, + dtls_retransmit_callback, ctx); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_init(session_t *sess) +{ + memset(sess, 0, sizeof(session_t)); +} +/*---------------------------------------------------------------------------*/ +int +dtls_session_equals(const session_t *a, const session_t *b) +{ + coap_endpoint_t *e1 = (coap_endpoint_t *)a; + coap_endpoint_t *e2 = (coap_endpoint_t *)b; + + if(LOG_DBG_ENABLED) { + LOG_DBG(" **** EP:"); + LOG_DBG_COAP_EP(e1); + LOG_DBG_(" =?= "); + LOG_DBG_COAP_EP(e2); + LOG_DBG_(" => %d\n", coap_endpoint_cmp(e1, e2)); + } + + return coap_endpoint_cmp(e1, e2); +} +/*---------------------------------------------------------------------------*/ +void * +dtls_session_get_address(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return (void *)a; +} +/*---------------------------------------------------------------------------*/ +int dtls_session_get_address_size(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return sizeof(session_t); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_print(const session_t *a) +{ + coap_endpoint_print((const coap_endpoint_t *)a); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_log(const session_t *a) +{ + coap_endpoint_log((const coap_endpoint_t *)a); +} +/*---------------------------------------------------------------------------*/ +void +dtls_support_init(void) +{ + LOG_INFO("init\n"); +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/http-socket/http-socket.h b/os/net/app-layer/http-socket/http-socket.h index 5b683e10b..adac80c3e 100644 --- a/os/net/app-layer/http-socket/http-socket.h +++ b/os/net/app-layer/http-socket/http-socket.h @@ -32,6 +32,7 @@ #define HTTP_SOCKET_H #include "tcp-socket.h" +#include "sys/cc.h" struct http_socket; @@ -62,8 +63,6 @@ typedef void (* http_socket_callback_t)(struct http_socket *s, const uint8_t *data, uint16_t datalen); -#define MAX(n, m) (((n) < (m)) ? (m) : (n)) - #define HTTP_SOCKET_INPUTBUFSIZE UIP_TCP_MSS #define HTTP_SOCKET_OUTPUTBUFSIZE MAX(UIP_TCP_MSS, 128) diff --git a/os/net/ipv6/multicast/esmrf.c b/os/net/ipv6/multicast/esmrf.c index adbea25e0..00619c354 100644 --- a/os/net/ipv6/multicast/esmrf.c +++ b/os/net/ipv6/multicast/esmrf.c @@ -46,15 +46,16 @@ #include "net/ipv6/multicast/uip-mcast6-route.h" #include "net/ipv6/multicast/uip-mcast6-stats.h" #include "net/ipv6/multicast/esmrf.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" #include "net/ipv6/uip.h" #include "net/netstack.h" #include "net/packetbuf.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#endif /* ROUTING_CONF_RPL_LITE */ +#if ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif /* ROUTING_CONF_RPL_CLASSIC */ #include extern uint16_t uip_slen; diff --git a/os/net/ipv6/multicast/smrf.c b/os/net/ipv6/multicast/smrf.c index 00043d60b..86a053648 100644 --- a/os/net/ipv6/multicast/smrf.c +++ b/os/net/ipv6/multicast/smrf.c @@ -47,13 +47,15 @@ #include "net/ipv6/multicast/uip-mcast6-route.h" #include "net/ipv6/multicast/uip-mcast6-stats.h" #include "net/ipv6/multicast/smrf.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" #include "net/netstack.h" #include "net/packetbuf.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#endif /* ROUTING_CONF_RPL_LITE */ +#if ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif /* ROUTING_CONF_RPL_CLASSIC */ #include #define DEBUG DEBUG_NONE diff --git a/os/net/ipv6/resolv.h b/os/net/ipv6/resolv.h index ed24d5bce..ac414425f 100644 --- a/os/net/ipv6/resolv.h +++ b/os/net/ipv6/resolv.h @@ -55,7 +55,7 @@ /** * Event that is broadcasted when a DNS name has been resolved. */ -CCIF extern process_event_t resolv_event_found; +extern process_event_t resolv_event_found; enum { /** Hostname is fresh and usable. This response is cached and will eventually @@ -91,14 +91,14 @@ enum { typedef uint8_t resolv_status_t; /* Functions. */ -CCIF resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr); +resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr); -CCIF void resolv_query(const char *name); +void resolv_query(const char *name); #if RESOLV_CONF_SUPPORTS_MDNS -CCIF void resolv_set_hostname(const char *hostname); +void resolv_set_hostname(const char *hostname); -CCIF const char *resolv_get_hostname(void); +const char *resolv_get_hostname(void); #endif PROCESS_NAME(resolv_process); diff --git a/os/net/ipv6/sicslowpan.c b/os/net/ipv6/sicslowpan.c index 060699e93..3a08df83a 100644 --- a/os/net/ipv6/sicslowpan.c +++ b/os/net/ipv6/sicslowpan.c @@ -74,12 +74,7 @@ #include "net/packetbuf.h" #include "net/queuebuf.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" @@ -676,8 +671,8 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) int ext_hdr_len; struct uip_udp_hdr *udp_buf; -#if LOG_DBG_ENABLED - { uint16_t ndx; + if(LOG_DBG_ENABLED) { + uint16_t ndx; LOG_DBG("before compression (%d): ", UIP_IP_BUF->len[1]); for(ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) { uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx]; @@ -685,7 +680,6 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) } LOG_DBG("\n"); } -#endif /* LOG_DBG_ENABLED */ hc06_ptr = PACKETBUF_IPHC_BUF + 2; /* @@ -1001,16 +995,15 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) PACKETBUF_IPHC_BUF[0] = iphc0; PACKETBUF_IPHC_BUF[1] = iphc1; -#if LOG_DBG_ENABLED - { uint16_t ndx; + if(LOG_DBG_ENABLED) { + uint16_t ndx; LOG_DBG("after compression %d: ", (int)(hc06_ptr - packetbuf_ptr)); for(ndx = 0; ndx < hc06_ptr - packetbuf_ptr; ndx++) { uint8_t data = ((uint8_t *) packetbuf_ptr)[ndx]; LOG_DBG("%02x", data); } LOG_DBG("\n"); - } -#endif + } packetbuf_hdr_len = hc06_ptr - packetbuf_ptr; } @@ -1436,10 +1429,8 @@ packet_sent(void *ptr, int status, int transmissions) /* Update neighbor link statistics */ link_stats_packet_sent(dest, status, transmissions); -#if UIP_CONF_IPV6_RPL - /* Call RPL link callback */ - rpl_link_callback(dest, status, transmissions); -#endif /* UIP_CONF_IPV6_RPL */ + /* Call routing protocol link callback */ + NETSTACK_ROUTING.link_callback(dest, status, transmissions); /* DS6 callback, used for UIP_DS6_LL_NUD */ uip_ds6_link_callback(status, transmissions); @@ -1913,8 +1904,7 @@ input(void) LOG_INFO("input: IP packet ready (length %d)\n", uip_len); -#if LOG_DBG_ENABLED - { + if(LOG_DBG_ENABLED) { uint16_t ndx; LOG_DBG("after decompression %u:", UIP_IP_BUF->len[1]); for (ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) { @@ -1923,7 +1913,6 @@ input(void) } LOG_DBG("\n"); } -#endif /* LOG_DBG_ENABLED */ /* if callback is set then set attributes and call */ if(callback) { diff --git a/os/net/ipv6/tcpip.c b/os/net/ipv6/tcpip.c index e096ce44b..41d317d17 100644 --- a/os/net/ipv6/tcpip.c +++ b/os/net/ipv6/tcpip.c @@ -38,21 +38,15 @@ * \author Julien Abeille (IPv6 related code) */ +#include "contiki.h" #include "contiki-net.h" #include "net/ipv6/uip-packetqueue.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/uip-ds6-nbr.h" #include "net/linkaddr.h" - -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif +#include "net/routing/routing.h" #include @@ -103,11 +97,6 @@ enum { PACKET_INPUT }; -#if UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING -#define NEXTHOP_NON_STORING(addr) rpl_ext_header_srh_get_next_hop(addr) -#else -#define NEXTHOP_NON_STORING(addr) 0 -#endif /*---------------------------------------------------------------------------*/ static void init_appstate(uip_tcp_appstate_t *as, void *state) @@ -489,23 +478,6 @@ output_fallback(void) } /*---------------------------------------------------------------------------*/ static void -drop_route(uip_ds6_route_t *route) -{ -#if UIP_CONF_IPV6_RPL && (UIP_CONF_IPV6_RPL_LITE == 0) - - /* If we are running RPL, and if we are the root of the - network, we'll trigger a global repair before we remove - the route. */ - rpl_dag_t *dag; - dag = (rpl_dag_t *)route->state.dag; - if(dag != NULL && dag->instance != NULL) { - rpl_repair_root(dag->instance->instance_id); - } -#endif /* UIP_CONF_IPV6_RPL && (UIP_CONF_IPV6_RPL_LITE == 0) */ - uip_ds6_route_rm(route); -} -/*---------------------------------------------------------------------------*/ -static void annotate_transmission(uip_ipaddr_t *nexthop) { #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS @@ -533,7 +505,7 @@ get_nexthop(uip_ipaddr_t *addr) LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr); LOG_INFO_("\n"); - if(NEXTHOP_NON_STORING(addr)) { + if(NETSTACK_ROUTING.ext_header_srh_get_next_hop(addr)) { LOG_INFO("output: selected next hop from SRH: "); LOG_INFO_6ADDR(addr); LOG_INFO_("\n"); @@ -571,9 +543,11 @@ get_nexthop(uip_ipaddr_t *addr) never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { LOG_ERR("output: found dead route\n"); - drop_route(route); - /* We don't have a nexthop to send the packet to, so we drop - it. */ + /* Notifiy the routing protocol that we are about to remove the route */ + NETSTACK_ROUTING.drop_route(route); + /* Remove the route */ + uip_ds6_route_rm(route); + /* We don't have a nexthop to send the packet to, so we drop it. */ } else { LOG_INFO("output: found next hop from routing table: "); LOG_INFO_6ADDR(nexthop); @@ -678,14 +652,13 @@ tcpip_ipv6_output(void) goto exit; } -#if UIP_CONF_IPV6_RPL - if(!rpl_ext_header_update()) { + + if(!NETSTACK_ROUTING.ext_header_update()) { /* Packet can not be forwarded */ - LOG_ERR("output: RPL header update error\n"); + LOG_ERR("output: routing protocol extension header update error\n"); uip_clear_buf(); return; } -#endif /* UIP_CONF_IPV6_RPL */ if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { linkaddr = NULL; @@ -855,10 +828,8 @@ PROCESS_THREAD(tcpip_process, ev, data) #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.init(); #endif - /* initialize RPL if configured for using RPL */ -#if UIP_CONF_IPV6_RPL - rpl_init(); -#endif /* UIP_CONF_IPV6_RPL */ + /* Initialize routing protocol */ + NETSTACK_ROUTING.init(); while(1) { PROCESS_YIELD(); diff --git a/os/net/ipv6/tcpip.h b/os/net/ipv6/tcpip.h index bf8c9b0b1..8f84cedb3 100644 --- a/os/net/ipv6/tcpip.h +++ b/os/net/ipv6/tcpip.h @@ -108,8 +108,7 @@ void tcpip_uipcall(void); * process whenever an event occurs on the connection. * */ -CCIF void tcp_attach(struct uip_conn *conn, - void *appstate); +void tcp_attach(struct uip_conn *conn, void *appstate); #define tcp_markconn(conn, appstate) tcp_attach(conn, appstate) /** @@ -126,7 +125,7 @@ CCIF void tcp_attach(struct uip_conn *conn, * \param port The port number in network byte order. * */ -CCIF void tcp_listen(uint16_t port); +void tcp_listen(uint16_t port); /** * Close a listening TCP port. @@ -140,7 +139,7 @@ CCIF void tcp_listen(uint16_t port); * \param port The port number in network byte order. * */ -CCIF void tcp_unlisten(uint16_t port); +void tcp_unlisten(uint16_t port); /** * Open a TCP connection to the specified IP address and port. @@ -165,8 +164,8 @@ CCIF void tcp_unlisten(uint16_t port); * memory could not be allocated for the connection. * */ -CCIF struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, - void *appstate); +struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, + void *appstate); /** * Cause a specified TCP connection to be polled. @@ -226,8 +225,8 @@ void udp_attach(struct uip_udp_conn *conn, * \return A pointer to the newly created connection, or NULL if * memory could not be allocated for the connection. */ -CCIF struct uip_udp_conn *udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, - void *appstate); +struct uip_udp_conn *udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, + void *appstate); /** * Create a new UDP broadcast connection. @@ -272,7 +271,7 @@ struct uip_udp_conn *udp_broadcast_new(uint16_t port, void *appstate); * \param conn A pointer to the UDP connection that should be polled. * */ -CCIF void tcpip_poll_udp(struct uip_udp_conn *conn); +void tcpip_poll_udp(struct uip_udp_conn *conn); /** @} */ @@ -288,7 +287,7 @@ CCIF void tcpip_poll_udp(struct uip_udp_conn *conn); * * This event is posted to a process whenever a uIP ICMP event has occurred. */ -CCIF extern process_event_t tcpip_icmp6_event; +extern process_event_t tcpip_icmp6_event; /** * \brief register an ICMPv6 callback @@ -318,7 +317,7 @@ void tcpip_icmp6_call(uint8_t type); * * This event is posted to a process whenever a uIP event has occurred. */ -CCIF extern process_event_t tcpip_event; +extern process_event_t tcpip_event; /** @@ -335,7 +334,7 @@ CCIF extern process_event_t tcpip_event; * and the length of the packet must be in the global * uip_len variable. */ -CCIF void tcpip_input(void); +void tcpip_input(void); /** * \brief Output packet to layer 2 diff --git a/os/net/ipv6/uip-debug.h b/os/net/ipv6/uip-debug.h index 267a36aca..6ebbf0aaa 100644 --- a/os/net/ipv6/uip-debug.h +++ b/os/net/ipv6/uip-debug.h @@ -43,13 +43,16 @@ #define UIP_DEBUG_H #include "net/net-debug.h" -#include "net/ipv6/uip.h" -#include +#include "net/ipv6/uiplib.h" -void uip_debug_ipaddr_print(const uip_ipaddr_t *addr); +static inline void +uip_debug_ipaddr_print(const uip_ipaddr_t *addr) +{ + uiplib_ipaddr_print(addr); +} #if (DEBUG) & DEBUG_PRINT -#define PRINT6ADDR(addr) uip_debug_ipaddr_print(addr) +#define PRINT6ADDR(addr) uiplib_ipaddr_print(addr) #else #define PRINT6ADDR(addr) #endif /* (DEBUG) & DEBUG_PRINT */ diff --git a/os/net/ipv6/uip-ds6-nbr.c b/os/net/ipv6/uip-ds6-nbr.c index d07f85d78..e49125548 100644 --- a/os/net/ipv6/uip-ds6-nbr.c +++ b/os/net/ipv6/uip-ds6-nbr.c @@ -50,20 +50,16 @@ #include "net/link-stats.h" #include "net/linkaddr.h" #include "net/packetbuf.h" +#include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-nd6.h" +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" #define LOG_MODULE "IPv6 Nbr" #define LOG_LEVEL LOG_LEVEL_IPV6 -#ifdef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED -#define NEIGHBOR_STATE_CHANGED(n) UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED(n) -void NEIGHBOR_STATE_CHANGED(uip_ds6_nbr_t *n); -#else -#define NEIGHBOR_STATE_CHANGED(n) -#endif /* UIP_DS6_CONF_NEIGHBOR_STATE_CHANGED */ - NBR_TABLE_GLOBAL(uip_ds6_nbr_t, ds6_neighbors); /*---------------------------------------------------------------------------*/ @@ -105,7 +101,7 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, LOG_INFO_(" link addr "); LOG_INFO_LLADDR((linkaddr_t*)lladdr); LOG_INFO_(" state %u\n", state); - NEIGHBOR_STATE_CHANGED(nbr); + NETSTACK_ROUTING.neighbor_state_changed(nbr); return nbr; } else { LOG_INFO("Add drop ip addr "); @@ -125,7 +121,7 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) #if UIP_CONF_IPV6_QUEUE_PKT uip_packetqueue_free(&nbr->packethandle); #endif /* UIP_CONF_IPV6_QUEUE_PKT */ - NEIGHBOR_STATE_CHANGED(nbr); + NETSTACK_ROUTING.neighbor_state_changed(nbr); return nbr_table_remove(ds6_neighbors, nbr); } return 0; @@ -257,7 +253,7 @@ uip_ds6_neighbor_periodic(void) switch(nbr->state) { case NBR_REACHABLE: if(stimer_expired(&nbr->reachable)) { -#if UIP_CONF_IPV6_RPL +#if UIP_CONF_ROUTER /* when a neighbor leave its REACHABLE state and is a default router, instead of going to STALE state it enters DELAY state in order to force a NUD on it. Otherwise, if there is no upward traffic, the @@ -277,12 +273,12 @@ uip_ds6_neighbor_periodic(void) LOG_INFO_(")\n"); nbr->state = NBR_STALE; } -#else /* UIP_CONF_IPV6_RPL */ +#else /* UIP_CONF_ROUTER */ LOG_INFO("REACHABLE: moving to STALE ("); LOG_INFO_6ADDR(&nbr->ipaddr); LOG_INFO_(")\n"); nbr->state = NBR_STALE; -#endif /* UIP_CONF_IPV6_RPL */ +#endif /* UIP_CONF_ROUTER */ } break; case NBR_INCOMPLETE: diff --git a/os/net/ipv6/uip-ds6-nbr.h b/os/net/ipv6/uip-ds6-nbr.h index ebb7de2d8..9aec47b4a 100644 --- a/os/net/ipv6/uip-ds6-nbr.h +++ b/os/net/ipv6/uip-ds6-nbr.h @@ -46,10 +46,11 @@ #ifndef UIP_DS6_NEIGHBOR_H_ #define UIP_DS6_NEIGHBOR_H_ +#include "contiki.h" #include "net/ipv6/uip.h" +#include "net/ipv6/uip-nd6.h" #include "net/nbr-table.h" #include "sys/stimer.h" -#include "net/ipv6/uip-ds6.h" #if UIP_CONF_IPV6_QUEUE_PKT #include "net/ipv6/uip-packetqueue.h" #endif /*UIP_CONF_QUEUE_PKT */ diff --git a/os/net/ipv6/uip-ds6-route.c b/os/net/ipv6/uip-ds6-route.c index 9321b632c..a8fdd88fb 100644 --- a/os/net/ipv6/uip-ds6-route.c +++ b/os/net/ipv6/uip-ds6-route.c @@ -103,7 +103,6 @@ LIST(notificationlist); #endif /*---------------------------------------------------------------------------*/ -#if LOG_DBG_ENABLED static void assert_nbr_routes_list_sane(void) { @@ -131,7 +130,6 @@ assert_nbr_routes_list_sane(void) } #endif /* (UIP_MAX_ROUTES != 0) */ } -#endif /* LOG_DBG_ENABLED */ /*---------------------------------------------------------------------------*/ #if UIP_DS6_NOTIFICATIONS static void @@ -330,9 +328,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ds6_route_t *r; struct uip_ds6_route_neighbor_route *nbrr; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } if(ipaddr == NULL || nexthop == NULL) { return NULL; @@ -473,9 +471,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop); #endif -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } return r; #else /* (UIP_MAX_ROUTES != 0) */ @@ -489,9 +487,11 @@ uip_ds6_route_rm(uip_ds6_route_t *route) { #if (UIP_MAX_ROUTES != 0) struct uip_ds6_route_neighbor_route *neighbor_route; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } + if(route != NULL && route->neighbor_routes != NULL) { LOG_INFO("Rm: removing route: "); @@ -541,9 +541,9 @@ uip_ds6_route_rm(uip_ds6_route_t *route) #endif } -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } #endif /* (UIP_MAX_ROUTES != 0) */ return; @@ -553,9 +553,10 @@ uip_ds6_route_rm(uip_ds6_route_t *route) static void rm_routelist(struct uip_ds6_route_neighbor_routes *routes) { -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } + if(routes != NULL && routes->route_list != NULL) { struct uip_ds6_route_neighbor_route *r; r = list_head(routes->route_list); @@ -565,9 +566,10 @@ rm_routelist(struct uip_ds6_route_neighbor_routes *routes) } nbr_table_remove(nbr_routes, routes); } -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } } /*---------------------------------------------------------------------------*/ static void @@ -603,9 +605,9 @@ uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) { uip_ds6_defrt_t *d; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } if(ipaddr == NULL) { return NULL; @@ -643,9 +645,9 @@ uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr); #endif -#if LOG_DBG_ENABLED +if(LOG_DBG_ENABLED) { assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ +} return d; } @@ -655,9 +657,9 @@ uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt) { uip_ds6_defrt_t *d; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } /* Make sure that the defrt is in the list before we remove it. */ for(d = list_head(defaultrouterlist); @@ -675,10 +677,10 @@ uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt) return; } } -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } } /*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * diff --git a/os/net/ipv6/uip-ds6-route.h b/os/net/ipv6/uip-ds6-route.h index acc417670..9f435824c 100644 --- a/os/net/ipv6/uip-ds6-route.h +++ b/os/net/ipv6/uip-ds6-route.h @@ -44,22 +44,28 @@ #include "net/nbr-table.h" #include "sys/stimer.h" #include "lib/list.h" -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl-conf.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl-conf.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif #ifdef UIP_CONF_MAX_ROUTES + #define UIP_MAX_ROUTES UIP_CONF_MAX_ROUTES + #else /* UIP_CONF_MAX_ROUTES */ + +#if ROUTING_CONF_RPL_LITE +#define UIP_MAX_ROUTES 0 /* RPL Lite only supports non-storing, no routes */ +#elif ROUTING_CONF_RPL_CLASSIC + +#include "net/routing/rpl-classic/rpl-conf.h" #if RPL_WITH_STORING #define UIP_MAX_ROUTES NETSTACK_MAX_ROUTE_ENTRIES -#else -#define UIP_MAX_ROUTES 0 +#else /* RPL_WITH_STORING */ +#define UIP_MAX_ROUTES 0 /* No storing mode, no need for routes */ +#endif /* RPL_WITH_STORING */ + +#else /* Not RPL Lite nor RPL Classic */ +#define UIP_MAX_ROUTES NETSTACK_MAX_ROUTE_ENTRIES #endif + #endif /* UIP_CONF_MAX_ROUTES */ NBR_TABLE_DECLARE(nbr_routes); diff --git a/os/net/ipv6/uip-ds6.c b/os/net/ipv6/uip-ds6.c index 18e9d33e9..6dd178dc8 100644 --- a/os/net/ipv6/uip-ds6.c +++ b/os/net/ipv6/uip-ds6.c @@ -47,6 +47,7 @@ #include #include "lib/random.h" #include "net/ipv6/uip-nd6.h" +#include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/multicast/uip-mcast6.h" #include "net/ipv6/uip-packetqueue.h" diff --git a/os/net/ipv6/uip-ds6.h b/os/net/ipv6/uip-ds6.h index 736f9bfeb..45394fec3 100644 --- a/os/net/ipv6/uip-ds6.h +++ b/os/net/ipv6/uip-ds6.h @@ -46,8 +46,8 @@ #include "sys/stimer.h" /* The size of uip_ds6_addr_t depends on UIP_ND6_DEF_MAXDADNS. Include uip-nd6.h to define it. */ #include "net/ipv6/uip-nd6.h" -#include "net/ipv6/uip-ds6-route.h" #include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-ds6-route.h" /*--------------------------------------------------*/ /** Configuration. For all tables (Neighbor cache, Prefix List, Routing Table, @@ -226,13 +226,6 @@ typedef struct uip_ds6_maddr { uip_ipaddr_t ipaddr; } uip_ds6_maddr_t; -/* only define the callback if RPL is active */ -#if UIP_CONF_IPV6_RPL && (UIP_CONF_IPV6_RPL_LITE == 0) -#ifndef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED -#define UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED rpl_ipv6_neighbor_callback -#endif /* UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED */ -#endif /* UIP_CONF_IPV6_RPL */ - /** \brief Interface structure (contains all the interface variables) */ typedef struct uip_ds6_netif { uint32_t link_mtu; diff --git a/os/net/ipv6/uip-icmp6.c b/os/net/ipv6/uip-icmp6.c index d46a9cd68..be33a1101 100644 --- a/os/net/ipv6/uip-icmp6.c +++ b/os/net/ipv6/uip-icmp6.c @@ -46,6 +46,7 @@ #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-icmp6.h" #include "contiki-default-conf.h" +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" @@ -58,15 +59,6 @@ #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_FIRST_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLIPH_LEN]) -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif /* UIP_CONF_IPV6_RPL */ - /** \brief temporary IP address */ static uip_ipaddr_t tmp_ipaddr; @@ -193,11 +185,8 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) { } } -#if UIP_CONF_IPV6_RPL - rpl_ext_header_remove(); -#else - uip_ext_len = 0; -#endif /* UIP_CONF_IPV6_RPL */ + /* Remove all extension headers related to the routing protocol in place */ + NETSTACK_ROUTING.ext_header_remove(); /* remember data of original packet before shifting */ uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); diff --git a/os/net/ipv6/uip-nd6.c b/os/net/ipv6/uip-nd6.c index 7881ed749..ce555ed53 100644 --- a/os/net/ipv6/uip-nd6.c +++ b/os/net/ipv6/uip-nd6.c @@ -973,7 +973,7 @@ ra_input(void) default: LOG_DBG("Updating timer of prefix "); LOG_DBG_6ADDR(&prefix->ipaddr); - LOG_DBG_(" new value %lu\n", (unsigned long)uip_ntohl(nd6_opt_prefix_info->validlt)); + LOG_DBG_(" new value %"PRIu32"\n", uip_ntohl(nd6_opt_prefix_info->validlt)); stimer_set(&prefix->vlifetime, uip_ntohl(nd6_opt_prefix_info->validlt)); prefix->isinfinite = 0; @@ -1034,7 +1034,7 @@ ra_input(void) while(naddr-- > 0) { LOG_DBG("nameserver: "); LOG_DBG_6ADDR(ip); - LOG_DBG_(" lifetime: %lx\n", (unsigned long)uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + LOG_DBG_(" lifetime: %"PRIx32"\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); ip++; } diff --git a/os/net/rpl-lite/rpl-ns.c b/os/net/ipv6/uip-sr.c similarity index 69% rename from os/net/rpl-lite/rpl-ns.c rename to os/net/ipv6/uip-sr.c index 0b31484b8..15b123552 100644 --- a/os/net/rpl-lite/rpl-ns.c +++ b/os/net/ipv6/uip-sr.c @@ -30,55 +30,59 @@ */ /** - * \addtogroup rpl-lite + * \addtogroup uip * @{ * * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. + * Source routing support * * \author Simon Duquennoy */ -#include "net/rpl-lite/rpl.h" +#include "contiki.h" +#include "net/ipv6/uip-sr.h" +#include "net/routing/routing.h" #include "lib/list.h" #include "lib/memb.h" /* Log configuration */ #include "sys/log.h" -#define LOG_MODULE "RPL" -#define LOG_LEVEL LOG_LEVEL_RPL +#define LOG_MODULE "IPv6 SR" +#define LOG_LEVEL LOG_LEVEL_IPV6 /* Total number of nodes */ static int num_nodes; /* Every known node in the network */ LIST(nodelist); -MEMB(nodememb, rpl_ns_node_t, RPL_NS_LINK_NUM); +MEMB(nodememb, uip_sr_node_t, UIP_SR_LINK_NUM); /*---------------------------------------------------------------------------*/ int -rpl_ns_num_nodes(void) +uip_sr_num_nodes(void) { return num_nodes; } /*---------------------------------------------------------------------------*/ static int -node_matches_address(const rpl_ns_node_t *node, const uip_ipaddr_t *addr) +node_matches_address(void *graph, const uip_sr_node_t *node, const uip_ipaddr_t *addr) { - return addr != NULL - && node != NULL - && !memcmp(addr, &curr_instance.dag.dag_id, 8) - && !memcmp(((const unsigned char *)addr) + 8, node->link_identifier, 8); + if(node == NULL || addr == NULL || graph != node->graph) { + return 0; + } else { + uip_ipaddr_t node_ipaddr; + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_ipaddr, node); + return uip_ipaddr_cmp(&node_ipaddr, addr); + } } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_get_node(const uip_ipaddr_t *addr) +uip_sr_node_t * +uip_sr_get_node(void *graph, const uip_ipaddr_t *addr) { - rpl_ns_node_t *l; + uip_sr_node_t *l; for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { /* Compare prefix and node identifier */ - if(node_matches_address(l, addr)) { + if(node_matches_address(graph, l, addr)) { return l; } } @@ -86,11 +90,17 @@ rpl_ns_get_node(const uip_ipaddr_t *addr) } /*---------------------------------------------------------------------------*/ int -rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr) +uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr) { - int max_depth = RPL_NS_LINK_NUM; - rpl_ns_node_t *node = rpl_ns_get_node(addr); - rpl_ns_node_t *root_node = rpl_ns_get_node(&curr_instance.dag.dag_id); + int max_depth = UIP_SR_LINK_NUM; + uip_ipaddr_t root_ipaddr; + uip_sr_node_t *node; + uip_sr_node_t *root_node; + + NETSTACK_ROUTING.get_root_ipaddr(&root_ipaddr); + node = uip_sr_get_node(graph, addr); + root_node = uip_sr_get_node(graph, &root_ipaddr); + while(node != NULL && node != root_node && max_depth > 0) { node = node->parent; max_depth--; @@ -99,26 +109,26 @@ rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr) } /*---------------------------------------------------------------------------*/ void -rpl_ns_expire_parent(const uip_ipaddr_t *child, const uip_ipaddr_t *parent) +uip_sr_expire_parent(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent) { - rpl_ns_node_t *l = rpl_ns_get_node(child); + uip_sr_node_t *l = uip_sr_get_node(graph, child); /* Check if parent matches */ - if(l != NULL && node_matches_address(l->parent, parent)) { - l->lifetime = RPL_NOPATH_REMOVAL_DELAY; + if(l != NULL && node_matches_address(graph, l->parent, parent)) { + l->lifetime = UIP_SR_REMOVAL_DELAY; } } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime) +uip_sr_node_t * +uip_sr_update_node(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime) { - rpl_ns_node_t *child_node = rpl_ns_get_node(child); - rpl_ns_node_t *parent_node = rpl_ns_get_node(parent); - rpl_ns_node_t *old_parent_node; + uip_sr_node_t *child_node = uip_sr_get_node(graph, child); + uip_sr_node_t *parent_node = uip_sr_get_node(graph, parent); + uip_sr_node_t *old_parent_node; if(parent != NULL) { /* No node for the parent, add one with infinite lifetime */ if(parent_node == NULL) { - parent_node = rpl_ns_update_node(parent, NULL, RPL_ROUTE_INFINITE_LIFETIME); + parent_node = uip_sr_update_node(graph, parent, NULL, UIP_SR_INFINITE_LIFETIME); if(parent_node == NULL) { LOG_ERR("NS: no space left for root node!\n"); return NULL; @@ -142,16 +152,17 @@ rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32 } /* Initialize node */ + child_node->graph = graph; child_node->lifetime = lifetime; memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8); /* Is the node reachable before the update? */ - if(rpl_ns_is_addr_reachable(child)) { + if(uip_sr_is_addr_reachable(graph, child)) { old_parent_node = child_node->parent; /* Update node */ child_node->parent = parent_node; /* Has the node become unreachable? May happen if we create a loop. */ - if(!rpl_ns_is_addr_reachable(child)) { + if(!uip_sr_is_addr_reachable(graph, child)) { /* The new parent makes the node unreachable, restore old parent. * We will take the update next time, with chances we know more of * the topology and the loop is gone. */ @@ -171,75 +182,63 @@ rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32 } /*---------------------------------------------------------------------------*/ void -rpl_ns_init(void) +uip_sr_init(void) { num_nodes = 0; memb_init(&nodememb); list_init(nodelist); } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_head(void) +uip_sr_node_t * +uip_sr_node_head(void) { return list_head(nodelist); } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_next(rpl_ns_node_t *item) +uip_sr_node_t * +uip_sr_node_next(uip_sr_node_t *item) { return list_item_next(item); } /*---------------------------------------------------------------------------*/ -int -rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node) -{ - if(addr != NULL && node != NULL) { - memcpy(addr, &curr_instance.dag.dag_id, 8); - memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); - return 1; - } else { - return 0; - } -} -/*---------------------------------------------------------------------------*/ void -rpl_ns_periodic(unsigned seconds) +uip_sr_periodic(unsigned seconds) { - rpl_ns_node_t *l; - rpl_ns_node_t *next; + uip_sr_node_t *l; + uip_sr_node_t *next; /* First pass, for all expired nodes, deallocate them iff no child points to them */ for(l = list_head(nodelist); l != NULL; l = next) { next = list_item_next(l); if(l->lifetime == 0) { - rpl_ns_node_t *l2; + uip_sr_node_t *l2; for(l2 = list_head(nodelist); l2 != NULL; l2 = list_item_next(l2)) { if(l2->parent == l) { break; } } -#if LOG_INFO_ENABLED - uip_ipaddr_t node_addr; - rpl_ns_get_node_global_addr(&node_addr, l); - LOG_INFO("NS: removing expired node "); - LOG_INFO_6ADDR(&node_addr); - LOG_INFO_("\n"); -#endif /* LOG_INFO_ENABLED */ + if(LOG_INFO_ENABLED) { + uip_ipaddr_t node_addr; + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, l); + LOG_INFO("NS: removing expired node "); + LOG_INFO_6ADDR(&node_addr); + LOG_INFO_("\n"); + } /* No child found, deallocate node */ list_remove(nodelist, l); memb_free(&nodememb, l); num_nodes--; - } else if(l->lifetime != RPL_ROUTE_INFINITE_LIFETIME) { + } else if(l->lifetime != UIP_SR_INFINITE_LIFETIME) { l->lifetime = l->lifetime > seconds ? l->lifetime - seconds : 0; } } } /*---------------------------------------------------------------------------*/ void -rpl_ns_free_all(void) +uip_sr_free_all(void) { - rpl_ns_node_t *l; - rpl_ns_node_t *next; + uip_sr_node_t *l; + uip_sr_node_t *next; for(l = list_head(nodelist); l != NULL; l = next) { next = list_item_next(l); list_remove(nodelist, l); diff --git a/os/net/rpl-lite/rpl-ns.h b/os/net/ipv6/uip-sr.h similarity index 57% rename from os/net/rpl-lite/rpl-ns.h rename to os/net/ipv6/uip-sr.h index 5f6e3d86d..7224cea14 100644 --- a/os/net/rpl-lite/rpl-ns.h +++ b/os/net/ipv6/uip-sr.h @@ -30,37 +30,75 @@ */ /** - * \addtogroup rpl-lite + * \addtogroup uip * @{ * * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. + * Source routing support * * \author Simon Duquennoy */ -#ifndef RPL_NS_H -#define RPL_NS_H +#ifndef UIP_SR_H +#define UIP_SR_H /********** Includes **********/ +#include "contiki.h" #include "net/ipv6/uip.h" -#include "net/rpl-lite/rpl.h" + +/********** Configuration **********/ + +/* The number of source routing nodes, i.e. the maximum netwrok size at the root */ +#ifdef UIP_SR_CONF_LINK_NUM + +#define UIP_SR_LINK_NUM UIP_SR_CONF_LINK_NUM + +#else /* UIP_SR_CONF_LINK_NUM */ + +#if ROUTING_CONF_RPL_LITE +#define UIP_SR_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES +#elif ROUTING_CONF_RPL_CLASSIC + +#include "net/routing/rpl-classic/rpl-conf.h" +#if RPL_WITH_NON_STORING +#define UIP_SR_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES +#else /* RPL_WITH_NON_STORING */ +#define UIP_SR_LINK_NUM 0 +#endif /* RPL_WITH_NON_STORING */ + +#else + +#define UIP_SR_LINK_NUM 0 + +#endif + +#endif /* UIP_SR_CONF_LINK_NUM */ + +/* Delay between between expiration order and actual node removal */ +#ifdef UIP_SR_CONF_REMOVAL_DELAY +#define UIP_SR_REMOVAL_DELAY UIP_SR_CONF_REMOVAL_DELAY +#else /* UIP_SR_CONF_REMOVAL_DELAY */ +#define UIP_SR_REMOVAL_DELAY 60 +#endif /* UIP_SR_CONF_REMOVAL_DELAY */ + +#define UIP_SR_INFINITE_LIFETIME 0xFFFFFFFF /********** Data Structures **********/ -/* A node in a RPL Non-storing graph, stored at the root and representing +/** \brief A node in a source routing graph, stored at the root and representing * all child-parent relationship. Used to build source routes */ -typedef struct rpl_ns_node { - struct rpl_ns_node *next; +typedef struct uip_sr_node { + struct uip_sr_node *next; uint32_t lifetime; - rpl_dag_t *dag; - /* Store only IPv6 link identifiers as all nodes in the DAG share the same prefix */ + /* Protocol-specific graph structure */ + void *graph; + /* Store only IPv6 link identifiers, the routing protocol will provide + us with the prefix */ unsigned char link_identifier[8]; - struct rpl_ns_node *parent; -} rpl_ns_node_t; + struct uip_sr_node *parent; +} uip_sr_node_t; /********** Public functions **********/ @@ -69,31 +107,33 @@ typedef struct rpl_ns_node { * * \return The number of nodes */ -int rpl_ns_num_nodes(void); +int uip_sr_num_nodes(void); /** * Expires a given child-parent link * + * \param graph The graph the link belongs to * \param child The IPv6 address of the child * \param parent The IPv6 address of the parent */ -void rpl_ns_expire_parent(const uip_ipaddr_t *child, const uip_ipaddr_t *parent); +void uip_sr_expire_parent(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent); /** * Updates a child-parent link * + * \param graph The graph the link belongs to * \param child The IPv6 address of the child * \param parent The IPv6 address of the parent * \param lifetime The link lifetime in seconds */ -rpl_ns_node_t *rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime); +uip_sr_node_t *uip_sr_update_node(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime); /** * Returns the head of the non-storing node list * * \return The head of the list */ -rpl_ns_node_t *rpl_ns_node_head(void); +uip_sr_node_t *uip_sr_node_head(void); /** * Returns the next element of the non-storing node list @@ -101,33 +141,26 @@ rpl_ns_node_t *rpl_ns_node_head(void); * \param item The current element in the list * \return The next element of the list */ -rpl_ns_node_t *rpl_ns_node_next(rpl_ns_node_t *item); +uip_sr_node_t *uip_sr_node_next(uip_sr_node_t *item); /** - * Looks up for a RPL NS node from its IPv6 global address + * Looks up for a source routing node from its IPv6 global address * + * \param graph The graph where to look up for the node * \param addr The target address * \return A pointer to the node */ -rpl_ns_node_t *rpl_ns_get_node(const uip_ipaddr_t *addr); +uip_sr_node_t *uip_sr_get_node(void *graph, const uip_ipaddr_t *addr); /** * Telle whether an address is reachable, i.e. if there exists a path from - * the root to the node in the current RPL NS graph + * the root to the node in the current source routing graph * + * \param graph The graph where to look up for the node * \param addr The target IPv6 global address * \return 1 if the node is reachable, 0 otherwise */ -int rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr); - -/** - * Finds the global address of a given node - * - * \param addr A pointer to the address to be written - * \param node The target node - * \return 1 if success, 0 otherwise -*/ -int rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node); +int uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr); /** * A function called periodically. Used to age the links (decrease lifetime @@ -135,18 +168,18 @@ int rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node); * * \param seconds The number of seconds elapsted since last call */ -void rpl_ns_periodic(unsigned seconds); +void uip_sr_periodic(unsigned seconds); /** - * Initialize rpl-ns module + * Initialize this module */ -void rpl_ns_init(void); +void uip_sr_init(void); /** * Deallocate all neighbors */ -void rpl_ns_free_all(void); +void uip_sr_free_all(void); /** @} */ -#endif /* RPL_NS_H */ +#endif /* UIP_SR_H */ diff --git a/os/net/ipv6/uip.h b/os/net/ipv6/uip.h index c3c9f2b38..7751b8fc3 100755 --- a/os/net/ipv6/uip.h +++ b/os/net/ipv6/uip.h @@ -500,7 +500,7 @@ typedef union { uint8_t u8[UIP_BUFSIZE]; } uip_buf_t; -CCIF extern uip_buf_t uip_aligned_buf; +extern uip_buf_t uip_aligned_buf; /** Macro to access uip_aligned_buf as an array of bytes */ #define uip_buf (uip_aligned_buf.u8) @@ -620,7 +620,7 @@ struct uip_conn *uip_connect(const uip_ipaddr_t *ripaddr, uint16_t port); * * \hideinitializer */ -CCIF void uip_send(const void *data, int len); +void uip_send(const void *data, int len); /** * The length of any incoming data that is currently available (if available) @@ -1238,14 +1238,14 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport); * network byte order, use the UIP_HTONS() macro instead. */ #ifndef uip_htons -CCIF uint16_t uip_htons(uint16_t val); +uint16_t uip_htons(uint16_t val); #endif /* uip_htons */ #ifndef uip_ntohs #define uip_ntohs uip_htons #endif #ifndef uip_htonl -CCIF uint32_t uip_htonl(uint32_t val); +uint32_t uip_htonl(uint32_t val); #endif /* uip_htonl */ #ifndef uip_ntohl #define uip_ntohl uip_htonl @@ -1260,7 +1260,7 @@ CCIF uint32_t uip_htonl(uint32_t val); * called. If the application wishes to send data, the application may * use this space to write the data into before calling uip_send(). */ -CCIF extern void *uip_appdata; +extern void *uip_appdata; #if UIP_URGDATA > 0 /* uint8_t *uip_urgdata: @@ -1295,7 +1295,7 @@ extern void *uip_urgdata; * packet. * */ -CCIF extern uint16_t uip_len; +extern uint16_t uip_len; /** * The length of the extension headers @@ -1367,10 +1367,10 @@ struct uip_conn { * connection. */ -CCIF extern struct uip_conn *uip_conn; +extern struct uip_conn *uip_conn; #if UIP_TCP /* The array containing all uIP connections. */ -CCIF extern struct uip_conn uip_conns[UIP_TCP_CONNS]; +extern struct uip_conn uip_conns[UIP_TCP_CONNS]; #endif /** @@ -1522,7 +1522,7 @@ struct uip_eth_hdr { * that are defined in this file. Please read below for more * information. */ -CCIF extern uint8_t uip_flags; +extern uint8_t uip_flags; /* The following flags may be set in the global variable uip_flags before calling the application callback. The UIP_ACKDATA, @@ -1934,17 +1934,17 @@ struct uip_udp_hdr { #if UIP_FIXEDADDR -CCIF extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; #else /* UIP_FIXEDADDR */ -CCIF extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; #endif /* UIP_FIXEDADDR */ -CCIF extern const uip_ipaddr_t uip_broadcast_addr; -CCIF extern const uip_ipaddr_t uip_all_zeroes_addr; +extern const uip_ipaddr_t uip_broadcast_addr; +extern const uip_ipaddr_t uip_all_zeroes_addr; #if UIP_FIXEDETHADDR -CCIF extern const uip_lladdr_t uip_lladdr; +extern const uip_lladdr_t uip_lladdr; #else -CCIF extern uip_lladdr_t uip_lladdr; +extern uip_lladdr_t uip_lladdr; #endif diff --git a/os/net/ipv6/uip6.c b/os/net/ipv6/uip6.c index 72384414a..de14486b9 100644 --- a/os/net/ipv6/uip6.c +++ b/os/net/ipv6/uip6.c @@ -79,15 +79,7 @@ #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/multicast/uip-mcast6.h" - -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif +#include "net/routing/routing.h" #if UIP_ND6_SEND_NS #include "net/ipv6/uip-ds6-nbr.h" @@ -161,9 +153,6 @@ uint8_t uip_ext_opt_offset = 0; #define UIP_DESTO_BUF ((struct uip_desto_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) -#if UIP_CONF_IPV6_RPL -#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) -#endif /* UIP_CONF_IPV6_RPL */ #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) /** @} */ /** @@ -883,13 +872,10 @@ ext_hdr_options_process(void) * Using this fix, the header is ignored, and the next header (if * present) is processed. */ -#if UIP_CONF_IPV6_RPL - LOG_DBG("Processing RPL option\n"); - if(!rpl_ext_header_hbh_update(uip_ext_opt_offset)) { + if(!NETSTACK_ROUTING.ext_header_hbh_update(uip_ext_opt_offset)) { LOG_ERR("RPL Option Error: Dropping Packet\n"); return 1; } -#endif /* UIP_CONF_IPV6_RPL */ uip_ext_opt_offset += (UIP_EXT_HDR_OPT_BUF->len) + 2; return 0; default: @@ -1363,8 +1349,7 @@ uip_process(uint8_t flag) LOG_DBG("Processing Routing header\n"); if(UIP_ROUTING_BUF->seg_left > 0) { -#if UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING - if(rpl_ext_header_srh_update()) { + if(NETSTACK_ROUTING.ext_header_srh_update()) { /* With routing header, the detination address is us and will * be swapped later to the next hop. Because of this, the MTU @@ -1392,7 +1377,6 @@ uip_process(uint8_t flag) goto send; /* Proceed to forwarding */ } -#endif /* UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING */ uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, UIP_IPH_LEN + uip_ext_len + 2); UIP_STAT(++uip_stat.ip.drop); LOG_ERR("unrecognized routing type"); diff --git a/os/net/ipv6/uiplib.c b/os/net/ipv6/uiplib.c index 4cc9179eb..693626c87 100644 --- a/os/net/ipv6/uiplib.c +++ b/os/net/ipv6/uiplib.c @@ -32,15 +32,27 @@ * */ +/** + * \file + * Various uIP library functions. + * \author + * Nicolas Tsiftes + * Niclas Finne + * Joakim Eriksson + */ #include "net/ipv6/uip.h" #include "net/ipv6/uiplib.h" +#include "net/ipv6/ip64-addr.h" #include +#include -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "uiplib" +#define LOG_LEVEL LOG_LEVEL_NONE -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #if NETSTACK_CONF_WITH_IPV6 int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) @@ -81,19 +93,19 @@ uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) } else if(c >= 'A' && c <= 'F') { tmp = c - 'A' + 10; } else { - PRINTF("uiplib: illegal char: '%c'\n", c); + LOG_ERR("illegal char: '%c'\n", c); return 0; } value = (value << 4) + (tmp & 0xf); } } if(c != '\0' && c != ']' && c != '/') { - PRINTF("uiplib: too large address\n"); + LOG_ERR("too large address\n"); return 0; } if(len < sizeof(uip_ip6addr_t)) { if(zero < 0) { - PRINTF("uiplib: too short address\n"); + LOG_ERR("too short address\n"); return 0; } memmove(&ipaddr->u8[zero + sizeof(uip_ip6addr_t) - len], @@ -104,7 +116,7 @@ uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) return 1; } #endif /* NETSTACK_CONF_WITH_IPV6 */ -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /* Parse a IPv4-address from a string. Returns the number of characters read * for the address. */ int @@ -138,6 +150,109 @@ uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *ipaddr) } while(c != '.' && c != 0 && c != ' '); } - return charsread-1; + return charsread - 1; } -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +void +uiplib_ipaddr_print(const uip_ipaddr_t *addr) +{ + uint16_t a; + unsigned int i; + int f; + + if(addr == NULL) { + printf("(NULL IP addr)"); + return; + } + + if(ip64_addr_is_ipv4_mapped_addr(addr)) { + /* + * Printing IPv4-mapped addresses is done according to RFC 4291 [1] + * + * "An alternative form that is sometimes more + * convenient when dealing with a mixed environment + * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, + * where the 'x's are the hexadecimal values of the + * six high-order 16-bit pieces of the address, and + * the 'd's are the decimal values of the four + * low-order 8-bit pieces of the address (standard + * IPv4 representation)." + * + * [1] https://tools.ietf.org/html/rfc4291#page-4 + */ + printf("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]); + } else { + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + printf("::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + printf(":"); + } + printf("%x", a); + } + } + } +} +/*---------------------------------------------------------------------------*/ +int +uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr) +{ + uint16_t a; + unsigned int i; + int f, n; + + if(size == 0) { + return 0; + } + + if(addr == NULL) { + n = snprintf(buf, size - 1, "(NULL IP addr)"); + + } else if(ip64_addr_is_ipv4_mapped_addr(addr)) { + /* + * Printing IPv4-mapped addresses is done according to RFC 4291 [1] + * + * "An alternative form that is sometimes more + * convenient when dealing with a mixed environment + * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, + * where the 'x's are the hexadecimal values of the + * six high-order 16-bit pieces of the address, and + * the 'd's are the decimal values of the four + * low-order 8-bit pieces of the address (standard + * IPv4 representation)." + * + * [1] https://tools.ietf.org/html/rfc4291#page-4 + */ + n = snprintf(buf, size - 1, "::FFFF:%u.%u.%u.%u", addr->u8[12], + addr->u8[13], addr->u8[14], addr->u8[15]); + } else { + for(n = 0, i = 0, f = 0; i < sizeof(uip_ipaddr_t) && n < size - 1; i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + buf[n++] = ':'; + buf[n++] = ':'; + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + buf[n++] = ':'; + } + n += snprintf(&buf[n], size - n - 1, "%x", a); + } + } + } + + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/ipv6/uiplib.h b/os/net/ipv6/uiplib.h index aa23435e0..6a122033e 100644 --- a/os/net/ipv6/uiplib.h +++ b/os/net/ipv6/uiplib.h @@ -73,8 +73,32 @@ #define uiplib_ipaddrconv uiplib_ip4addrconv #endif /* NETSTACK_CONF_WITH_IPV6 */ -CCIF int uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *addr); -CCIF int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *addr); +int uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *addr); +int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *addr); +/** @} */ + +/** + * \addtogroup uiplib + * @{ + */ + +/** + * Print an IP address using printf(). + * + * \param addr A pointer to a uip_ipaddr_t that will be printed with printf(). + */ +void uiplib_ipaddr_print(const uip_ipaddr_t *addr); + +/** + * Write at most size - 1 characters of the IP address to the output string. + * The output is always null-terminated, unless size is 0. + * + * \param buffer A pointer to an output string with at least size bytes. + * \param size The max number of characters to write to the output string. + * \param addr A pointer to a uip_ipaddr_t that will be printed with printf(). + */ +int uiplib_ipaddr_snprint(char *buffer, size_t size, const uip_ipaddr_t *addr); + /** @} */ #endif /* UIPLIB_H_ */ diff --git a/os/net/mac/csma/csma-output.c b/os/net/mac/csma/csma-output.c index 0bbc34fb0..74803ecf1 100644 --- a/os/net/mac/csma/csma-output.c +++ b/os/net/mac/csma/csma-output.c @@ -66,14 +66,14 @@ #ifdef CSMA_CONF_MIN_BE #define CSMA_MIN_BE CSMA_CONF_MIN_BE #else -#define CSMA_MIN_BE 0 +#define CSMA_MIN_BE 3 #endif /* macMaxBE: Maximum backoff exponent. Range 3--8 */ #ifdef CSMA_CONF_MAX_BE #define CSMA_MAX_BE CSMA_CONF_MAX_BE #else -#define CSMA_MAX_BE 4 +#define CSMA_MAX_BE 5 #endif /* macMaxCSMABackoffs: Maximum number of backoffs in case of channel busy/collision. Range 0--5 */ @@ -154,9 +154,15 @@ neighbor_queue_from_addr(const linkaddr_t *addr) static clock_time_t backoff_period(void) { +#if CONTIKI_TARGET_COOJA + /* Increase normal value by 20 to compensate for the coarse-grained + radio medium with Cooja motes */ + return MAX(20 * CLOCK_SECOND / 3125, 1); +#else /* CONTIKI_TARGET_COOJA */ /* Use the default in IEEE 802.15.4: aUnitBackoffPeriod which is * 20 symbols i.e. 320 usec. That is, 1/3125 second. */ return MAX(CLOCK_SECOND / 3125, 1); +#endif /* CONTIKI_TARGET_COOJA */ } /*---------------------------------------------------------------------------*/ static int @@ -281,7 +287,7 @@ schedule_transmission(struct neighbor_queue *n) clock_time_t delay; int backoff_exponent; /* BE in IEEE 802.15.4 */ - backoff_exponent = MIN(n->collisions, CSMA_MAX_BE); + backoff_exponent = MIN(n->collisions + CSMA_MIN_BE, CSMA_MAX_BE); /* Compute max delay as per IEEE 802.15.4: 2^BE-1 backoff periods */ delay = ((1 << backoff_exponent) - 1) * backoff_period(); @@ -310,7 +316,7 @@ free_packet(struct neighbor_queue *n, struct packet_queue *p, int status) if(list_head(n->packet_queue) != NULL) { /* There is a next packet. We reset current tx information */ n->transmissions = 0; - n->collisions = CSMA_MIN_BE; + n->collisions = 0; /* Schedule next transmissions */ schedule_transmission(n); } else { @@ -365,7 +371,7 @@ collision(struct packet_queue *q, struct neighbor_queue *n, n->collisions += num_transmissions; if(n->collisions > CSMA_MAX_BACKOFF) { - n->collisions = CSMA_MIN_BE; + n->collisions = 0; /* Increment to indicate a next retry */ n->transmissions++; } @@ -384,7 +390,7 @@ noack(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions) metadata = (struct qbuf_metadata *)q->ptr; - n->collisions = CSMA_MIN_BE; + n->collisions = 0; n->transmissions += num_transmissions; if(n->transmissions >= metadata->max_transmissions) { diff --git a/os/net/mac/framer/nullframer.c b/os/net/mac/framer/nullframer.c index 3df8f6ea1..019ed2209 100644 --- a/os/net/mac/framer/nullframer.c +++ b/os/net/mac/framer/nullframer.c @@ -36,7 +36,27 @@ * Joakim Eriksson */ #include "net/mac/framer/framer.h" +#include "net/packetbuf.h" +#ifdef NULLFRAMER_CONF_PARSE_802154 +#define NULLFRAMER_PARSE_802154 NULLFRAMER_CONF_PARSE_802154 +#else +/* defaults to parsing of the 802154 header as that is used for Slip-Radio */ +#define NULLFRAMER_PARSE_802154 1 +#endif + +/*---------------------------------------------------------------------------*/ +static int +is_broadcast_addr(uint8_t mode, uint8_t *addr) +{ + int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8; + while(i-- > 0) { + if(addr[i] != 0xff) { + return 0; + } + } + return 1; +} /*---------------------------------------------------------------------------*/ static int hdr_length(void) @@ -55,6 +75,21 @@ create(void) static int parse(void) { +#if NULLFRAMER_PARSE_802154 + frame802154_t frame; + int len; + len = packetbuf_datalen(); + if(frame802154_parse(packetbuf_dataptr(), len, &frame)) { + if(frame.fcf.dest_addr_mode) { + if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); + } + } + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); + packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); + return 0; + } +#endif return 0; } /*---------------------------------------------------------------------------*/ diff --git a/os/net/mac/tsch/tsch-log.c b/os/net/mac/tsch/tsch-log.c index 9235d9d7d..fdaaf3b53 100644 --- a/os/net/mac/tsch/tsch-log.c +++ b/os/net/mac/tsch/tsch-log.c @@ -85,10 +85,10 @@ tsch_log_process_pending(void) while((log_index = ringbufindex_peek_get(&log_ringbuf)) != -1) { struct tsch_log_t *log = &log_array[log_index]; if(log->link == NULL) { - printf("[INFO: TSCH-LOG ] {asn-%x.%lx link-NULL} ", log->asn.ms1b, log->asn.ls4b); + printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link-NULL} ", log->asn.ms1b, log->asn.ls4b); } else { struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle); - printf("[INFO: TSCH-LOG ] {asn-%x.%lx link-%u-%u-%u-%u ch-%u} ", + printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link %2u %3u %3u %2u ch %2u} ", log->asn.ms1b, log->asn.ls4b, log->link->slotframe_handle, sf ? sf->size.val : 0, log->link->timeslot, log->link->channel_offset, tsch_calculate_channel(&log->asn, log->link->channel_offset)); @@ -100,10 +100,10 @@ tsch_log_process_pending(void) log_lladdr_compact(&linkaddr_node_addr); printf("->"); log_lladdr_compact(&log->tx.dest); - printf(", len %u, seq %u, st %d %d", + printf(", len %3u, seq %3u, st %d %2d", log->tx.datalen, log->tx.seqno, log->tx.mac_tx_status, log->tx.num_tx); if(log->tx.drift_used) { - printf(", dr %d", log->tx.drift); + printf(", dr %3d", log->tx.drift); } printf("\n"); break; @@ -113,12 +113,14 @@ tsch_log_process_pending(void) log_lladdr_compact(&log->rx.src); printf("->"); log_lladdr_compact(log->rx.is_unicast ? &linkaddr_node_addr : NULL); - printf(", len %u, seq %u", + printf(", len %3u, seq %3u", log->rx.datalen, log->rx.seqno); + printf(", edr %3d", (int)log->rx.estimated_drift); if(log->rx.drift_used) { - printf(", dr %d", log->rx.drift); + printf(", dr %3d\n", log->rx.drift); + } else { + printf("\n"); } - printf(", edr %d\n", (int)log->rx.estimated_drift); break; case tsch_log_message: printf("%s\n", log->message); diff --git a/os/net/mac/tsch/tsch-private.h b/os/net/mac/tsch/tsch-private.h index ec114813e..fc5559b38 100644 --- a/os/net/mac/tsch/tsch-private.h +++ b/os/net/mac/tsch/tsch-private.h @@ -53,10 +53,10 @@ #include "net/linkaddr.h" #include "net/mac/tsch/tsch-asn.h" #include "net/mac/tsch/tsch-conf.h" -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA #include "lib/simEnvChange.h" #include "sys/cooja_mt.h" -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ /************ Types ***********/ @@ -94,9 +94,9 @@ extern struct tsch_asn_divisor_t tsch_hopping_sequence_length; /* TSCH timeslot timing (in rtimer ticks) */ extern rtimer_clock_t tsch_timing[tsch_ts_elements_count]; /* Statistics on the current session */ -unsigned long tx_count; -unsigned long rx_count; -unsigned long sync_count; +extern unsigned long tx_count; +extern unsigned long rx_count; +extern unsigned long sync_count; /* TSCH processes */ PROCESS_NAME(tsch_process); @@ -124,7 +124,7 @@ void tsch_disassociate(void); #define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length) /* Wait for a condition with timeout t0+offset. */ -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA #define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \ simProcessRunValue = 1; \ @@ -133,6 +133,6 @@ void tsch_disassociate(void); #else #define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ; -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ #endif /* __TSCH_PRIVATE_H__ */ /** @} */ diff --git a/os/net/mac/tsch/tsch-rpl.c b/os/net/mac/tsch/tsch-rpl.c index ec3f24d8b..bc54de99c 100644 --- a/os/net/mac/tsch/tsch-rpl.c +++ b/os/net/mac/tsch/tsch-rpl.c @@ -40,21 +40,23 @@ * @{ */ +#include "contiki.h" + #if UIP_CONF_IPV6_RPL -#include "contiki.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" #include "net/mac/tsch/tsch.h" #include "net/mac/tsch/tsch-private.h" #include "net/mac/tsch/tsch-schedule.h" #include "net/mac/tsch/tsch-log.h" #include "net/mac/tsch/tsch-rpl.h" -#include "tsch-rpl.h" + +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" +#endif /* Log configuration */ #include "sys/log.h" @@ -66,7 +68,7 @@ void tsch_rpl_callback_ka_sent(int status, int transmissions) { - rpl_link_callback(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), status, transmissions); + NETSTACK_ROUTING.link_callback(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), status, transmissions); } /*---------------------------------------------------------------------------*/ /* To use, set #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network */ @@ -81,14 +83,7 @@ tsch_rpl_callback_joining_network(void) void tsch_rpl_callback_leaving_network(void) { - rpl_dag_t *dag = rpl_get_any_dag(); - if(dag != NULL) { -#if UIP_CONF_IPV6_RPL_LITE - rpl_local_repair("TSCH leaving"); -#else - rpl_local_repair(dag->instance); -#endif - } + NETSTACK_ROUTING.local_repair("TSCH leaving"); } /*---------------------------------------------------------------------------*/ /* Set TSCH EB period based on current RPL DIO period. @@ -100,7 +95,7 @@ tsch_rpl_callback_new_dio_interval(clock_time_t dio_interval) rpl_dag_t *dag; rpl_rank_t root_rank; rpl_rank_t dag_rank; -#if UIP_CONF_IPV6_RPL_LITE +#if ROUTING_CONF_RPL_LITE dag = &curr_instance.dag; root_rank = ROOT_RANK; dag_rank = DAG_RANK(dag->rank); diff --git a/os/net/mac/tsch/tsch-rpl.h b/os/net/mac/tsch/tsch-rpl.h index 15be760f5..41fa17e91 100644 --- a/os/net/mac/tsch/tsch-rpl.h +++ b/os/net/mac/tsch/tsch-rpl.h @@ -38,12 +38,13 @@ /********** Includes **********/ -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" #include "net/mac/tsch/tsch-queue.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif /********** Functions *********/ diff --git a/os/net/mac/tsch/tsch-schedule.c b/os/net/mac/tsch/tsch-schedule.c index dd31afecd..193827f44 100644 --- a/os/net/mac/tsch/tsch-schedule.c +++ b/os/net/mac/tsch/tsch-schedule.c @@ -452,16 +452,15 @@ tsch_schedule_print(void) if(!tsch_is_locked()) { struct tsch_slotframe *sf = list_head(slotframe_list); - printf("Schedule: slotframe list\n"); + LOG_PRINT("----- start slotframe list -----\n"); while(sf != NULL) { struct tsch_link *l = list_head(sf->links_list); - printf("[Slotframe] Handle %u, size %u\n", sf->handle, sf->size.val); - printf("List of links:\n"); + LOG_PRINT("Slotframe Handle %u, size %u\n", sf->handle, sf->size.val); while(l != NULL) { - printf("[Link] Options %02x, type %u, timeslot %u, channel offset %u, address %u\n", + LOG_PRINT("* Link Options %02x, type %u, timeslot %u, channel offset %u, address %u\n", l->link_options, l->link_type, l->timeslot, l->channel_offset, l->addr.u8[7]); l = list_item_next(l); } @@ -469,7 +468,7 @@ tsch_schedule_print(void) sf = list_item_next(sf); } - printf("Schedule: end of slotframe list\n"); + LOG_PRINT("----- end slotframe list -----\n"); } } /*---------------------------------------------------------------------------*/ diff --git a/os/net/mac/tsch/tsch-slot-operation.c b/os/net/mac/tsch/tsch-slot-operation.c index 3596b913c..5fcd969d3 100644 --- a/os/net/mac/tsch/tsch-slot-operation.c +++ b/os/net/mac/tsch/tsch-slot-operation.c @@ -59,10 +59,10 @@ #include "net/mac/tsch/tsch-packet.h" #include "net/mac/tsch/tsch-security.h" #include "net/mac/tsch/tsch-adaptive-timesync.h" -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA #include "lib/simEnvChange.h" #include "sys/cooja_mt.h" -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ #include "sys/log.h" /* TSCH debug macros, i.e. to set LEDs or GPIOs on various TSCH @@ -107,7 +107,7 @@ #if RTIMER_SECOND < (32 * 1024) #error "TSCH: RTIMER_SECOND < (32 * 1024)" #endif -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA /* Use 0 usec guard time for Cooja Mote with a 1 MHz Rtimer*/ #define RTIMER_GUARD 0u #elif RTIMER_SECOND >= 200000 @@ -208,10 +208,10 @@ tsch_get_lock(void) busy_wait = 1; busy_wait_time = RTIMER_NOW(); while(tsch_in_slot_operation) { -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA simProcessRunValue = 1; cooja_mt_yield(); -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ } busy_wait_time = RTIMER_NOW() - busy_wait_time; } @@ -297,15 +297,16 @@ tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_ "!dl-miss %s %d %d", str, (int)(now-ref_time), (int)offset); ); + } else { + r = rtimer_set(tm, ref_time + offset, 1, (void (*)(struct rtimer *, void *))tsch_slot_operation, NULL); + if(r == RTIMER_OK) { + return 1; + } + } - return 0; - } - ref_time += offset; - r = rtimer_set(tm, ref_time, 1, (void (*)(struct rtimer *, void *))tsch_slot_operation, NULL); - if(r != RTIMER_OK) { - return 0; - } - return 1; + /* block until the time to schedule comes */ + BUSYWAIT_UNTIL_ABS(0, ref_time, offset); + return 0; } /*---------------------------------------------------------------------------*/ /* Schedule slot operation conditionally, and YIELD if success only. @@ -315,8 +316,8 @@ tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_ do { \ if(tsch_schedule_slot_operation(tm, ref_time, offset - RTIMER_GUARD, str)) { \ PT_YIELD(pt); \ + BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \ } \ - BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \ } while(0); /*---------------------------------------------------------------------------*/ /* Get EB, broadcast or unicast packet to be sent, and target neighbor. */ @@ -1010,12 +1011,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr)) TSCH_ASN_INC(tsch_current_asn, timeslot_diff); /* Time to next wake up */ time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length] + drift_correction; + time_to_next_active_slot += tsch_timesync_adaptive_compensate(time_to_next_active_slot); drift_correction = 0; is_drift_correction_used = 0; /* Update current slot start */ prev_slot_start = current_slot_start; current_slot_start += time_to_next_active_slot; - current_slot_start += tsch_timesync_adaptive_compensate(time_to_next_active_slot); } while(!tsch_schedule_slot_operation(t, prev_slot_start, time_to_next_active_slot, "main")); } diff --git a/os/net/mac/tsch/tsch.c b/os/net/mac/tsch/tsch.c index 6d60f097a..9d0affb8a 100644 --- a/os/net/mac/tsch/tsch.c +++ b/os/net/mac/tsch/tsch.c @@ -60,12 +60,12 @@ #include "net/mac/tsch/tsch-log.h" #include "net/mac/tsch/tsch-packet.h" #include "net/mac/tsch/tsch-security.h" -#include "net/mac/mac-sequence.h" -#include "lib/random.h" - #if UIP_CONF_IPV6_RPL #include "net/mac/tsch/tsch-rpl.h" #endif /* UIP_CONF_IPV6_RPL */ +#include "net/mac/mac-sequence.h" +#include "lib/random.h" +#include "net/routing/routing.h" #if TSCH_WITH_SIXTOP #include "net/mac/tsch/sixtop/sixtop.h" diff --git a/os/net/netstack.h b/os/net/netstack.h index b7a439940..8528e3fff 100644 --- a/os/net/netstack.h +++ b/os/net/netstack.h @@ -43,6 +43,22 @@ #include "contiki.h" +/* Routing protocol configuration. The Routing protocol is configured through the Makefile, + via the flag MAC_ROUTING */ +#ifdef NETSTACK_CONF_ROUTING +#define NETSTACK_ROUTING NETSTACK_CONF_ROUTING +#else /* NETSTACK_CONF_ROUTING */ +#if ROUTING_CONF_RPL_LITE +#define NETSTACK_ROUTING rpl_lite_driver +#elif ROUTING_CONF_RPL_CLASSIC +#define NETSTACK_ROUTING rpl_classic_driver +#elif ROUTING_CONF_NULLROUTING +#define NETSTACK_ROUTING nullrouting_driver +#else +#error Unknown ROUTING configuration +#endif +#endif /* NETSTACK_CONF_ROUTING */ + /* Network layer configuration. The NET layer is configured through the Makefile, via the flag MAC_NET */ #ifdef NETSTACK_CONF_NETWORK @@ -111,6 +127,7 @@ struct network_driver { uint8_t (*output)(const linkaddr_t *localdest); }; +extern const struct routing_driver NETSTACK_ROUTING; extern const struct network_driver NETSTACK_NETWORK; extern const struct mac_driver NETSTACK_MAC; extern const struct radio_driver NETSTACK_RADIO; diff --git a/os/net/routing/nullrouting/nullrouting.c b/os/net/routing/nullrouting/nullrouting.c new file mode 100644 index 000000000..14c328b0c --- /dev/null +++ b/os/net/routing/nullrouting/nullrouting.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017, 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. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup null-routing + * @{ + * + * \file + * A routing protocol that does nothing + * + * \author Simon Duquennoy + */ + +#include "net/routing/routing.h" + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +static void +root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) +{ +} +/*---------------------------------------------------------------------------*/ +static int +root_start(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +node_is_root(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +get_root_ipaddr(uip_ipaddr_t *ipaddr) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +leave_network(void) +{ +} +/*---------------------------------------------------------------------------*/ +static int +node_has_joined(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +node_is_reachable(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +global_repair(const char *str) +{ +} +/*---------------------------------------------------------------------------*/ +static void +local_repair(const char *str) +{ +} +/*---------------------------------------------------------------------------*/ +static void +ext_header_remove(void) +{ + uip_ext_len = 0; +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_update(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_hbh_update(int uip_ext_opt_offset) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_srh_update(void) +{ + return 0; /* Means SRH not found */ +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +link_callback(const linkaddr_t *addr, int status, int numtx) +{ +} +/*---------------------------------------------------------------------------*/ +static void +neighbor_state_changed(uip_ds6_nbr_t *nbr) +{ +} +/*---------------------------------------------------------------------------*/ +static void +drop_route(uip_ds6_route_t *route) +{ +} +/*---------------------------------------------------------------------------*/ +const struct routing_driver nullrouting_driver = { + "Null Routing", + init, + root_set_prefix, + root_start, + node_is_root, + get_root_ipaddr, + get_sr_node_ipaddr, + leave_network, + node_has_joined, + node_is_reachable, + global_repair, + local_repair, + ext_header_remove, + ext_header_update, + ext_header_hbh_update, + ext_header_srh_update, + ext_header_srh_get_next_hop, + link_callback, + neighbor_state_changed, + drop_route, +}; +/*---------------------------------------------------------------------------*/ + +/** @}*/ diff --git a/os/net/routing/routing.h b/os/net/routing/routing.h new file mode 100644 index 000000000..7fe6e7ca8 --- /dev/null +++ b/os/net/routing/routing.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017, 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. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Routing driver header file + * \author + * Simon Duquennoy + */ + +#ifndef ROUTING_H_ +#define ROUTING_H_ + +#include "contiki.h" +#include "net/ipv6/uip.h" +#include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-ds6-route.h" +#include "net/ipv6/uip-sr.h" +#include "net/linkaddr.h" + +/** + * The structure of a routing protocol driver. + */ +struct routing_driver { + char *name; + /** Initialize the routing protocol */ + void (* init)(void); + /** + * Set the prefix, for nodes that will operate as root + * + * \param prefix The prefix. If NULL, UIP_DS6_DEFAULT_PREFIX is used instead + * \param iid The IID. If NULL, it will be built from uip_ds6_set_addr_iid. + */ + void (* root_set_prefix)(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); + /** + * Set the node as root and start a network + * + * \return 0 in case of success, -1 otherwise + */ + int (* root_start)(void); + /** + * Tells whether the node is a network root or not + * + * \return 1 if we are root, 0 otherwise + */ + int (* node_is_root)(void); + /** + * Returns the IPv6 address of the network root, if any + * + * \param ipaddr A pointer where to copy the IP address of the root + * \return 1 if the root address was copied, 0 otherwise + */ + int (* get_root_ipaddr)(uip_ipaddr_t *ipaddr); + /** + * Returns the global IPv6 address of a source routing node + * + * \param ipaddr A pointer where to copy the IP address of the node + * \param node The source routing node + * \return 1 if the global node address was copied, 0 otherwise + */ + int (* get_sr_node_ipaddr)(uip_ipaddr_t *addr, const uip_sr_node_t *node); + /** + * Leave the network the node is part of + * + */ + void (* leave_network)(void); + /** + * Tells whether the node is currently part of a network + * + * \return 1 if we have joined a network, 0 otherwise. + */ + int (* node_has_joined)(void); + /** + * Tells whether the node is currently reachable as part of the network + * + * \return 1 if we are reachable, 0 otherwise. + */ + int (* node_is_reachable)(void); + /** + * Triggers a global topology repair + * + * \param str A textual description of the cause for triggering a repair + */ + void (* global_repair)(const char *str); + /** + * Triggers a RPL local topology repair + * + * \param str A textual description of the cause for triggering a repair + */ + void (* local_repair)(const char *str); + /** + * Removes all extension headers that pertain to the routing protocol. + */ + void (* ext_header_remove)(void); + /** + * Adds/updates routing protocol extension headers to current uIP packet. + * + * \return 1 in case of success, 0 otherwise + */ + int (* ext_header_update)(void); + /** + * Process and update the routing protocol hob-by-hop + * extention headers of the current uIP packet. + * + * \param uip_ext_opt_offset The offset within the uIP packet where + * extension headers start + * \return 1 in case the packet is valid and to be processed further, + * 0 in case the packet must be dropped. + */ + int (* ext_header_hbh_update)(int uip_ext_opt_offset); + /** + * Process and update SRH in-place, + * i.e. internal address swapping as per RFC6554 + * \return 1 if SRH found, 0 otherwise + */ + int (* ext_header_srh_update)(void); + /** + * Look for next hop from SRH of current uIP packet. + * + * \param ipaddr A pointer to the address where to store the next hop. + * \return 1 if a next hop was found, 0 otherwise + */ + int (* ext_header_srh_get_next_hop)(uip_ipaddr_t *ipaddr); + /** + * Called by lower layers after every packet transmission + * + * \param addr The link-layer addrress of the packet destination + * \param status The transmission status (see os/net/mac/mac.h) + * \param numtx The total number of transmission attempts + */ + void (* link_callback)(const linkaddr_t *addr, int status, int numtx); + /** + * Called by uIP to notify addition/removal of IPv6 neighbor entries + * + * \param addr The link-layer addrress of the packet destination + * \param status The transmission status (see os/net/mac/mac.h) + * \param numtx The total number of transmission attempts + */ + void (* neighbor_state_changed)(uip_ds6_nbr_t *nbr); + /** + * Called by uIP if it has decided to drop a route because + * + * \param route The route that will be dropped after this function returns + */ + void (* drop_route)(uip_ds6_route_t *route); +}; + +#endif /* ROUTING_H_ */ diff --git a/os/net/rpl-classic/rpl-conf.h b/os/net/routing/rpl-classic/rpl-conf.h similarity index 100% rename from os/net/rpl-classic/rpl-conf.h rename to os/net/routing/rpl-classic/rpl-conf.h diff --git a/os/net/rpl-classic/rpl-dag-root.c b/os/net/routing/rpl-classic/rpl-dag-root.c similarity index 54% rename from os/net/rpl-classic/rpl-dag-root.c rename to os/net/routing/rpl-classic/rpl-dag-root.c index 96d00f6e1..05adff4de 100644 --- a/os/net/rpl-classic/rpl-dag-root.c +++ b/os/net/routing/rpl-classic/rpl-dag-root.c @@ -32,9 +32,8 @@ #include "contiki.h" #include "contiki-net.h" -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-dag-root.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/ipv6/uip-ds6-route.h" #include @@ -42,105 +41,6 @@ #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" -#define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1) - -#if (UIP_MAX_ROUTES != 0) -static struct uip_ds6_notification n; -#endif /* (UIP_MAX_ROUTES != 0) */ -static uint8_t to_become_root; -static struct ctimer c; -/*---------------------------------------------------------------------------*/ -static const uip_ipaddr_t * -dag_root(void) -{ - rpl_dag_t *dag; - - dag = rpl_get_any_dag(); - if(dag != NULL) { - return &dag->dag_id; - } - - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const uip_ipaddr_t * -get_global_address(void) -{ - int i; - uint8_t state; - uip_ipaddr_t *ipaddr = NULL; - - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - state == ADDR_PREFERRED && - !uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr)) { - ipaddr = &uip_ds6_if.addr_list[i].ipaddr; - } - } - return ipaddr; -} -/*---------------------------------------------------------------------------*/ -static void -create_dag_callback(void *ptr) -{ - const uip_ipaddr_t *root, *ipaddr; - - root = dag_root(); - ipaddr = get_global_address(); - - if(root == NULL || uip_ipaddr_cmp(root, ipaddr)) { - /* The RPL network we are joining is one that we created, so we - become root. */ - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } else { - rpl_dag_t *dag; - - dag = rpl_get_any_dag(); -#if DEBUG - printf("Found a network we did not create\n"); - printf("version %d grounded %d preference %d used %d joined %d rank %d\n", - dag->version, dag->grounded, - dag->preference, dag->used, - dag->joined, dag->rank); -#endif /* DEBUG */ - - /* We found a RPL network that we did not create so we just join - it without becoming root. But if the network has an infinite - rank, we assume the network has broken, and we become the new - root of the network. */ - - if(dag->rank == RPL_INFINITE_RANK) { - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } - - /* Try again after the grace period */ - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - } -} -#if (UIP_MAX_ROUTES != 0) -/*---------------------------------------------------------------------------*/ -static void -route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, - int numroutes) -{ - if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD) { - if(route != NULL && ipaddr != NULL && - !uip_is_addr_unspecified(route) && - !uip_is_addr_unspecified(ipaddr)) { - if(to_become_root) { - ctimer_set(&c, 0, create_dag_callback, NULL); - } - } - } -} -#endif /* (UIP_MAX_ROUTES != 0) */ /*---------------------------------------------------------------------------*/ static void set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) @@ -176,29 +76,25 @@ set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) } /*---------------------------------------------------------------------------*/ void -rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) +rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) { static uint8_t initialized = 0; if(!initialized) { - to_become_root = 0; set_global_address(prefix, iid); -#if (UIP_MAX_ROUTES != 0) - uip_ds6_notification_add(&n, route_callback); -#endif /* (UIP_MAX_ROUTES != 0) */ initialized = 1; } } /*---------------------------------------------------------------------------*/ int -rpl_dag_root_init_dag_immediately(void) +rpl_dag_root_start(void) { struct uip_ds6_addr *root_if; int i; uint8_t state; uip_ipaddr_t *ipaddr = NULL; - rpl_dag_root_init(NULL, NULL); + rpl_dag_root_set_prefix(NULL, NULL); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; @@ -223,38 +119,25 @@ rpl_dag_root_init_dag_immediately(void) if(RPL_IS_STORING(dag->instance)) { rpl_remove_routes(dag); } - if(dag->instance != NULL && - dag->instance->def_route != NULL) { - uip_ds6_defrt_rm(dag->instance->def_route); + if(dag->instance != NULL && dag->instance->def_route != NULL) { + uip_ds6_defrt_rm(dag->instance->def_route); dag->instance->def_route = NULL; } uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &prefix, 64); - PRINTF("rpl_dag_root_init_dag: created a new RPL dag\n"); + PRINTF("rpl_dag_root_set_prefix_dag: created a new RPL dag\n"); return 0; } else { - PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG\n"); + PRINTF("rpl_dag_root_set_prefix_dag: failed to create a new RPL DAG\n"); return -1; } } else { - PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG, no preferred IP address found\n"); + PRINTF("rpl_dag_root_set_prefix_dag: failed to create a new RPL DAG, no preferred IP address found\n"); return -2; } } /*---------------------------------------------------------------------------*/ -void -rpl_dag_root_init_dag_delay(void) -{ - rpl_dag_root_init(NULL, NULL); - - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - to_become_root = 1; - - /* Send a DIS packet to request RPL info from neighbors. */ - dis_output(NULL); -} -/*---------------------------------------------------------------------------*/ int rpl_dag_root_is_root(void) { diff --git a/os/net/rpl-classic/rpl-dag-root.h b/os/net/routing/rpl-classic/rpl-dag-root.h similarity index 92% rename from os/net/rpl-classic/rpl-dag-root.h rename to os/net/routing/rpl-classic/rpl-dag-root.h index 05daec15b..9d2d09b02 100644 --- a/os/net/rpl-classic/rpl-dag-root.h +++ b/os/net/routing/rpl-classic/rpl-dag-root.h @@ -32,9 +32,8 @@ #ifndef RPL_DAG_ROOT_H_ #define RPL_DAG_ROOT_H_ -void rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); -void rpl_dag_root_init_dag_delay(void); -int rpl_dag_root_init_dag_immediately(void); +void rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); +int rpl_dag_root_start(void); int rpl_dag_root_is_root(void); diff --git a/os/net/rpl-classic/rpl-dag.c b/os/net/routing/rpl-classic/rpl-dag.c similarity index 99% rename from os/net/rpl-classic/rpl-dag.c rename to os/net/routing/rpl-classic/rpl-dag.c index aeed6194e..899322264 100644 --- a/os/net/rpl-classic/rpl-dag.c +++ b/os/net/routing/rpl-classic/rpl-dag.c @@ -45,7 +45,9 @@ #include "contiki.h" #include "net/link-stats.h" -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl-dag-root.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6-nbr.h" @@ -1004,9 +1006,18 @@ rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) } /*---------------------------------------------------------------------------*/ int +rpl_has_joined(void) +{ + return rpl_get_any_dag() != NULL; +} +/*---------------------------------------------------------------------------*/ +int rpl_has_downward_route(void) { int i; + if(rpl_dag_root_is_root()) { + return 1; /* We are the root, and know the route to ourself */ + } for(i = 0; i < RPL_MAX_INSTANCES; ++i) { if(instance_table[i].used && instance_table[i].has_downward_route) { return 1; diff --git a/os/net/rpl-classic/rpl-ext-header.c b/os/net/routing/rpl-classic/rpl-ext-header.c similarity index 96% rename from os/net/rpl-classic/rpl-ext-header.c rename to os/net/routing/rpl-classic/rpl-ext-header.c index 083d26741..e6498b993 100644 --- a/os/net/rpl-classic/rpl-ext-header.c +++ b/os/net/routing/rpl-classic/rpl-ext-header.c @@ -44,11 +44,12 @@ * @{ */ +#include "net/routing/routing.h" #include "net/ipv6/uip.h" #include "net/ipv6/tcpip.h" #include "net/ipv6/uip-ds6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/ipv6/uip-sr.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/packetbuf.h" #define DEBUG DEBUG_NONE @@ -174,15 +175,15 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset) return 1; } /*---------------------------------------------------------------------------*/ -#if RPL_WITH_NON_STORING int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) { +#if RPL_WITH_NON_STORING uint8_t *uip_next_hdr; int last_uip_ext_len = uip_ext_len; rpl_dag_t *dag; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; uip_ext_len = 0; uip_next_hdr = &UIP_IP_BUF->proto; @@ -208,8 +209,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) } dag = rpl_get_dag(&UIP_IP_BUF->destipaddr); - root_node = rpl_ns_get_node(dag, &dag->dag_id); - dest_node = rpl_ns_get_node(dag, &UIP_IP_BUF->destipaddr); + root_node = uip_sr_get_node(dag, &dag->dag_id); + dest_node = uip_sr_get_node(dag, &UIP_IP_BUF->destipaddr); if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) || @@ -227,11 +228,15 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) uip_ext_len = last_uip_ext_len; return 0; +#else /* RPL_WITH_NON_STORING */ + return 0; /* SRH not found */ +#endif /* RPL_WITH_NON_STORING */ } /*---------------------------------------------------------------------------*/ int rpl_ext_header_srh_update(void) { +#if RPL_WITH_NON_STORING uint8_t *uip_next_hdr; int last_uip_ext_len = uip_ext_len; @@ -308,6 +313,9 @@ rpl_ext_header_srh_update(void) uip_ext_len = last_uip_ext_len; return 0; +#else /* RPL_WITH_NON_STORING */ + return 0; /* SRH not found */ +#endif /* RPL_WITH_NON_STORING */ } /*---------------------------------------------------------------------------*/ static int @@ -332,9 +340,9 @@ insert_srh_header(void) uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */ uint8_t *hop_ptr; uint8_t padding; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; - rpl_ns_node_t *node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; + uip_sr_node_t *node; rpl_dag_t *dag; uip_ipaddr_t node_addr; @@ -352,19 +360,19 @@ insert_srh_header(void) return 0; } - dest_node = rpl_ns_get_node(dag, &UIP_IP_BUF->destipaddr); + dest_node = uip_sr_get_node(dag, &UIP_IP_BUF->destipaddr); if(dest_node == NULL) { /* The destination is not found, skip SRH insertion */ return 1; } - root_node = rpl_ns_get_node(dag, &dag->dag_id); + root_node = uip_sr_get_node(dag, &dag->dag_id); if(root_node == NULL) { PRINTF("RPL: SRH root node not found\n"); return 0; } - if(!rpl_ns_is_node_reachable(dag, &UIP_IP_BUF->destipaddr)) { + if(!uip_sr_is_addr_reachable(dag, &UIP_IP_BUF->destipaddr)) { PRINTF("RPL: SRH no path found to destination\n"); return 0; } @@ -383,7 +391,7 @@ insert_srh_header(void) while(node != NULL && node != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); /* How many bytes in common between all nodes in the path? */ cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &UIP_IP_BUF->destipaddr, 16)); @@ -437,7 +445,7 @@ insert_srh_header(void) hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */ while(node != NULL && node->parent != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); hop_ptr -= (16 - cmpri); memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri); @@ -446,7 +454,7 @@ insert_srh_header(void) } /* The next hop (i.e. node whose parent is the root) is placed as the current IPv6 destination */ - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr); /* In-place update of IPv6 length field */ @@ -461,9 +469,6 @@ insert_srh_header(void) return 1; } -#else /* RPL_WITH_NON_STORING */ -int insert_srh_header(void); -#endif /* RPL_WITH_NON_STORING */ /*---------------------------------------------------------------------------*/ static int update_hbh_header(void) diff --git a/os/net/rpl-classic/rpl-icmp6.c b/os/net/routing/rpl-classic/rpl-icmp6.c similarity index 99% rename from os/net/rpl-classic/rpl-icmp6.c rename to os/net/routing/rpl-classic/rpl-icmp6.c index 6d9a2bca3..914575dbf 100644 --- a/os/net/rpl-classic/rpl-icmp6.c +++ b/os/net/routing/rpl-classic/rpl-icmp6.c @@ -49,9 +49,9 @@ #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-nd6.h" +#include "net/ipv6/uip-sr.h" #include "net/ipv6/uip-icmp6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/packetbuf.h" #include "net/ipv6/multicast/uip-mcast6.h" #include "random.h" @@ -993,9 +993,9 @@ dao_input_nonstoring(void) if(lifetime == RPL_ZERO_LIFETIME) { PRINTF("RPL: No-Path DAO received\n"); - rpl_ns_expire_parent(dag, &prefix, &dao_parent_addr); + uip_sr_expire_parent(dag, &prefix, &dao_parent_addr); } else { - if(rpl_ns_update_node(dag, &prefix, &dao_parent_addr, RPL_LIFETIME(instance, lifetime)) == NULL) { + if(uip_sr_update_node(dag, &prefix, &dao_parent_addr, RPL_LIFETIME(instance, lifetime)) == NULL) { PRINTF("RPL: failed to add link\n"); return; } diff --git a/os/net/rpl-classic/rpl-mrhof.c b/os/net/routing/rpl-classic/rpl-mrhof.c similarity index 99% rename from os/net/rpl-classic/rpl-mrhof.c rename to os/net/routing/rpl-classic/rpl-mrhof.c index 21db377e7..4f5189384 100644 --- a/os/net/rpl-classic/rpl-mrhof.c +++ b/os/net/routing/rpl-classic/rpl-mrhof.c @@ -46,8 +46,8 @@ * @{ */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/nbr-table.h" #include "net/link-stats.h" diff --git a/os/net/rpl-classic/rpl-nbr-policy.c b/os/net/routing/rpl-classic/rpl-nbr-policy.c similarity index 99% rename from os/net/rpl-classic/rpl-nbr-policy.c rename to os/net/routing/rpl-classic/rpl-nbr-policy.c index 1804fd4b7..077977a10 100644 --- a/os/net/rpl-classic/rpl-nbr-policy.c +++ b/os/net/routing/rpl-classic/rpl-nbr-policy.c @@ -44,7 +44,7 @@ * */ -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/nbr-table.h" #include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-route.h" diff --git a/os/net/rpl-classic/rpl-of0.c b/os/net/routing/rpl-classic/rpl-of0.c similarity index 98% rename from os/net/rpl-classic/rpl-of0.c rename to os/net/routing/rpl-classic/rpl-of0.c index aa18823cb..1a679d23b 100644 --- a/os/net/rpl-classic/rpl-of0.c +++ b/os/net/routing/rpl-classic/rpl-of0.c @@ -42,8 +42,8 @@ * @{ */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/nbr-table.h" #include "net/link-stats.h" diff --git a/os/net/rpl-classic/rpl-private.h b/os/net/routing/rpl-classic/rpl-private.h similarity index 99% rename from os/net/rpl-classic/rpl-private.h rename to os/net/routing/rpl-classic/rpl-private.h index 723154cdd..1259fffeb 100644 --- a/os/net/rpl-classic/rpl-private.h +++ b/os/net/routing/rpl-classic/rpl-private.h @@ -37,7 +37,7 @@ #ifndef RPL_PRIVATE_H #define RPL_PRIVATE_H -#include "net/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl.h" #include "lib/list.h" #include "net/ipv6/uip.h" @@ -45,7 +45,6 @@ #include "sys/ctimer.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6-route.h" -#include "net/rpl-classic/rpl-ns.h" #include "net/ipv6/multicast/uip-mcast6.h" /*---------------------------------------------------------------------------*/ diff --git a/os/net/rpl-classic/rpl-timers.c b/os/net/routing/rpl-classic/rpl-timers.c similarity index 99% rename from os/net/rpl-classic/rpl-timers.c rename to os/net/routing/rpl-classic/rpl-timers.c index 7742a5fcc..c812a8897 100644 --- a/os/net/rpl-classic/rpl-timers.c +++ b/os/net/routing/rpl-classic/rpl-timers.c @@ -42,10 +42,10 @@ */ #include "contiki.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/link-stats.h" #include "net/ipv6/multicast/uip-mcast6.h" +#include "net/ipv6/uip-sr.h" #include "lib/random.h" #include "sys/ctimer.h" @@ -89,7 +89,7 @@ handle_periodic_timer(void *ptr) rpl_purge_routes(); } if(RPL_IS_NON_STORING(dag->instance)) { - rpl_ns_periodic(); + uip_sr_periodic(1); } } rpl_recalculate_ranks(); diff --git a/os/net/rpl-classic/rpl.c b/os/net/routing/rpl-classic/rpl.c similarity index 80% rename from os/net/rpl-classic/rpl.c rename to os/net/routing/rpl-classic/rpl.c index dfa7c99cf..b1905d611 100644 --- a/os/net/rpl-classic/rpl.c +++ b/os/net/routing/rpl-classic/rpl.c @@ -45,9 +45,11 @@ #include "net/ipv6/uip.h" #include "net/ipv6/tcpip.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/uip-sr.h" #include "net/ipv6/uip-icmp6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/routing/routing.h" +#include "net/routing/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl-dag-root.h" #include "net/ipv6/multicast/uip-mcast6.h" #define DEBUG DEBUG_NONE @@ -327,8 +329,8 @@ rpl_purge_dags(void) } } /*---------------------------------------------------------------------------*/ -void -rpl_init(void) +static void +init(void) { uip_ipaddr_t rplmaddr; PRINTF("RPL started\n"); @@ -347,9 +349,93 @@ rpl_init(void) #endif #if RPL_WITH_NON_STORING - rpl_ns_init(); + uip_sr_init(); #endif /* RPL_WITH_NON_STORING */ } /*---------------------------------------------------------------------------*/ +static int +get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node) +{ + if(addr != NULL && node != NULL) { + memcpy(addr, &((rpl_dag_t *)node->graph)->dag_id, 8); + memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); + return 1; + } else { + return 0; + } +} +/*---------------------------------------------------------------------------*/ +static void +global_repair(const char *str) +{ + rpl_dag_t *dag = rpl_get_any_dag(); + if(dag != NULL && dag->instance != NULL) { + rpl_repair_root(dag->instance->instance_id); + } +} +/*---------------------------------------------------------------------------*/ +static void +local_repair(const char *str) +{ + rpl_dag_t *dag = rpl_get_any_dag(); + if(dag != NULL) { + rpl_local_repair(dag->instance); + } +} +/*---------------------------------------------------------------------------*/ +static void +drop_route(uip_ds6_route_t *route) +{ + /* If we are the root of the network, trigger a global repair before + the route gets removed */ + rpl_dag_t *dag; + dag = (rpl_dag_t *)route->state.dag; + if(dag != NULL && dag->instance != NULL) { + rpl_repair_root(dag->instance->instance_id); + } +} +/*---------------------------------------------------------------------------*/ +static void +leave_network(void) +{ + PRINTF("RPL: leave_network not supported in RPL Classic\n"); +} +/*---------------------------------------------------------------------------*/ +static int +get_root_ipaddr(uip_ipaddr_t *ipaddr) +{ + rpl_dag_t *dag; + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL && ipaddr != NULL) { + uip_ipaddr_copy(ipaddr, &dag->dag_id); + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +const struct routing_driver rpl_classic_driver = { + "RPL Classic", + init, + rpl_dag_root_set_prefix, + rpl_dag_root_start, + rpl_dag_root_is_root, + get_root_ipaddr, + get_sr_node_ipaddr, + leave_network, + rpl_has_joined, + rpl_has_downward_route, + global_repair, + local_repair, + rpl_ext_header_remove, + rpl_ext_header_update, + rpl_ext_header_hbh_update, + rpl_ext_header_srh_update, + rpl_ext_header_srh_get_next_hop, + rpl_link_callback, + rpl_ipv6_neighbor_callback, + drop_route, +}; +/*---------------------------------------------------------------------------*/ /** @}*/ diff --git a/os/net/rpl-classic/rpl.h b/os/net/routing/rpl-classic/rpl.h similarity index 98% rename from os/net/rpl-classic/rpl.h rename to os/net/routing/rpl-classic/rpl.h index 2fe9f1dbf..db87cc824 100644 --- a/os/net/rpl-classic/rpl.h +++ b/os/net/routing/rpl-classic/rpl.h @@ -38,7 +38,7 @@ #ifndef RPL_H #define RPL_H -#include "net/rpl-classic/rpl-conf.h" +#include "net/routing/rpl-classic/rpl-conf.h" #include "lib/list.h" #include "net/ipv6/uip.h" @@ -266,7 +266,6 @@ struct rpl_instance { /*---------------------------------------------------------------------------*/ /* Public RPL functions. */ -void rpl_init(void); void uip_rpl_input(void); rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len); @@ -328,6 +327,12 @@ enum rpl_mode rpl_set_mode(enum rpl_mode mode); */ enum rpl_mode rpl_get_mode(void); +/** + * Tells whether the node has joined a network or not + * + * \retval 1 if we have joined a network, 0 if not. + */ +int rpl_has_joined(void); /** * Get the RPL's best guess on if we have downward route or not. diff --git a/os/net/rpl-lite/rpl-conf.h b/os/net/routing/rpl-lite/rpl-conf.h similarity index 95% rename from os/net/rpl-lite/rpl-conf.h rename to os/net/routing/rpl-lite/rpl-conf.h index 410cce988..a3693f8b9 100644 --- a/os/net/rpl-lite/rpl-conf.h +++ b/os/net/routing/rpl-lite/rpl-conf.h @@ -29,7 +29,7 @@ * This file is part of the Contiki operating system. * */ - + /** * \addtogroup rpl-lite * @{ @@ -62,18 +62,16 @@ * We only support non-storing mode */ #define RPL_WITH_STORING 0 -#define RPL_WITH_NON_STORING (RPL_MOP_DEFAULT == RPL_MOP_NON_STORING) -/* The number of non-storing nodes, i.e. the maximum netwrok size at the root */ -#ifdef RPL_NS_CONF_LINK_NUM -#define RPL_NS_LINK_NUM RPL_NS_CONF_LINK_NUM -#else /* RPL_NS_CONF_LINK_NUM */ -#if RPL_WITH_NON_STORING -#define RPL_NS_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES -#else -#define RPL_NS_LINK_NUM 0 -#endif -#endif /* RPL_NS_CONF_LINK_NUM */ +/* + * Embed support for non-storing mode + */ +#ifdef RPL_CONF_WITH_NON_STORING +#define RPL_WITH_NON_STORING RPL_CONF_WITH_NON_STORING +#else /* RPL_CONF_WITH_NON_STORING */ +/* By default: embed support for non-storing if and only if the configured MOP is non-storing */ +#define RPL_WITH_NON_STORING (RPL_MOP_DEFAULT == RPL_MOP_NON_STORING) +#endif /* RPL_CONF_WITH_NON_STORING */ /* * The objective function (OF) used by a RPL root is configurable through @@ -309,13 +307,6 @@ #define RPL_DAO_DELAY (CLOCK_SECOND * 4) #endif /* RPL_CONF_DAO_DELAY */ -/* Delay between reception of a no-path DAO and actual route removal */ -#ifdef RPL_CONF_NOPATH_REMOVAL_DELAY -#define RPL_NOPATH_REMOVAL_DELAY RPL_CONF_NOPATH_REMOVAL_DELAY -#else /* RPL_CONF_NOPATH_REMOVAL_DELAY */ -#define RPL_NOPATH_REMOVAL_DELAY 60 -#endif /* RPL_CONF_NOPATH_REMOVAL_DELAY */ - #ifdef RPL_CONF_DAO_MAX_RETRANSMISSIONS #define RPL_DAO_MAX_RETRANSMISSIONS RPL_CONF_DAO_MAX_RETRANSMISSIONS #else diff --git a/os/net/rpl-lite/rpl-const.h b/os/net/routing/rpl-lite/rpl-const.h similarity index 100% rename from os/net/rpl-lite/rpl-const.h rename to os/net/routing/rpl-lite/rpl-const.h diff --git a/os/net/rpl-lite/rpl-dag-root.c b/os/net/routing/rpl-lite/rpl-dag-root.c similarity index 68% rename from os/net/rpl-lite/rpl-dag-root.c rename to os/net/routing/rpl-lite/rpl-dag-root.c index cfe227d4c..0d5cebe92 100644 --- a/os/net/rpl-lite/rpl-dag-root.c +++ b/os/net/routing/rpl-lite/rpl-dag-root.c @@ -40,7 +40,7 @@ #include "contiki.h" #include "contiki-net.h" -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/ipv6/uip-ds6-route.h" /* Log configuration */ @@ -48,48 +48,6 @@ #define LOG_MODULE "RPL" #define LOG_LEVEL LOG_LEVEL_RPL -#define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1) - -static uint8_t to_become_root; -static struct ctimer c; - -/*---------------------------------------------------------------------------*/ -static void -create_dag_callback(void *ptr) -{ - const uip_ipaddr_t *root, *ipaddr; - - root = curr_instance.used ? &curr_instance.dag.dag_id : NULL; - ipaddr = rpl_get_global_address(); - - if(root == NULL || uip_ipaddr_cmp(root, ipaddr)) { - /* The RPL network we are joining is one that we created, so we - become root. */ - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } else { - LOG_WARN("found a network we did not create: version %d grounded %d preference %d rank %d\n", - curr_instance.dag.version, curr_instance.dag.grounded, - curr_instance.dag.preference, curr_instance.dag.rank); - - /* We found a RPL network that we did not create so we just join - it without becoming root. But if the network has an infinite - rank, we assume the network has broken, and we become the new - root of the network. */ - - if(curr_instance.dag.rank == RPL_INFINITE_RANK) { - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } - - /* Try again after the grace period */ - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - } -} /*---------------------------------------------------------------------------*/ static void set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) @@ -125,26 +83,25 @@ set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) } /*---------------------------------------------------------------------------*/ void -rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) +rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) { static uint8_t initialized = 0; if(!initialized) { - to_become_root = 0; set_global_address(prefix, iid); initialized = 1; } } /*---------------------------------------------------------------------------*/ int -rpl_dag_root_init_dag_immediately(void) +rpl_dag_root_start(void) { struct uip_ds6_addr *root_if; int i; uint8_t state; uip_ipaddr_t *ipaddr = NULL; - rpl_dag_root_init(NULL, NULL); + rpl_dag_root_set_prefix(NULL, NULL); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; @@ -170,18 +127,6 @@ rpl_dag_root_init_dag_immediately(void) } } /*---------------------------------------------------------------------------*/ -void -rpl_dag_root_init_dag_delay(void) -{ - rpl_dag_root_init(NULL, NULL); - - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - to_become_root = 1; - - /* Send a DIS packet to request RPL info from neighbors. */ - rpl_icmp6_dis_output(NULL); -} -/*---------------------------------------------------------------------------*/ int rpl_dag_root_is_root(void) { diff --git a/os/net/rpl-lite/rpl-dag-root.h b/os/net/routing/rpl-lite/rpl-dag-root.h similarity index 83% rename from os/net/rpl-lite/rpl-dag-root.h rename to os/net/routing/rpl-lite/rpl-dag-root.h index d6260ff21..af0048c4d 100644 --- a/os/net/rpl-lite/rpl-dag-root.h +++ b/os/net/routing/rpl-lite/rpl-dag-root.h @@ -43,26 +43,19 @@ /********** Public functions **********/ /** - * Initialize dag-root module and sets a prefix in case the node is later - * set as dag root. + * Set a prefix in case the node is later set as dag root. * * \param prefix The prefix. If NULL, UIP_DS6_DEFAULT_PREFIX is used instead * \param iid The IID. If NULL, it will be built from uip_ds6_set_addr_iid. */ -void rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); +void rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); /** - * Initializes the node as DAG root after a delay. Until the delay, the node - * gets a chance to hear another DAG and join it instead. -*/ -void rpl_dag_root_init_dag_delay(void); - -/** - * Initializes the node as DAG root immediatly. + * Set the node as root and start a DAG * * \return 0 in case of success, -1 otherwise */ -int rpl_dag_root_init_dag_immediately(void); +int rpl_dag_root_start(void); /** * Tells whether we are DAG root or not diff --git a/os/net/rpl-lite/rpl-dag.c b/os/net/routing/rpl-lite/rpl-dag.c similarity index 96% rename from os/net/rpl-lite/rpl-dag.c rename to os/net/routing/rpl-lite/rpl-dag.c index 36373dfb1..5074dd482 100644 --- a/os/net/rpl-lite/rpl-dag.c +++ b/os/net/routing/rpl-lite/rpl-dag.c @@ -42,7 +42,8 @@ * Contributors: George Oikonomou (multicast) */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/ipv6/uip-sr.h" #include "net/nbr-table.h" #include "net/link-stats.h" @@ -78,6 +79,16 @@ rpl_dag_state_to_str(enum rpl_dag_state state) } } /*---------------------------------------------------------------------------*/ +int +rpl_dag_get_root_ipaddr(uip_ipaddr_t *ipaddr) +{ + if(curr_instance.used && ipaddr != NULL) { + uip_ipaddr_copy(ipaddr, &curr_instance.dag.dag_id); + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ void rpl_dag_leave(void) { @@ -96,7 +107,7 @@ rpl_dag_leave(void) /* Remove all neighbors and lnks */ rpl_neighbor_remove_all(); - rpl_ns_free_all(); + uip_sr_free_all(); /* Stop all timers */ rpl_timers_stop_dag_timers(); @@ -169,14 +180,14 @@ find_objective_function(rpl_ocp_t ocp) } /*---------------------------------------------------------------------------*/ void -rpl_global_repair(void) +rpl_global_repair(const char *str) { if(rpl_dag_root_is_root()) { - LOG_WARN("initiating global repair, version %u, rank %u)\n", - curr_instance.dag.version, curr_instance.dag.rank); -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Global repair (before)"); -#endif /* LOG_INFO_ENABLED */ + LOG_WARN("initiating global repair (%s), version %u, rank %u)\n", + str, curr_instance.dag.version, curr_instance.dag.rank); + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Global repair (before)"); + } /* Initiate global repair */ RPL_LOLLIPOP_INCREMENT(curr_instance.dag.version); /* New DAG version */ @@ -191,9 +202,9 @@ global_repair_non_root(rpl_dio_t *dio) if(!rpl_dag_root_is_root()) { LOG_WARN("participating in global repair, version %u, rank %u)\n", curr_instance.dag.version, curr_instance.dag.rank); -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Global repair (before)"); -#endif /* LOG_INFO_ENABLED */ + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Global repair (before)"); + } /* Re-initialize configuration from DIO */ init_dag_from_dio(dio); rpl_local_repair("Global repair"); @@ -314,9 +325,9 @@ rpl_dag_update_state(void) rpl_timers_schedule_leaving(); } -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Parent switch"); -#endif /* LOG_INFO_ENABLED */ + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Parent switch"); + } } } @@ -391,7 +402,7 @@ process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio) LOG_ERR("inconsistent DIO version (current: %u, received: %u), initiate global repair\n", curr_instance.dag.version, dio->version); curr_instance.dag.version = dio->version; /* Update version and trigger global repair */ - rpl_global_repair(); + rpl_global_repair("Inconsistent DIO version"); } else { LOG_WARN("new DIO version (current: %u, received: %u), apply global repair\n", curr_instance.dag.version, dio->version); @@ -579,9 +590,9 @@ void rpl_process_dao(uip_ipaddr_t *from, rpl_dao_t *dao) { if(dao->lifetime == 0) { - rpl_ns_expire_parent(from, &dao->parent_addr); + uip_sr_expire_parent(NULL, from, &dao->parent_addr); } else { - if(!rpl_ns_update_node(from, &dao->parent_addr, RPL_LIFETIME(dao->lifetime))) { + if(!uip_sr_update_node(NULL, from, &dao->parent_addr, RPL_LIFETIME(dao->lifetime))) { LOG_ERR("failed to add link on incoming DAO\n"); return; } diff --git a/os/net/rpl-lite/rpl-dag.h b/os/net/routing/rpl-lite/rpl-dag.h similarity index 93% rename from os/net/rpl-lite/rpl-dag.h rename to os/net/routing/rpl-lite/rpl-dag.h index bc59ac4bb..f9ae66f5f 100644 --- a/os/net/rpl-lite/rpl-dag.h +++ b/os/net/routing/rpl-lite/rpl-dag.h @@ -58,6 +58,13 @@ * \return The description string */ const char *rpl_dag_state_to_str(enum rpl_dag_state state); +/** + * Returns the IPv6 address of the RPL DAG root, if any + * + * \param ipaddr A pointer where to copy the IP address of the DAG root + * \return 1 if the root address was copied, 0 otherwise +*/ +int rpl_dag_get_root_ipaddr(uip_ipaddr_t *ipaddr); /** * Start poisoning and leave the DAG after a delay * @@ -78,8 +85,10 @@ void rpl_dag_periodic(unsigned seconds); /** * Triggers a RPL global repair + * + * \param str A textual description of the cause for triggering a repair */ -void rpl_global_repair(void); +void rpl_global_repair(const char *str); /** * Triggers a RPL local repair diff --git a/os/net/rpl-lite/rpl-ext-header.c b/os/net/routing/rpl-lite/rpl-ext-header.c similarity index 96% rename from os/net/rpl-lite/rpl-ext-header.c rename to os/net/routing/rpl-lite/rpl-ext-header.c index 6031d7eef..af67cdaff 100644 --- a/os/net/rpl-lite/rpl-ext-header.c +++ b/os/net/routing/rpl-lite/rpl-ext-header.c @@ -42,8 +42,10 @@ * Nicolas Tsiftes , * Simon Duquennoy */ - -#include "net/rpl-lite/rpl.h" + +#include "net/routing/routing.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/ipv6/uip-sr.h" #include "net/packetbuf.h" /* Log configuration */ @@ -68,8 +70,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) { uint8_t *uip_next_hdr; int last_uip_ext_len = uip_ext_len; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; uip_ext_len = 0; uip_next_hdr = &UIP_IP_BUF->proto; @@ -96,8 +98,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) return 0; } - root_node = rpl_ns_get_node(&curr_instance.dag.dag_id); - dest_node = rpl_ns_get_node(&UIP_IP_BUF->destipaddr); + root_node = uip_sr_get_node(NULL, &curr_instance.dag.dag_id); + dest_node = uip_sr_get_node(NULL, &UIP_IP_BUF->destipaddr); if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) || @@ -227,9 +229,9 @@ insert_srh_header(void) uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */ uint8_t *hop_ptr; uint8_t padding; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; - rpl_ns_node_t *node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; + uip_sr_node_t *node; uip_ipaddr_t node_addr; LOG_INFO("SRH creating source routing header with destination "); @@ -246,20 +248,20 @@ insert_srh_header(void) return 1; } - dest_node = rpl_ns_get_node(&UIP_IP_BUF->destipaddr); + dest_node = uip_sr_get_node(NULL, &UIP_IP_BUF->destipaddr); if(dest_node == NULL) { /* The destination is not found, skip SRH insertion */ LOG_INFO("SRH node not found, skip SRH insertion\n"); return 1; } - root_node = rpl_ns_get_node(&curr_instance.dag.dag_id); + root_node = uip_sr_get_node(NULL, &curr_instance.dag.dag_id); if(root_node == NULL) { LOG_ERR("SRH root node not found\n"); return 0; } - if(!rpl_ns_is_addr_reachable(&UIP_IP_BUF->destipaddr)) { + if(!uip_sr_is_addr_reachable(NULL, &UIP_IP_BUF->destipaddr)) { LOG_ERR("SRH no path found to destination\n"); return 0; } @@ -277,7 +279,7 @@ insert_srh_header(void) while(node != NULL && node != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); /* How many bytes in common between all nodes in the path? */ cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &UIP_IP_BUF->destipaddr, 16)); @@ -331,7 +333,7 @@ insert_srh_header(void) hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */ while(node != NULL && node->parent != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); hop_ptr -= (16 - cmpri); memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri); @@ -340,7 +342,7 @@ insert_srh_header(void) } /* The next hop (i.e. node whose parent is the root) is placed as the current IPv6 destination */ - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr); /* In-place update of IPv6 length field */ diff --git a/os/net/rpl-lite/rpl-ext-header.h b/os/net/routing/rpl-lite/rpl-ext-header.h similarity index 71% rename from os/net/rpl-lite/rpl-ext-header.h rename to os/net/routing/rpl-lite/rpl-ext-header.h index 3e339e6e2..df61bc325 100644 --- a/os/net/rpl-lite/rpl-ext-header.h +++ b/os/net/routing/rpl-lite/rpl-ext-header.h @@ -44,33 +44,34 @@ /********** Public functions **********/ - /** - * Look for next hop from SRH of current uIP packet. - * - * \param ipaddr A pointer to the address where to store the next hop. - * \return 1 if a next hop was found, 0 otherwise - */ - int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr); - - /** - * Process and update SRH in-place, - * i.e. internal address swapping as per RFC6554 - * \return 1 if SRH found, 0 otherwise - */ - int rpl_ext_header_srh_update(void); - - /** - * Process and update the RPL extension headers of the current uIP packet. - * - * \param uip_ext_opt_offset The offset within the uIP packet where - * extension headers start - * \return 1 in case the packet is valid and to be processed further, - * 0 in case the packet must be dropped. - */ - int rpl_ext_header_hbh_update(int uip_ext_opt_offset); +/** +* Look for next hop from SRH of current uIP packet. +* +* \param ipaddr A pointer to the address where to store the next hop. +* \return 1 if a next hop was found, 0 otherwise +*/ +int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr); /** - * Adds/updates RPL extension headers to current uIP packet. +* Process and update SRH in-place, +* i.e. internal address swapping as per RFC6554 +* \return 1 if SRH found, 0 otherwise +*/ +int rpl_ext_header_srh_update(void); + +/** +* Process and update the RPL hop-by-hop extension headers of +* the current uIP packet. +* +* \param uip_ext_opt_offset The offset within the uIP packet where +* extension headers start +* \return 1 in case the packet is valid and to be processed further, +* 0 in case the packet must be dropped. +*/ +int rpl_ext_header_hbh_update(int uip_ext_opt_offset); + +/** + * Adds/updates all RPL extension headers to current uIP packet. * * \return 1 in case of success, 0 otherwise */ diff --git a/os/net/rpl-lite/rpl-icmp6.c b/os/net/routing/rpl-lite/rpl-icmp6.c similarity index 99% rename from os/net/rpl-lite/rpl-icmp6.c rename to os/net/routing/rpl-lite/rpl-icmp6.c index 65c486be5..1e4a50423 100644 --- a/os/net/rpl-lite/rpl-icmp6.c +++ b/os/net/routing/rpl-lite/rpl-icmp6.c @@ -44,7 +44,7 @@ * George Oikonomou (multicast) */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/ipv6/uip-icmp6.h" #include "net/packetbuf.h" #include "lib/random.h" diff --git a/os/net/rpl-lite/rpl-icmp6.h b/os/net/routing/rpl-lite/rpl-icmp6.h similarity index 99% rename from os/net/rpl-lite/rpl-icmp6.h rename to os/net/routing/rpl-lite/rpl-icmp6.h index 443d28ef6..fc877b948 100644 --- a/os/net/rpl-lite/rpl-icmp6.h +++ b/os/net/routing/rpl-lite/rpl-icmp6.h @@ -44,6 +44,7 @@ #include "uip.h" #include "uip-ds6.h" +#include "uip-ds6-nbr.h" /********** Data structures **********/ diff --git a/os/net/rpl-lite/rpl-mrhof.c b/os/net/routing/rpl-lite/rpl-mrhof.c similarity index 99% rename from os/net/rpl-lite/rpl-mrhof.c rename to os/net/routing/rpl-lite/rpl-mrhof.c index 9f9ba2889..a0b2546eb 100644 --- a/os/net/rpl-lite/rpl-mrhof.c +++ b/os/net/routing/rpl-lite/rpl-mrhof.c @@ -45,7 +45,7 @@ * Simon Duquennoy */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/nbr-table.h" #include "net/link-stats.h" diff --git a/os/net/rpl-lite/rpl-nbr-policy.c b/os/net/routing/rpl-lite/rpl-nbr-policy.c similarity index 90% rename from os/net/rpl-lite/rpl-nbr-policy.c rename to os/net/routing/rpl-lite/rpl-nbr-policy.c index 0a8da44d4..3db84f3a8 100644 --- a/os/net/rpl-lite/rpl-nbr-policy.c +++ b/os/net/routing/rpl-lite/rpl-nbr-policy.c @@ -42,7 +42,7 @@ * */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/nbr-table.h" /* Log configuration */ @@ -65,19 +65,7 @@ static int num_parents; /* all nodes that are possible parents */ static int num_free; static linkaddr_t *worst_rank_nbr_lladdr; /* lladdr of the the neighbor with the worst rank */ static rpl_rank_t worst_rank; -/*---------------------------------------------------------------------------*/ -#if LOG_DBG_ENABLED -/* Print out state periodically */ -static void update_state(void); -static struct ctimer periodic_timer; -static int timer_init = 0; -static void -handle_periodic_timer(void *ptr) -{ - update_state(); - ctimer_restart(&periodic_timer); -} -#endif /* LOG_DBG_ENABLED */ + /*---------------------------------------------------------------------------*/ static void update_state(void) @@ -87,14 +75,6 @@ update_state(void) rpl_rank_t nbr_rank; int num_used = 0; -#if LOG_DBG_ENABLED - if(!timer_init) { - timer_init = 1; - ctimer_set(&periodic_timer, 60 * CLOCK_SECOND, - &handle_periodic_timer, NULL); - } -#endif /* LOG_DBG_ENABLED */ - worst_rank = 0; worst_rank_nbr_lladdr = NULL; num_parents = 0; diff --git a/os/net/rpl-lite/rpl-neighbor.c b/os/net/routing/rpl-lite/rpl-neighbor.c similarity index 99% rename from os/net/rpl-lite/rpl-neighbor.c rename to os/net/routing/rpl-lite/rpl-neighbor.c index 96c85a886..d6a545e13 100644 --- a/os/net/rpl-lite/rpl-neighbor.c +++ b/os/net/routing/rpl-lite/rpl-neighbor.c @@ -43,7 +43,7 @@ */ #include "contiki.h" -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/link-stats.h" #include "net/nbr-table.h" diff --git a/os/net/rpl-lite/rpl-neighbor.h b/os/net/routing/rpl-lite/rpl-neighbor.h similarity index 99% rename from os/net/rpl-lite/rpl-neighbor.h rename to os/net/routing/rpl-lite/rpl-neighbor.h index 319ab2414..028d089c7 100644 --- a/os/net/rpl-lite/rpl-neighbor.h +++ b/os/net/routing/rpl-lite/rpl-neighbor.h @@ -47,7 +47,7 @@ /********** Includes **********/ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "lib/list.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" diff --git a/os/net/rpl-lite/rpl-of0.c b/os/net/routing/rpl-lite/rpl-of0.c similarity index 99% rename from os/net/rpl-lite/rpl-of0.c rename to os/net/routing/rpl-lite/rpl-of0.c index 0e94f73f9..c6f820157 100644 --- a/os/net/rpl-lite/rpl-of0.c +++ b/os/net/routing/rpl-lite/rpl-of0.c @@ -41,7 +41,7 @@ * Simon Duquennoy */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/nbr-table.h" #include "net/link-stats.h" diff --git a/os/net/rpl-lite/rpl-timers.c b/os/net/routing/rpl-lite/rpl-timers.c similarity index 99% rename from os/net/rpl-lite/rpl-timers.c rename to os/net/routing/rpl-lite/rpl-timers.c index 486ccd5b4..9bb98ed60 100644 --- a/os/net/rpl-lite/rpl-timers.c +++ b/os/net/routing/rpl-lite/rpl-timers.c @@ -41,7 +41,8 @@ */ #include "contiki.h" -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/ipv6/uip-sr.h" #include "net/link-stats.h" #include "lib/random.h" #include "sys/ctimer.h" @@ -500,7 +501,7 @@ handle_periodic_timer(void *ptr) { if(curr_instance.used) { rpl_dag_periodic(PERIODIC_DELAY_SECONDS); - rpl_ns_periodic(PERIODIC_DELAY_SECONDS); + uip_sr_periodic(PERIODIC_DELAY_SECONDS); } if(!curr_instance.used || @@ -513,9 +514,9 @@ handle_periodic_timer(void *ptr) the meaning of last_advertised_rank changes with time */ rpl_dag_update_state(); -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Periodic"); -#endif /* LOG_INFO_ENABLED */ + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Periodic"); + } ctimer_reset(&periodic_timer); } diff --git a/os/net/rpl-lite/rpl-timers.h b/os/net/routing/rpl-lite/rpl-timers.h similarity index 98% rename from os/net/rpl-lite/rpl-timers.h rename to os/net/routing/rpl-lite/rpl-timers.h index c32f3775c..884a55696 100644 --- a/os/net/rpl-lite/rpl-timers.h +++ b/os/net/routing/rpl-lite/rpl-timers.h @@ -47,7 +47,7 @@ /********** Includes **********/ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" /********** Public functions **********/ diff --git a/os/net/rpl-lite/rpl-types.h b/os/net/routing/rpl-lite/rpl-types.h similarity index 100% rename from os/net/rpl-lite/rpl-types.h rename to os/net/routing/rpl-lite/rpl-types.h diff --git a/os/net/rpl-lite/rpl.c b/os/net/routing/rpl-lite/rpl.c similarity index 80% rename from os/net/rpl-lite/rpl.c rename to os/net/routing/rpl-lite/rpl.c index 29eca52b0..acfe94c37 100644 --- a/os/net/rpl-lite/rpl.c +++ b/os/net/routing/rpl-lite/rpl.c @@ -41,7 +41,8 @@ * Simon Duquennoy */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" @@ -108,6 +109,12 @@ rpl_link_callback(const linkaddr_t *addr, int status, int numtx) } /*---------------------------------------------------------------------------*/ int +rpl_has_joined(void) +{ + return curr_instance.used && curr_instance.dag.state >= DAG_JOINED; +} +/*---------------------------------------------------------------------------*/ +int rpl_is_reachable(void) { return curr_instance.used && curr_instance.dag.state == DAG_REACHABLE; @@ -175,8 +182,8 @@ rpl_set_prefix(rpl_prefix_t *prefix) return 0; } /*---------------------------------------------------------------------------*/ -void -rpl_init(void) +static void +init(void) { LOG_INFO("initializing\n"); @@ -189,8 +196,55 @@ rpl_init(void) rpl_timers_init(); rpl_icmp6_init(); - rpl_ns_init(); + uip_sr_init(); } /*---------------------------------------------------------------------------*/ +static int +get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node) +{ + if(addr != NULL && node != NULL) { + memcpy(addr, &curr_instance.dag.dag_id, 8); + memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); + return 1; + } else { + return 0; + } +} +/*---------------------------------------------------------------------------*/ +static void +neighbor_state_changed(uip_ds6_nbr_t *nbr) +{ + /* Nothing needs be done in non-storing mode */ +} +/*---------------------------------------------------------------------------*/ +static void +drop_route(uip_ds6_route_t *route) +{ + /* Do nothing. RPL-lite only supports non-storing mode, i.e. no routes */ +} +/*---------------------------------------------------------------------------*/ +const struct routing_driver rpl_lite_driver = { + "RPL Lite", + init, + rpl_dag_root_set_prefix, + rpl_dag_root_start, + rpl_dag_root_is_root, + rpl_dag_get_root_ipaddr, + get_sr_node_ipaddr, + rpl_dag_poison_and_leave, + rpl_has_joined, + rpl_is_reachable, + rpl_global_repair, + rpl_local_repair, + rpl_ext_header_remove, + rpl_ext_header_update, + rpl_ext_header_hbh_update, + rpl_ext_header_srh_update, + rpl_ext_header_srh_get_next_hop, + rpl_link_callback, + neighbor_state_changed, + drop_route, +}; +/*---------------------------------------------------------------------------*/ /** @}*/ diff --git a/os/net/rpl-lite/rpl.h b/os/net/routing/rpl-lite/rpl.h similarity index 90% rename from os/net/rpl-lite/rpl.h rename to os/net/routing/rpl-lite/rpl.h index 9557f41c3..7fb4c8718 100644 --- a/os/net/rpl-lite/rpl.h +++ b/os/net/routing/rpl-lite/rpl.h @@ -48,16 +48,15 @@ /********** Includes **********/ #include "net/ipv6/uip.h" -#include "net/rpl-lite/rpl-const.h" -#include "net/rpl-lite/rpl-conf.h" -#include "net/rpl-lite/rpl-types.h" -#include "net/rpl-lite/rpl-icmp6.h" -#include "net/rpl-lite/rpl-dag.h" -#include "net/rpl-lite/rpl-ns.h" -#include "net/rpl-lite/rpl-dag-root.h" -#include "net/rpl-lite/rpl-neighbor.h" -#include "net/rpl-lite/rpl-ext-header.h" -#include "net/rpl-lite/rpl-timers.h" +#include "net/routing/rpl-lite/rpl-const.h" +#include "net/routing/rpl-lite/rpl-conf.h" +#include "net/routing/rpl-lite/rpl-types.h" +#include "net/routing/rpl-lite/rpl-icmp6.h" +#include "net/routing/rpl-lite/rpl-dag.h" +#include "net/routing/rpl-lite/rpl-dag-root.h" +#include "net/routing/rpl-lite/rpl-neighbor.h" +#include "net/routing/rpl-lite/rpl-ext-header.h" +#include "net/routing/rpl-lite/rpl-timers.h" /********** Public symbols **********/ @@ -127,11 +126,6 @@ int rpl_is_reachable(void); */ int rpl_lollipop_greater_than(int a, int b); -/** - * Initialize RPL main module - */ -void rpl_init(void); - /** @} */ #endif /* RPL_H */ diff --git a/os/net/rpl-classic/rpl-ns.c b/os/net/rpl-classic/rpl-ns.c deleted file mode 100644 index dc2eb23e4..000000000 --- a/os/net/rpl-classic/rpl-ns.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2016, Inria. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. - * - * \author Simon Duquennoy - */ - -#include "net/rpl-classic/rpl-conf.h" - -#include "net/ipv6/uip.h" -#include "net/ipv6/tcpip.h" -#include "net/ipv6/uip-ds6.h" -#include "net/ipv6/uip-icmp6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" -#include "lib/list.h" -#include "lib/memb.h" - -#if RPL_WITH_NON_STORING - -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" - -#include -#include - -/* Total number of nodes */ -static int num_nodes; - -/* Every known node in the network */ -LIST(nodelist); -MEMB(nodememb, rpl_ns_node_t, RPL_NS_LINK_NUM); - -/*---------------------------------------------------------------------------*/ -int -rpl_ns_num_nodes(void) -{ - return num_nodes; -} -/*---------------------------------------------------------------------------*/ -static int -node_matches_address(const rpl_dag_t *dag, const rpl_ns_node_t *node, const uip_ipaddr_t *addr) -{ - return addr != NULL - && node != NULL - && dag != NULL - && dag == node->dag - && !memcmp(addr, &node->dag->dag_id, 8) - && !memcmp(((const unsigned char *)addr) + 8, node->link_identifier, 8); -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_get_node(const rpl_dag_t *dag, const uip_ipaddr_t *addr) -{ - rpl_ns_node_t *l; - for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { - /* Compare prefix and node identifier */ - if(node_matches_address(dag, l, addr)) { - return l; - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -int -rpl_ns_is_node_reachable(const rpl_dag_t *dag, const uip_ipaddr_t *addr) -{ - int max_depth = RPL_NS_LINK_NUM; - rpl_ns_node_t *node = rpl_ns_get_node(dag, addr); - rpl_ns_node_t *root_node = rpl_ns_get_node(dag, dag != NULL ? &dag->dag_id : NULL); - while(node != NULL && node != root_node && max_depth > 0) { - node = node->parent; - max_depth--; - } - return node != NULL && node == root_node; -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_expire_parent(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent) -{ - rpl_ns_node_t *l = rpl_ns_get_node(dag, child); - /* Check if parent matches */ - if(l != NULL && node_matches_address(dag, l->parent, parent)) { - l->lifetime = RPL_NOPATH_REMOVAL_DELAY; - } -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime) -{ - rpl_ns_node_t *child_node = rpl_ns_get_node(dag, child); - rpl_ns_node_t *parent_node = rpl_ns_get_node(dag, parent); - rpl_ns_node_t *old_parent_node; - - if(parent != NULL) { - /* No node for the parent, add one with infinite lifetime */ - if(parent_node == NULL) { - parent_node = rpl_ns_update_node(dag, parent, NULL, 0xffffffff); - if(parent_node == NULL) { - return NULL; - } - } - } - - /* No node for this child, add one */ - if(child_node == NULL) { - child_node = memb_alloc(&nodememb); - /* No space left, abort */ - if(child_node == NULL) { - return NULL; - } - child_node->parent = NULL; - list_add(nodelist, child_node); - num_nodes++; - } - - /* Initialize node */ - child_node->dag = dag; - child_node->lifetime = lifetime; - memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8); - - /* Is the node reachable before the update? */ - if(rpl_ns_is_node_reachable(dag, child)) { - old_parent_node = child_node->parent; - /* Update node */ - child_node->parent = parent_node; - /* Has the node become unreachable? May happen if we create a loop. */ - if(!rpl_ns_is_node_reachable(dag, child)) { - /* The new parent makes the node unreachable, restore old parent. - * We will take the update next time, with chances we know more of - * the topology and the loop is gone. */ - child_node->parent = old_parent_node; - } - } else { - child_node->parent = parent_node; - } - - return child_node; -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_init(void) -{ - num_nodes = 0; - memb_init(&nodememb); - list_init(nodelist); -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_head(void) -{ - return list_head(nodelist); -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_next(rpl_ns_node_t *item) -{ - return list_item_next(item); -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node) -{ - if(addr != NULL && node != NULL && node->dag != NULL) { - memcpy(addr, &node->dag->dag_id, 8); - memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); - } -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_periodic(void) -{ - rpl_ns_node_t *l; - rpl_ns_node_t *next; - - /* First pass, for all expired nodes, deallocate them iff no child points to them */ - for(l = list_head(nodelist); l != NULL; l = next) { - next = list_item_next(l); - if(l->lifetime == 0) { - rpl_ns_node_t *l2; - for(l2 = list_head(nodelist); l2 != NULL; l2 = list_item_next(l2)) { - if(l2->parent == l) { - break; - } - } - /* No child found, deallocate node */ - list_remove(nodelist, l); - memb_free(&nodememb, l); - num_nodes--; - } else if(l->lifetime != 0xffffffff) { - /* Decrement lifetime for all nodes with non-infinite lifetime */ - l->lifetime--; - } - } -} - -#endif /* RPL_WITH_NON_STORING */ diff --git a/os/net/rpl-classic/rpl-ns.h b/os/net/rpl-classic/rpl-ns.h deleted file mode 100644 index dcc7e584a..000000000 --- a/os/net/rpl-classic/rpl-ns.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016, Inria. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. - * - * \author Simon Duquennoy - */ - - -#ifndef RPL_NS_H -#define RPL_NS_H - -#include "net/rpl-classic/rpl-conf.h" - -#ifdef RPL_NS_CONF_LINK_NUM -#define RPL_NS_LINK_NUM RPL_NS_CONF_LINK_NUM -#else /* RPL_NS_CONF_LINK_NUM */ -#if RPL_WITH_NON_STORING -#define RPL_NS_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES -#else -#define RPL_NS_LINK_NUM 0 -#endif -#endif /* RPL_NS_CONF_LINK_NUM */ - -typedef struct rpl_ns_node { - struct rpl_ns_node *next; - uint32_t lifetime; - rpl_dag_t *dag; - /* Store only IPv6 link identifiers as all nodes in the DAG share the same prefix */ - unsigned char link_identifier[8]; - struct rpl_ns_node *parent; -} rpl_ns_node_t; - -int rpl_ns_num_nodes(void); -void rpl_ns_expire_parent(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent); -rpl_ns_node_t *rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime); -void rpl_ns_init(void); -rpl_ns_node_t *rpl_ns_node_head(void); -rpl_ns_node_t *rpl_ns_node_next(rpl_ns_node_t *item); -rpl_ns_node_t *rpl_ns_get_node(const rpl_dag_t *dag, const uip_ipaddr_t *addr); -int rpl_ns_is_node_reachable(const rpl_dag_t *dag, const uip_ipaddr_t *addr); -void rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node); -void rpl_ns_periodic(void); - -#endif /* RPL_NS_H */ diff --git a/os/net/security/tinydtls b/os/net/security/tinydtls new file mode 160000 index 000000000..5da931eeb --- /dev/null +++ b/os/net/security/tinydtls @@ -0,0 +1 @@ +Subproject commit 5da931eeb78d1cd4a1e0068a91de9b78bd3f66de diff --git a/os/services/ipso-objects/Makefile.ipso-objects b/os/services/ipso-objects/Makefile.ipso-objects deleted file mode 100644 index 21c56fed0..000000000 --- a/os/services/ipso-objects/Makefile.ipso-objects +++ /dev/null @@ -1 +0,0 @@ -CFLAGS += -DWITH_IPSO=1 diff --git a/os/services/ipso-objects/ipso-blockwise-test.c b/os/services/ipso-objects/ipso-blockwise-test.c new file mode 100644 index 000000000..3a557de2b --- /dev/null +++ b/os/services/ipso-objects/ipso-blockwise-test.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT 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 ipso-objects + * @{ + * + * Code to test blockwise transfer together with the LWM2M-engine. + * This object tests get with BLOCK2 and put with BLOCK1. + * + */ + +#include "lwm2m-engine.h" +#include "coap.h" +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +static lwm2m_object_instance_t reg_object; +static char junk[64]; + +static const lwm2m_resource_id_t resources[] = + { + RO(10000), + RO(11000), + RW(11001) + }; + +#define LEN 900 + +static lwm2m_status_t +opaque_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write) +{ + int i; + PRINTF("opaque-stream callback num_to_write: %d off: %d outlen: %d\n", + num_to_write, ctx->offset, ctx->outbuf->len); + for(i = 0; i < num_to_write; i++) { + ctx->outbuf->buffer[i + ctx->outbuf->len] = '0' + (i & 31); + if(i + ctx->offset == LEN) break; + } + ctx->outbuf->len += i; + if(ctx->offset + i < LEN) { + ctx->writer_flags |= WRITER_HAS_MORE; + } + return LWM2M_STATUS_OK; +} + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + char *str = "just a string"; + + PRINTF("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level); + + if(ctx->level == 1) { + /* Should not happen */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 2) { + /* This is a get whole object - or write whole object */ + return LWM2M_STATUS_ERROR; + } + + if(ctx->operation == LWM2M_OP_READ) { +#if DEBUG + if(coap_get_header_block2(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK2: %d/%d/%d offset:%d\n", num, more, size, offset); + } +#endif + + switch(ctx->resource_id) { + case 10000: + lwm2m_object_write_string(ctx, str, strlen(str)); + break; + case 11000: + case 11001: + PRINTF("Preparing object write\n"); + lwm2m_object_write_opaque_stream(ctx, LEN, opaque_callback); + break; + default: + return LWM2M_STATUS_NOT_FOUND; + } + } else if(ctx->operation == LWM2M_OP_WRITE) { + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); + coap_set_header_block1(ctx->response, num, 0, size); + } + } + return LWM2M_STATUS_OK; +} + +void +ipso_blockwise_test_init(void) +{ + int i; + PRINTF("Starting blockwise\n"); + reg_object.object_id = 4711; + reg_object.instance_id = 0; + reg_object.resource_ids = resources; + reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + reg_object.callback = lwm2m_callback; + + for(i = 0; i < sizeof(junk); i++) { + junk[i] = '0' + i; + } + junk[i - 1] = 0; + + lwm2m_engine_add_object(®_object); +} +/** @} */ diff --git a/os/services/ipso-objects/ipso-button.c b/os/services/ipso-objects/ipso-button.c index adda46d1e..1f3cb2d9b 100644 --- a/os/services/ipso-objects/ipso-button.c +++ b/os/services/ipso-objects/ipso-button.c @@ -36,6 +36,7 @@ /** * \file * Implementation of OMA LWM2M / IPSO button as a digital input + * NOTE: only works with a Contiki Button Sensor (not for Standalone) * \author * Joakim Eriksson * Niclas Finne @@ -44,7 +45,6 @@ #include "contiki.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" #define DEBUG 0 #if DEBUG @@ -54,20 +54,55 @@ #define PRINTF(...) #endif +#define IPSO_INPUT_STATE 5500 +#define IPSO_INPUT_COUNTER 5501 +#define IPSO_INPUT_POLARITY 5502 +#define IPSO_INPUT_DEBOUNCE 5503 +#define IPSO_INPUT_EDGE_SEL 5504 +#define IPSO_INPUT_CTR_RESET 5505 +#define IPSO_INPUT_SENSOR_TYPE 5751 + #if PLATFORM_HAS_BUTTON #include "dev/button-sensor.h" +#if BOARD_SENSORTAG +#include "sensortag/button-sensor.h" +#define IPSO_BUTTON_SENSOR button_left_sensor +#else +#define IPSO_BUTTON_SENSOR button_sensor +#endif + PROCESS(ipso_button_process, "ipso-button"); #endif /* PLATFORM_HAS_BUTTON */ + +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); + static int input_state = 0; static int polarity = 0; static int32_t counter = 0; -static int32_t edge_selection = 3; +static int32_t edge_selection = 3; /* both */ static int32_t debounce_time = 10; + +static const lwm2m_resource_id_t resources[] = { + RO(IPSO_INPUT_STATE), RO(IPSO_INPUT_COUNTER), RW(IPSO_INPUT_POLARITY), + RW(IPSO_INPUT_DEBOUNCE), RW(IPSO_INPUT_EDGE_SEL), EX(IPSO_INPUT_CTR_RESET), + RO(IPSO_INPUT_SENSOR_TYPE) +}; + +/* Only support for one button for now */ +static lwm2m_object_instance_t reg_object = { + .object_id = 3200, + .instance_id = 0, + .resource_ids = resources, + .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t), + .callback = lwm2m_callback, +}; + /*---------------------------------------------------------------------------*/ static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +read_state(void) { int value; if(polarity == 0) { @@ -77,36 +112,53 @@ read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) } PRINTF("Read button state (polarity=%d, state=%d): %d\n", polarity, input_state, value); - return ctx->writer->write_boolean(ctx, outbuf, outsize, value); + return value; } /*---------------------------------------------------------------------------*/ -static int -reset_counter(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, - uint8_t *outbuf, size_t outlen) +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) { - counter = 0; - return 0; + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_INPUT_STATE: + lwm2m_object_write_int(ctx, read_state()); + break; + case IPSO_INPUT_COUNTER: + lwm2m_object_write_int(ctx, counter); + break; + case IPSO_INPUT_POLARITY: + lwm2m_object_write_int(ctx, polarity); + break; + case IPSO_INPUT_DEBOUNCE: + lwm2m_object_write_int(ctx, debounce_time); + break; + case IPSO_INPUT_EDGE_SEL: + lwm2m_object_write_int(ctx, edge_selection); + break; + case IPSO_INPUT_SENSOR_TYPE: + lwm2m_object_write_string(ctx, "button", strlen("button")); + break; + default: + return LWM2M_STATUS_ERROR; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == IPSO_INPUT_CTR_RESET) { + counter = 0; + } else { + return LWM2M_STATUS_ERROR; + } + } + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(button_resources, - LWM2M_RESOURCE_CALLBACK(5500, { read_state, NULL, NULL }), - LWM2M_RESOURCE_INTEGER_VAR(5501, &counter), - LWM2M_RESOURCE_BOOLEAN_VAR(5502, &polarity), - LWM2M_RESOURCE_INTEGER_VAR(5503, &debounce_time), - LWM2M_RESOURCE_INTEGER_VAR(5504, &edge_selection), - LWM2M_RESOURCE_CALLBACK(5505, { NULL, NULL, reset_counter }), - LWM2M_RESOURCE_STRING(5751, "Button") - ); -LWM2M_INSTANCES(button_instances, - LWM2M_INSTANCE(0, button_resources)); -LWM2M_OBJECT(button, 3200, button_instances); -/*---------------------------------------------------------------------------*/ void ipso_button_init(void) { /* register this device and its handlers - the handlers automatically sends in the object to handle */ - lwm2m_engine_register_object(&button); + lwm2m_engine_add_object(®_object); #if PLATFORM_HAS_BUTTON process_start(&ipso_button_process, NULL); @@ -121,19 +173,19 @@ PROCESS_THREAD(ipso_button_process, ev, data) PROCESS_BEGIN(); - SENSORS_ACTIVATE(button_sensor); + SENSORS_ACTIVATE(IPSO_BUTTON_SENSOR); while(1) { PROCESS_WAIT_EVENT(); - if(ev == sensors_event && data == &button_sensor) { + if(ev == sensors_event && data == &IPSO_BUTTON_SENSOR) { if(!input_state) { input_state = 1; counter++; if((edge_selection & 2) != 0) { - lwm2m_object_notify_observers(&button, "/0/5500"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); } - lwm2m_object_notify_observers(&button, "/0/5501"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_COUNTER); time = (debounce_time * CLOCK_SECOND / 1000); if(time < 1) { @@ -144,13 +196,13 @@ PROCESS_THREAD(ipso_button_process, ev, data) } else if(ev == PROCESS_EVENT_TIMER && data == &timer) { if(!input_state) { /* Button is not in pressed state */ - } else if(button_sensor.value(0) != 0) { + } else if(IPSO_BUTTON_SENSOR.value(0) != 0) { /* Button is still pressed */ etimer_reset(&timer); } else { input_state = 0; if((edge_selection & 1) != 0) { - lwm2m_object_notify_observers(&button, "/0/5500"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); } } } diff --git a/os/services/ipso-objects/ipso-control-template.c b/os/services/ipso-objects/ipso-control-template.c new file mode 100644 index 000000000..23b53ef06 --- /dev/null +++ b/os/services/ipso-objects/ipso-control-template.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT 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 ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO control template. + * Useful for implementing controllable objects + * \author + * Joakim Eriksson + * Niclas Finne + */ +#include "ipso-control-template.h" +#include "lwm2m-engine.h" +#include "coap-timer.h" +#include +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define IPSO_ONOFF 5850 +#define IPSO_DIMMER 5851 +#define IPSO_ON_TIME 5852 + +static const lwm2m_resource_id_t resources[] = + { + RW(IPSO_ONOFF), + RW(IPSO_DIMMER), + RW(IPSO_ON_TIME) + }; +/*---------------------------------------------------------------------------*/ +lwm2m_status_t +ipso_control_set_on(ipso_control_t *control, uint8_t onoroff) +{ + uint8_t v; + + if(onoroff) { + v = control->value & 0x7f; + if(v == 0) { + v = 100; + } + } else { + v = 0; + } + + return ipso_control_set_value(control, v); +} +/*---------------------------------------------------------------------------*/ +lwm2m_status_t +ipso_control_set_value(ipso_control_t *control, uint8_t value) +{ + lwm2m_status_t status = LWM2M_STATUS_OK; + int was_on; + + was_on = ipso_control_is_on(control); + + if(value == 0) { + if(was_on) { + /* Turn off */ + status = control->set_value(control, 0); + if(status == LWM2M_STATUS_OK) { + control->value &= 0x7f; + control->on_time += + (coap_timer_uptime() - control->last_on_time) / 1000; + } + } + } else { + /* Restrict value between 0 - 100 */ + if(value > 100) { + value = 100; + } + value |= 0x80; + + if(value != control->value) { + status = control->set_value(control, value & 0x7f); + if(status == LWM2M_STATUS_OK) { + control->value = value; + if(! was_on) { + control->last_on_time = coap_timer_uptime(); + } + } + } + } + return status; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) +{ + ipso_control_t *control; + int32_t v; + + /* Here we cast to our sensor-template struct */ + control = (ipso_control_t *)object; + + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_ONOFF: + v = ipso_control_is_on(control) ? 1 : 0; + break; + case IPSO_DIMMER: + v = ipso_control_get_value(control); + break; + case IPSO_ON_TIME: + v = control->on_time; + if(ipso_control_is_on(control)) { + v += (coap_timer_uptime() - control->last_on_time) / 1000; + } + PRINTF("ON-TIME: %"PRId32" (last on: %"PRIu32"\n", v, control->on_time); + break; + default: + return LWM2M_STATUS_ERROR; + } + lwm2m_object_write_int(ctx, v); + return LWM2M_STATUS_OK; + + } else if(ctx->operation == LWM2M_OP_WRITE) { + switch(ctx->resource_id) { + case IPSO_ONOFF: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + return ipso_control_set_on(control, v > 0); + case IPSO_DIMMER: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + if(v < 0) { + v = 0; + } else if(v > 100) { + v = 100; + } + return ipso_control_set_value(control, v & 0xff); + case IPSO_ON_TIME: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + + if(v == 0) { + control->on_time = 0; + control->last_on_time = coap_timer_uptime(); + return LWM2M_STATUS_OK; + } else { + /* Only allowed to write 0 to reset ontime */ + return LWM2M_STATUS_FORBIDDEN; + } + break; + default: + return LWM2M_STATUS_ERROR; + } + } else { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } +} +/*---------------------------------------------------------------------------*/ +int +ipso_control_add(ipso_control_t *control) +{ + control->reg_object.resource_ids = resources; + control->reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + + control->reg_object.callback = lwm2m_callback; + return lwm2m_engine_add_object(&control->reg_object); +} +/*---------------------------------------------------------------------------*/ +int +ipso_control_remove(ipso_control_t *control) +{ + lwm2m_engine_remove_object(&control->reg_object); + return 1; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/ipso-objects/ipso-control-template.h b/os/services/ipso-objects/ipso-control-template.h new file mode 100644 index 000000000..dfbd7076b --- /dev/null +++ b/os/services/ipso-objects/ipso-control-template.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT 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 ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#ifndef IPSO_CONTROL_TEMPLATE_H_ +#define IPSO_CONTROL_TEMPLATE_H_ + +#include "lwm2m-engine.h" + +typedef struct ipso_control ipso_control_t; + +#define IPSO_CONTROL_USE_DIMMER 0x01 + +typedef lwm2m_status_t (*ipso_control_set_value_t)(ipso_control_t *control, + uint8_t v); + +/* Values of the IPSO control object */ +struct ipso_control { + lwm2m_object_instance_t reg_object; + uint8_t flags; + uint8_t value; /* used to emulate on/off and dim-value */ + uint32_t on_time; /* on-time in seconds */ + uint64_t last_on_time; + ipso_control_set_value_t set_value; +}; + +#define IPSO_CONTROL(name, oid, iid, setv) \ + static ipso_control_t name = { \ + .reg_object.object_id = oid, \ + .reg_object.instance_id = iid, \ + .set_value = setv \ + } + +int ipso_control_add(ipso_control_t *control); +int ipso_control_remove(ipso_control_t *control); + +static inline uint16_t +ipso_control_get_object_id(const ipso_control_t *control) +{ + return control->reg_object.object_id; +} + +static inline uint16_t +ipso_control_get_instance_id(const ipso_control_t *control) +{ + return control->reg_object.instance_id; +} + +static inline uint8_t +ipso_control_is_on(const ipso_control_t *control) +{ + return (control->value & 0x80) != 0; +} + +static inline uint8_t +ipso_control_get_value(const ipso_control_t *control) +{ + return (control->value & 0x80) != 0 ? (control->value & 0x7f) : 0; +} + +lwm2m_status_t ipso_control_set_on(ipso_control_t *control, uint8_t onoroff); + +lwm2m_status_t ipso_control_set_value(ipso_control_t *control, uint8_t dimm_value); + +#endif /* IPSO_CONTROL_TEMPLATE_H_ */ +/** @} */ diff --git a/os/services/ipso-objects/ipso-leds-control.c b/os/services/ipso-objects/ipso-leds-control.c index 38f150f39..2c64da328 100644 --- a/os/services/ipso-objects/ipso-leds-control.c +++ b/os/services/ipso-objects/ipso-leds-control.c @@ -44,7 +44,7 @@ #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" +#include "ipso-control-template.h" #include "dev/leds.h" #include @@ -56,146 +56,42 @@ #define PRINTF(...) #endif +#if LEDS_LEGACY_API #if LEDS_ALL & LEDS_BLUE || LEDS_ALL & LEDS_RED || LEDS_ALL & LEDS_BLUE #define LEDS_CONTROL_NUMBER (((LEDS_ALL & LEDS_BLUE) ? 1 : 0) + ((LEDS_ALL & LEDS_RED) ? 1 : 0) + ((LEDS_ALL & LEDS_GREEN) ? 1 : 0)) #else #define LEDS_CONTROL_NUMBER 1 #endif +#else /* LEDS_LEGACY_API */ +#define LEDS_CONTROL_NUMBER LEDS_COUNT +#endif /* LEDS_LEGACY_API */ -struct led_state { - unsigned long last_on_time; - uint32_t total_on_time; - uint8_t is_on; +typedef struct led_state { + ipso_control_t control; uint8_t led_value; -}; +} led_state_t; -static struct led_state states[LEDS_CONTROL_NUMBER]; -static lwm2m_instance_t leds_control_instances[LEDS_CONTROL_NUMBER]; +static led_state_t leds_controls[LEDS_CONTROL_NUMBER]; /*---------------------------------------------------------------------------*/ -static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) { - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - return ctx->writer->write_boolean(ctx, outbuf, outsize, - states[idx].is_on ? 1 : 0); -} -/*---------------------------------------------------------------------------*/ -static int -write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int value; - size_t len; +#if PLATFORM_HAS_LEDS || LEDS_COUNT + led_state_t *state; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } + state = (led_state_t *)control; - len = ctx->reader->read_boolean(ctx, inbuf, insize, &value); - if(len > 0) { - if(value) { - if(!states[idx].is_on) { - states[idx].is_on = 1; - states[idx].last_on_time = clock_seconds(); -#if PLATFORM_HAS_LEDS - leds_on(states[idx].led_value); -#endif /* PLATFORM_HAS_LEDS */ - } - } else if(states[idx].is_on) { - states[idx].total_on_time += clock_seconds() - states[idx].last_on_time; - states[idx].is_on = 0; -#if PLATFORM_HAS_LEDS - leds_off(states[idx].led_value); -#endif /* PLATFORM_HAS_LEDS */ - } + if(value) { + leds_on(state->led_value); } else { - PRINTF("IPSO leds control - ignored illegal write to on/off\n"); + leds_off(state->led_value); } - return len; -} -/*---------------------------------------------------------------------------*/ -static char * -get_color(int value) { - switch(value) { - case LEDS_GREEN: - return "Green"; - case LEDS_RED: - return "Red"; - case LEDS_BLUE: - return "Blue"; - } - return "None"; -} +#endif /* PLATFORM_HAS_LEDS */ -static int -read_color(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - char *value; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - value = get_color(states[idx].led_value); - return ctx->writer->write_string(ctx, outbuf, outsize, - value, strlen(value)); + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ static int -read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - unsigned long now; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - - if(states[idx].is_on) { - /* Update the on time */ - now = clock_seconds(); - states[idx].total_on_time += now - states[idx].last_on_time; - states[idx].last_on_time = now; - } - return ctx->writer->write_int(ctx, outbuf, outsize, - (int32_t)states[idx].total_on_time); -} -/*---------------------------------------------------------------------------*/ -static int -write_on_time(lwm2m_context_t *ctx, - const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - - len = ctx->reader->read_int(ctx, inbuf, insize, &value); - if(len > 0 && value == 0) { - PRINTF("IPSO leds control - reset On Time\n"); - states[idx].total_on_time = 0; - if(states[idx].is_on) { - states[idx].last_on_time = clock_seconds(); - } - } else { - PRINTF("IPSO leds control - ignored illegal write to On Time\n"); - } - return len; -} -/*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(leds_control_resources, - LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }), - LWM2M_RESOURCE_CALLBACK(5706, { read_color, NULL, NULL }), - LWM2M_RESOURCE_CALLBACK(5852, { read_on_time, write_on_time, NULL }) - ); -LWM2M_OBJECT(leds_control, 3311, leds_control_instances); -/*---------------------------------------------------------------------------*/ -static int bit_no(int bit) { int i; @@ -212,23 +108,23 @@ bit_no(int bit) } return 0; } - +/*---------------------------------------------------------------------------*/ void ipso_leds_control_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE(0, leds_control_resources); + ipso_control_t *c; int i; /* Initialize the instances */ for(i = 0; i < LEDS_CONTROL_NUMBER; i++) { - leds_control_instances[i] = template; - leds_control_instances[i].id = i; - states[i].led_value = bit_no(i); + c = &leds_controls[i].control; + c->reg_object.object_id = 3311; + c->reg_object.instance_id = i; + c->set_value = set_value; + leds_controls[i].led_value = bit_no(i); + ipso_control_add(c); } - /* register this device and its handlers - the handlers automatically - sends in the object to handle */ - lwm2m_engine_register_object(&leds_control); PRINTF("IPSO leds control initialized with %u instances\n", LEDS_CONTROL_NUMBER); } diff --git a/os/services/ipso-objects/ipso-light-control.c b/os/services/ipso-objects/ipso-light-control.c index 02c4b9be2..97733b629 100644 --- a/os/services/ipso-objects/ipso-light-control.c +++ b/os/services/ipso-objects/ipso-light-control.c @@ -45,138 +45,29 @@ #include "ipso-objects.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "ipso-control-template.h" #ifdef IPSO_LIGHT_CONTROL extern const struct ipso_objects_actuator IPSO_LIGHT_CONTROL; #endif /* IPSO_LIGHT_CONTROL */ -/*---------------------------------------------------------------------------*/ -static unsigned long last_on_time; -static uint32_t total_on_time; -static int dim_level = 0; -static uint8_t is_on = 0; -/*---------------------------------------------------------------------------*/ -static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - return ctx->writer->write_boolean(ctx, outbuf, outsize, is_on ? 1 : 0); -} -/*---------------------------------------------------------------------------*/ -static int -write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int value; - size_t len; - len = ctx->reader->read_boolean(ctx, inbuf, insize, &value); - if(len > 0) { - if(value) { - if(!is_on) { - is_on = 1; - last_on_time = clock_seconds(); - } - } else { - if(is_on) { - total_on_time += clock_seconds() - last_on_time; - is_on = 0; - } - } +static lwm2m_status_t set_value(ipso_control_t *control, uint8_t value); + +IPSO_CONTROL(light_control, 3311, 0, set_value); +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) +{ #ifdef IPSO_LIGHT_CONTROL - if(IPSO_LIGHT_CONTROL.set_on) { - IPSO_LIGHT_CONTROL.set_on(value); - } else if(IPSO_LIGHT_CONTROL.set_dim_level) { - dim_level = value ? 100 : 0; - IPSO_LIGHT_CONTROL.set_dim_level(dim_level); - } + if(IPSO_LIGHT_CONTROL.set_dim_level) { + IPSO_LIGHT_CONTROL.set_dim_level(value); + } else if(IPSO_LIGHT_CONTROL.set_on) { + IPSO_LIGHT_CONTROL.set_on(value); + } #endif /* IPSO_LIGHT_CONTROL */ - } - return len; + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -static int -read_dim(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - return ctx->writer->write_int(ctx, outbuf, outsize, dim_level); -} -/*---------------------------------------------------------------------------*/ -static int -write_dim(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; - - len = ctx->reader->read_int(ctx, inbuf, insize, &value); - if(len > 0) { - if(value < 0) { - value = 0; - } else if(value > 100) { - value = 100; - } - - dim_level = value; - if(value > 0) { - if(!is_on) { - is_on = 1; - last_on_time = clock_seconds(); - } - } else { - if(is_on) { - total_on_time += clock_seconds() - last_on_time; - is_on = 0; - } - } -#ifdef IPSO_LIGHT_CONTROL - if(IPSO_LIGHT_CONTROL.set_dim_level) { - IPSO_LIGHT_CONTROL.set_dim_level(dim_level); - } else if(IPSO_LIGHT_CONTROL.set_on) { - IPSO_LIGHT_CONTROL.set_on(is_on); - } -#endif /* IPSO_LIGHT_CONTROL */ - } - return len; -} -/*---------------------------------------------------------------------------*/ -static int -read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - unsigned long now; - if(is_on) { - /* Update the on time */ - now = clock_seconds(); - total_on_time += now - last_on_time; - last_on_time = now; - } - return ctx->writer->write_int(ctx, outbuf, outsize, (int32_t)total_on_time); -} -/*---------------------------------------------------------------------------*/ -static int -write_on_time(lwm2m_context_t *ctx, - const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; - - len = ctx->reader->read_int(ctx, inbuf, insize, &value); - if(len > 0 && value == 0) { - total_on_time = 0; - if(is_on) { - last_on_time = clock_seconds(); - } - } - return len; -} -/*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(light_control_resources, - LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }), - LWM2M_RESOURCE_CALLBACK(5851, { read_dim, write_dim, NULL }), - LWM2M_RESOURCE_CALLBACK(5852, { read_on_time, write_on_time, NULL }), - ); -LWM2M_INSTANCES(light_control_instances, - LWM2M_INSTANCE(0, light_control_resources)); -LWM2M_OBJECT(light_control, 3311, light_control_instances); -/*---------------------------------------------------------------------------*/ void ipso_light_control_init(void) { @@ -184,19 +75,15 @@ ipso_light_control_init(void) if(IPSO_LIGHT_CONTROL.init) { IPSO_LIGHT_CONTROL.init(); } - if(IPSO_LIGHT_CONTROL.is_on) { - is_on = IPSO_LIGHT_CONTROL.is_on(); - } if(IPSO_LIGHT_CONTROL.get_dim_level) { - dim_level = IPSO_LIGHT_CONTROL.get_dim_level(); - if(dim_level > 0 && IPSO_LIGHT_CONTROL.is_on == NULL) { - is_on = 1; - } + ipso_control_set_value(&light_control, + IPSO_LIGHT_CONTROL.get_dim_level()); + } else if(IPSO_LIGHT_CONTROL.is_on) { + ipso_control_set_on(&light_control, IPSO_LIGHT_CONTROL.is_on()); } #endif /* IPSO_LIGHT_CONTROL */ - last_on_time = clock_seconds(); - lwm2m_engine_register_object(&light_control); + ipso_control_add(&light_control); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/ipso-objects/ipso-objects.c b/os/services/ipso-objects/ipso-objects.c index 1e8243f94..f8538ee43 100644 --- a/os/services/ipso-objects/ipso-objects.c +++ b/os/services/ipso-objects/ipso-objects.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup ipso-objects * @{ */ @@ -42,6 +42,7 @@ */ #include "contiki.h" +#include "dev/leds.h" #include "ipso-objects.h" /*---------------------------------------------------------------------------*/ void @@ -58,7 +59,7 @@ ipso_objects_init(void) #ifdef IPSO_LIGHT_CONTROL ipso_light_control_init(); -#elif PLATFORM_HAS_LEDS +#elif PLATFORM_HAS_LEDS || LEDS_COUNT ipso_leds_control_init(); #endif } diff --git a/os/services/ipso-objects/ipso-objects.h b/os/services/ipso-objects/ipso-objects.h index 6b8f5c2a6..92bdfd8de 100644 --- a/os/services/ipso-objects/ipso-objects.h +++ b/os/services/ipso-objects/ipso-objects.h @@ -37,8 +37,7 @@ * \defgroup ipso-objects An implementation of IPSO Objects * @{ * - * This application is an implementation of IPSO Objects for - * OMA Lightweight M2M. + * This is an implementation of IPSO Objects for OMA LWM2M. */ /** diff --git a/os/services/ipso-objects/ipso-sensor-template.c b/os/services/ipso-objects/ipso-sensor-template.c new file mode 100644 index 000000000..bf46ed5ae --- /dev/null +++ b/os/services/ipso-objects/ipso-sensor-template.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT 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 ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson + * Niclas Finne + */ +#include "ipso-sensor-template.h" +#include "lwm2m-engine.h" +#include +#include + +#define IPSO_SENSOR_VALUE 5700 +#define IPSO_SENSOR_UNIT 5701 +#define IPSO_SENSOR_MIN_VALUE 5601 +#define IPSO_SENSOR_MAX_VALUE 5602 +#define IPSO_SENSOR_MIN_RANGE 5603 +#define IPSO_SENSOR_MAX_RANGE 5604 + +#define IPSO_SENSOR_RESET_MINMAX 5605 + +static const lwm2m_resource_id_t resources[] = + { + RO(IPSO_SENSOR_VALUE), RO(IPSO_SENSOR_UNIT), + RO(IPSO_SENSOR_MIN_VALUE), RO(IPSO_SENSOR_MAX_VALUE), + RO(IPSO_SENSOR_MIN_RANGE), RO(IPSO_SENSOR_MAX_RANGE), + EX(IPSO_SENSOR_RESET_MINMAX) + }; + +/*---------------------------------------------------------------------------*/ +static void update_last_value(ipso_sensor_value_t *sval, int32_t value, + uint8_t notify); +/*---------------------------------------------------------------------------*/ +static int init = 0; +static coap_timer_t nt; + +/* Currently support max 4 periodic sensors */ +#define MAX_PERIODIC 4 +struct periodic_sensor { + ipso_sensor_value_t *value; + uint16_t ticks_left; +} periodics[MAX_PERIODIC]; + +static void +timer_callback(coap_timer_t *timer) +{ + int i; + coap_timer_reset(timer, 1000); + + for(i = 0; i < MAX_PERIODIC; i++) { + if(periodics[i].value != NULL) { + if(periodics[i].ticks_left > 0) { + periodics[i].ticks_left--; + } else { + int32_t value; + periodics[i].ticks_left = periodics[i].value->sensor->update_interval; + if(periodics[i].value->sensor->get_value_in_millis(periodics[i].value->sensor, &value) == LWM2M_STATUS_OK) { + update_last_value(periodics[i].value, value, 1); + } + } + } + } +} + +static void +add_periodic(const ipso_sensor_t *sensor) +{ + int i; + for(i = 0; i < MAX_PERIODIC; i++) { + if(periodics[i].value == NULL) { + periodics[i].value = sensor->sensor_value; + periodics[i].ticks_left = sensor->update_interval; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +static void +update_last_value(ipso_sensor_value_t *sval, int32_t value, uint8_t notify) +{ + /* No notification if this a regular read that cause the update */ + if(sval->last_value != value && notify) { + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_VALUE); + } + sval->last_value = value; + if(sval->min_value > value) { + sval->min_value = value; + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MIN_VALUE); + } + if(sval->max_value < value) { + sval->max_value = value; + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MAX_VALUE); + } +} +/*---------------------------------------------------------------------------*/ +static inline size_t +write_float32fix(lwm2m_context_t *ctx, int32_t value) +{ + int64_t tmp = value; + tmp = (tmp * 1024) / 1000; + return lwm2m_object_write_float32fix(ctx, (int32_t)tmp, 10); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + /* Here we cast to our sensor-template struct */ + const ipso_sensor_t *sensor; + ipso_sensor_value_t *value; + value = (ipso_sensor_value_t *) object; + sensor = value->sensor; + + /* Do the stuff */ + if(ctx->level == 1) { + /* Should not happen 3303 */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 2) { + /* This is a get whole object - or write whole object 3303/0 */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 3) { + /* This is a get request on 3303/0/3700 */ + /* NOW we assume a get.... which might be wrong... */ + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_SENSOR_UNIT: + if(sensor->unit != NULL) { + lwm2m_object_write_string(ctx, sensor->unit, strlen(sensor->unit)); + } + break; + case IPSO_SENSOR_MAX_RANGE: + write_float32fix(ctx, sensor->max_range); + break; + case IPSO_SENSOR_MIN_RANGE: + write_float32fix(ctx, sensor->min_range); + break; + case IPSO_SENSOR_MAX_VALUE: + write_float32fix(ctx, value->max_value); + break; + case IPSO_SENSOR_MIN_VALUE: + write_float32fix(ctx, value->min_value); + break; + case IPSO_SENSOR_VALUE: + if(sensor->get_value_in_millis != NULL) { + int32_t v; + if(sensor->get_value_in_millis(sensor, &v) == LWM2M_STATUS_OK) { + update_last_value(value, v, 0); + write_float32fix(ctx, value->last_value); + } + } + break; + default: + return LWM2M_STATUS_ERROR; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == IPSO_SENSOR_RESET_MINMAX) { + value->min_value = value->last_value; + value->max_value = value->last_value; + } + } + } + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +int +ipso_sensor_add(const ipso_sensor_t *sensor) +{ + if(sensor->update_interval > 0) { + if(init == 0) { + coap_timer_set_callback(&nt, timer_callback); + coap_timer_set(&nt, 1000); + init = 1; + } + add_periodic(sensor); + } + + if(sensor->sensor_value == NULL) { + return 0; + } + sensor->sensor_value->reg_object.object_id = sensor->object_id; + sensor->sensor_value->sensor = sensor; + if(sensor->instance_id == 0) { + sensor->sensor_value->reg_object.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } else { + sensor->sensor_value->reg_object.instance_id = sensor->instance_id; + } + sensor->sensor_value->reg_object.callback = lwm2m_callback; + sensor->sensor_value->reg_object.resource_ids = resources; + sensor->sensor_value->reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + return lwm2m_engine_add_object(&sensor->sensor_value->reg_object); +} +/*---------------------------------------------------------------------------*/ +int +ipso_sensor_remove(const ipso_sensor_t *sensor) +{ + lwm2m_engine_remove_object(&sensor->sensor_value->reg_object); + return 1; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/ipso-objects/ipso-sensor-template.h b/os/services/ipso-objects/ipso-sensor-template.h new file mode 100644 index 000000000..375dbad7c --- /dev/null +++ b/os/services/ipso-objects/ipso-sensor-template.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT 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 ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#ifndef IPSO_SENSOR_TEMPLATE_H_ +#define IPSO_SENSOR_TEMPLATE_H_ + +#include "lwm2m-engine.h" + +typedef struct ipso_sensor ipso_sensor_t; + +typedef lwm2m_status_t (*ipso_sensor_get_value_millis_t)(const ipso_sensor_t *sensor, int32_t *v); + +/* Values of the IPSO object */ +typedef struct ipso_sensor_value { + lwm2m_object_instance_t reg_object; + const ipso_sensor_t *sensor; + uint8_t flags; + int32_t last_value; + int32_t min_value; + int32_t max_value; +} ipso_sensor_value_t; + +/* Meta data about an IPSO sensor object */ +struct ipso_sensor { + /* LWM2M object type */ + uint16_t object_id; + uint16_t instance_id; + /* When we read out the value we send in a context to write to */ + ipso_sensor_get_value_millis_t get_value_in_millis; + int32_t min_range; + int32_t max_range; + char *unit; + /* update interval in seconds */ + uint16_t update_interval; + ipso_sensor_value_t *sensor_value; +}; + +#define IPSO_SENSOR(name, oid, get_value, ...) \ + static ipso_sensor_value_t name##_value; \ + static const ipso_sensor_t name = { \ + .object_id = oid, \ + .sensor_value = &name##_value, \ + .get_value_in_millis = get_value, \ + __VA_ARGS__ \ + } + +int ipso_sensor_add(const ipso_sensor_t *sensor); +int ipso_sensor_remove(const ipso_sensor_t *sensor); + +#endif /* IPSO_SENSOR_TEMPLATE_H_ */ +/** @} */ diff --git a/os/services/ipso-objects/ipso-temperature.c b/os/services/ipso-objects/ipso-temperature.c index 1851245e2..c27d8b6ba 100644 --- a/os/services/ipso-objects/ipso-temperature.c +++ b/os/services/ipso-objects/ipso-temperature.c @@ -42,118 +42,56 @@ */ #include +#include "ipso-sensor-template.h" #include "ipso-objects.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" #ifdef IPSO_TEMPERATURE extern const struct ipso_objects_sensor IPSO_TEMPERATURE; #endif /* IPSO_TEMPERATURE */ #ifndef IPSO_TEMPERATURE_MIN -#define IPSO_TEMPERATURE_MIN (-50 * LWM2M_FLOAT32_FRAC) +#define IPSO_TEMPERATURE_MIN -50000 #endif #ifndef IPSO_TEMPERATURE_MAX -#define IPSO_TEMPERATURE_MAX (80 * LWM2M_FLOAT32_FRAC) +#define IPSO_TEMPERATURE_MAX 80000 #endif -static struct ctimer periodic_timer; -static int32_t min_temp; -static int32_t max_temp; -static int read_temp(int32_t *value); +static lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, + int32_t *value); + +IPSO_SENSOR(temp_sensor, 3303, get_temp_value, + .max_range = IPSO_TEMPERATURE_MAX, /* milli celcius */ + .min_range = IPSO_TEMPERATURE_MIN, /* milli celcius */ + .unit = "Cel", + .update_interval = 10 + ); + /*---------------------------------------------------------------------------*/ -static int -temp(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - int32_t value; - if(read_temp(&value)) { - return ctx->writer->write_float32fix(ctx, outbuf, outsize, - value, LWM2M_FLOAT32_BITS); - } - return 0; -} -/*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(temperature_resources, - /* Temperature (Current) */ - LWM2M_RESOURCE_CALLBACK(5700, { temp, NULL, NULL }), - /* Units */ - LWM2M_RESOURCE_STRING(5701, "Cel"), - /* Min Range Value */ - LWM2M_RESOURCE_FLOATFIX(5603, IPSO_TEMPERATURE_MIN), - /* Max Range Value */ - LWM2M_RESOURCE_FLOATFIX(5604, IPSO_TEMPERATURE_MAX), - /* Min Measured Value */ - LWM2M_RESOURCE_FLOATFIX_VAR(5601, &min_temp), - /* Max Measured Value */ - LWM2M_RESOURCE_FLOATFIX_VAR(5602, &max_temp), - ); -LWM2M_INSTANCES(temperature_instances, - LWM2M_INSTANCE(0, temperature_resources)); -LWM2M_OBJECT(temperature, 3303, temperature_instances); -/*---------------------------------------------------------------------------*/ -static int -read_temp(int32_t *value) +static lwm2m_status_t +get_temp_value(const ipso_sensor_t *s, int32_t *value) { #ifdef IPSO_TEMPERATURE - int32_t temp; if(IPSO_TEMPERATURE.read_value == NULL || - IPSO_TEMPERATURE.read_value(&temp) != 0) { - return 0; + IPSO_TEMPERATURE.read_value(value) != 0) { + return LWM2M_STATUS_OK; } - - /* Convert milliCelsius to fix float */ - *value = (temp * LWM2M_FLOAT32_FRAC) / 1000; - - if(*value < min_temp) { - min_temp = *value; - lwm2m_object_notify_observers(&temperature, "/0/5601"); - } - if(*value > max_temp) { - max_temp = *value; - lwm2m_object_notify_observers(&temperature, "/0/5602"); - } - return 1; -#else /* IPSO_TEMPERATURE */ - return 0; #endif /* IPSO_TEMPERATURE */ -} -/*---------------------------------------------------------------------------*/ -static void -handle_periodic_timer(void *ptr) -{ - static int32_t last_value = IPSO_TEMPERATURE_MIN; - int32_t v; - - /* Only notify when the value has changed since last */ - if(read_temp(&v) && v != last_value) { - last_value = v; - lwm2m_object_notify_observers(&temperature, "/0/5700"); - } - ctimer_reset(&periodic_timer); + return LWM2M_STATUS_ERROR; } /*---------------------------------------------------------------------------*/ void ipso_temperature_init(void) { - int32_t v; - min_temp = IPSO_TEMPERATURE_MAX; - max_temp = IPSO_TEMPERATURE_MIN; - #ifdef IPSO_TEMPERATURE if(IPSO_TEMPERATURE.init) { IPSO_TEMPERATURE.init(); } #endif /* IPSO_TEMPERATURE */ - /* register this device and its handlers - the handlers automatically - sends in the object to handle */ - lwm2m_engine_register_object(&temperature); - - /* update temp and min/max + notify any listeners */ - read_temp(&v); - ctimer_set(&periodic_timer, CLOCK_SECOND * 10, handle_periodic_timer, NULL); + ipso_sensor_add(&temp_sensor); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/Makefile.lwm2m b/os/services/lwm2m/Makefile.lwm2m deleted file mode 100644 index 47c4fe5da..000000000 --- a/os/services/lwm2m/Makefile.lwm2m +++ /dev/null @@ -1 +0,0 @@ -CFLAGS += -DHAVE_OMA_LWM2M=1 diff --git a/os/services/lwm2m/lwm2m-device.c b/os/services/lwm2m/lwm2m-device.c index a911c7c4a..9e91b37fd 100644 --- a/os/services/lwm2m/lwm2m-device.c +++ b/os/services/lwm2m/lwm2m-device.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -44,109 +44,182 @@ #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-engine.h" +#include -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-device" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +static const lwm2m_resource_id_t resources[] = + { RO(LWM2M_DEVICE_MANUFACTURER_ID), + RO(LWM2M_DEVICE_MODEL_NUMBER_ID), + RO(LWM2M_DEVICE_SERIAL_NUMBER_ID), + RO(LWM2M_DEVICE_FIRMWARE_VERSION_ID), + RO(LWM2M_DEVICE_AVAILABLE_POWER_SOURCES), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_POWER_SOURCE_VOLTAGE), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_POWER_SOURCE_CURRENT), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_TYPE_ID), + EX(LWM2M_DEVICE_REBOOT_ID), + RW(LWM2M_DEVICE_TIME_ID), + EX(LWM2M_DEVICE_FACTORY_DEFAULT_ID), + }; + +#ifndef LWM2M_DEVICE_MANUFACTURER +#define LWM2M_DEVICE_MANUFACTURER "RISE SICS" +#endif +#ifndef LWM2M_DEVICE_MODEL_NUMBER +#define LWM2M_DEVICE_MODEL_NUMBER "1" +#endif +#ifndef LWM2M_DEVICE_SERIAL_NUMBER +#define LWM2M_DEVICE_SERIAL_NUMBER "1" +#endif +#ifndef LWM2M_DEVICE_FIRMWARE_VERSION +#define LWM2M_DEVICE_FIRMWARE_VERSION CONTIKI_VERSION +#endif +#ifndef LWM2M_DEVICE_TYPE +#define LWM2M_DEVICE_TYPE "Contiki-NG LWM2M" +#endif + +/* All three must be defined */ +#ifndef LWM2M_DEVICE_POWER_AVAILABLE +#define LWM2M_DEVICE_POWER_AVAILABLE {1,5} +#define LWM2M_DEVICE_POWER_VOLTAGE {2500,5000} +#define LWM2M_DEVICE_POWER_CURRENT {500,1000} #endif static int32_t time_offset = 0; + +/* Internal battery and USB - just for test...*/ +static uint16_t power_avail[] = LWM2M_DEVICE_POWER_AVAILABLE; +static uint16_t power_voltage[] = LWM2M_DEVICE_POWER_VOLTAGE; +static uint16_t power_current[] = LWM2M_DEVICE_POWER_CURRENT; /*---------------------------------------------------------------------------*/ -static int -read_lwtime(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +int32_t +lwm2m_device_get_time(void) { - return ctx->writer->write_int(ctx, outbuf, outsize, - time_offset + clock_seconds()); + return coap_timer_seconds() + time_offset; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_device_set_time(int32_t time) +{ + time_offset = time - coap_timer_seconds(); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +write_string(lwm2m_context_t *ctx, const char *text) +{ + lwm2m_object_write_string(ctx, text, strlen(text)); + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ static int -set_lwtime(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) +output_multi_i16(lwm2m_context_t *ctx, const uint16_t *data, int count) { - /* assume that this only read one TLV value */ - int32_t lw_time; - size_t len = ctx->reader->read_int(ctx, inbuf, insize, &lw_time); - if(len == 0) { - PRINTF("FAIL: could not read time '%*.s'\n", (int)insize, inbuf); - } else { - PRINTF("Got: time: %*.s => %" PRId32 "\n", (int)insize, inbuf, lw_time); - - time_offset = lw_time - clock_seconds(); - PRINTF("Write time...%" PRId32 " => offset = %" PRId32 "\n", - lw_time, time_offset); + int i; + size_t len; + len = lwm2m_object_write_enter_ri(ctx); + for(i = 0; i < count; i++) { + len += lwm2m_object_write_int_ri(ctx, i, data[i]); } - /* return the number of bytes read */ + len += lwm2m_object_write_exit_ri(ctx); return len; } + /*---------------------------------------------------------------------------*/ -#ifdef PLATFORM_REBOOT -static struct ctimer reboot_timer; -static void -do_the_reboot(void *ptr) -{ - PLATFORM_REBOOT(); -} static int -reboot(lwm2m_context_t *ctx, const uint8_t *arg, size_t argsize, - uint8_t *outbuf, size_t outsize) +lwm2m_dim_callback(lwm2m_object_instance_t *object, uint16_t resource_id) { - PRINTF("Device will reboot!\n"); - ctimer_set(&reboot_timer, CLOCK_SECOND / 2, do_the_reboot, NULL); + switch(resource_id) { + case LWM2M_DEVICE_AVAILABLE_POWER_SOURCES: + case LWM2M_DEVICE_POWER_SOURCE_VOLTAGE: + case LWM2M_DEVICE_POWER_SOURCE_CURRENT: + return sizeof(power_avail) / sizeof(uint16_t); + break; + } + /* zero means that it is no dim parameter to send?? */ return 0; } -#endif /* PLATFORM_REBOOT */ /*---------------------------------------------------------------------------*/ -#ifdef PLATFORM_FACTORY_DEFAULT -static int -factory_reset(lwm2m_context_t *ctx, const uint8_t *arg, size_t arg_size, - uint8_t *outbuf, size_t outsize) +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) { - PRINTF("Device will do factory default!\n"); - PLATFORM_FACTORY_DEFAULT(); - return 0; + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_DEVICE_MANUFACTURER_ID: + return write_string(ctx, LWM2M_DEVICE_MANUFACTURER); + case LWM2M_DEVICE_MODEL_NUMBER_ID: + return write_string(ctx, LWM2M_DEVICE_MODEL_NUMBER); + case LWM2M_DEVICE_SERIAL_NUMBER_ID: + return write_string(ctx, LWM2M_DEVICE_SERIAL_NUMBER); + case LWM2M_DEVICE_FIRMWARE_VERSION_ID: + return write_string(ctx, LWM2M_DEVICE_FIRMWARE_VERSION); + case LWM2M_DEVICE_TYPE_ID: + return write_string(ctx, LWM2M_DEVICE_TYPE); + case LWM2M_DEVICE_TIME_ID: + LOG_DBG("Reading time: %u\n", (unsigned int)lwm2m_device_get_time()); + lwm2m_object_write_int(ctx, lwm2m_device_get_time()); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_AVAILABLE_POWER_SOURCES: + /* Power Multi-resource case - just use array index as ID */ + output_multi_i16(ctx, power_avail, + sizeof(power_avail)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_POWER_SOURCE_VOLTAGE: + output_multi_i16(ctx, power_voltage, + sizeof(power_voltage)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_POWER_SOURCE_CURRENT: + output_multi_i16(ctx, power_current, + sizeof(power_current)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + default: + LOG_WARN("Not found: %u\n", ctx->resource_id); + return LWM2M_STATUS_NOT_FOUND; + } + + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == LWM2M_DEVICE_REBOOT_ID) { + /* Do THE REBOOT */ + LOG_INFO("REBOOT\n"); + return LWM2M_STATUS_OK; + } + + } else if(ctx->operation == LWM2M_OP_WRITE) { + if(ctx->resource_id == LWM2M_DEVICE_TIME_ID) { + int32_t lw_time; + size_t len; + len = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, + &lw_time); + if(len == 0) { + LOG_WARN("FAIL: could not write time\n"); + return LWM2M_STATUS_WRITE_ERROR; + } else { + lwm2m_device_set_time(lw_time); + LOG_DBG("Write time %lu sec => offset = %ld\n", + (unsigned long)lw_time, (long)time_offset); + return LWM2M_STATUS_OK; + } + } + } + + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; } -#endif /* PLATFORM_FACTORY_DEFAULT */ /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(device_resources, -#ifdef LWM2M_DEVICE_MANUFACTURER - LWM2M_RESOURCE_STRING(0, LWM2M_DEVICE_MANUFACTURER), -#endif /* LWM2M_DEVICE_MANUFACTURER */ -#ifdef LWM2M_DEVICE_TYPE - LWM2M_RESOURCE_STRING(17, LWM2M_DEVICE_TYPE), -#endif /* LWM2M_DEVICE_TYPE */ -#ifdef LWM2M_DEVICE_MODEL_NUMBER - LWM2M_RESOURCE_STRING(1, LWM2M_DEVICE_MODEL_NUMBER), -#endif /* LWM2M_DEVICE_MODEL_NUMBER */ -#ifdef LWM2M_DEVICE_SERIAL_NO - LWM2M_RESOURCE_STRING(2, LWM2M_DEVICE_SERIAL_NO), -#endif /* LWM2M_DEVICE_SERIAL_NO */ -#ifdef LWM2M_DEVICE_FIRMWARE_VERSION - LWM2M_RESOURCE_STRING(3, LWM2M_DEVICE_FIRMWARE_VERSION), -#endif /* LWM2M_DEVICE_FIRMWARE_VERSION */ -#ifdef PLATFORM_REBOOT - LWM2M_RESOURCE_CALLBACK(4, { NULL, NULL, reboot }), -#endif /* PLATFORM_REBOOT */ -#ifdef PLATFORM_FACTORY_DEFAULT - LWM2M_RESOURCE_CALLBACK(5, { NULL, NULL, factory_reset }), -#endif /* PLATFORM_FACTORY_DEFAULT */ - /* Current Time */ - LWM2M_RESOURCE_CALLBACK(13, { read_lwtime, set_lwtime, NULL }), - ); -LWM2M_INSTANCES(device_instances, LWM2M_INSTANCE(0, device_resources)); -LWM2M_OBJECT(device, 3, device_instances); +static lwm2m_object_instance_t device = { + .object_id = LWM2M_OBJECT_DEVICE_ID, + .instance_id = 0, + .resource_ids = resources, + .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t), + .resource_dim_callback = lwm2m_dim_callback, + .callback = lwm2m_callback, +}; /*---------------------------------------------------------------------------*/ void lwm2m_device_init(void) { - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle. - */ - PRINTF("*** Init lwm2m-device\n"); - lwm2m_engine_register_object(&device); + lwm2m_engine_add_object(&device); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-device.h b/os/services/lwm2m/lwm2m-device.h index 4587822d5..d7389153c 100644 --- a/os/services/lwm2m/lwm2m-device.h +++ b/os/services/lwm2m/lwm2m-device.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -46,6 +46,22 @@ #include "contiki.h" +#define LWM2M_DEVICE_MANUFACTURER_ID 0 +#define LWM2M_DEVICE_MODEL_NUMBER_ID 1 +#define LWM2M_DEVICE_SERIAL_NUMBER_ID 2 +#define LWM2M_DEVICE_FIRMWARE_VERSION_ID 3 +#define LWM2M_DEVICE_REBOOT_ID 4 +#define LWM2M_DEVICE_FACTORY_DEFAULT_ID 5 +#define LWM2M_DEVICE_AVAILABLE_POWER_SOURCES 6 +/* These do have multiple instances */ +#define LWM2M_DEVICE_POWER_SOURCE_VOLTAGE 7 +#define LWM2M_DEVICE_POWER_SOURCE_CURRENT 8 +#define LWM2M_DEVICE_BATTERY_LEVEL 9 + +#define LWM2M_DEVICE_ERROR_CODE 11 +#define LWM2M_DEVICE_TIME_ID 13 +#define LWM2M_DEVICE_TYPE_ID 17 + #ifndef LWM2M_DEVICE_MODEL_NUMBER #ifdef BOARD_STRING #define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING @@ -53,9 +69,14 @@ #endif /* LWM2M_DEVICE_MODEL_NUMBER */ #ifndef LWM2M_DEVICE_FIRMWARE_VERSION +#ifdef CONTIKI_VERSION_STRING #define LWM2M_DEVICE_FIRMWARE_VERSION CONTIKI_VERSION_STRING +#endif /* CONTIKI_VERSION_STRING */ #endif /* LWM2M_DEVICE_FIRMWARE_VERSION */ +int32_t lwm2m_device_get_time(void); +void lwm2m_device_set_time(int32_t time); + void lwm2m_device_init(void); #endif /* LWM2M_DEVICE_H_ */ diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 1e313718f..b96674215 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -41,29 +41,30 @@ * Niclas Finne */ -#include "contiki.h" #include "lwm2m-engine.h" #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-plain-text.h" #include "lwm2m-json.h" -#include "net/app-layer/coap/rest-engine.h" -#include "net/app-layer/coap/coap-constants.h" -#include "net/app-layer/coap/coap-engine.h" -#include "oma-tlv.h" -#include "oma-tlv-reader.h" -#include "oma-tlv-writer.h" -#include "net/ipv6/uip-ds6.h" +#include "coap-constants.h" +#include "coap-engine.h" +#include "lwm2m-tlv.h" +#include "lwm2m-tlv-reader.h" +#include "lwm2m-tlv-writer.h" +#include "lib/list.h" +#include "sys/cc.h" #include #include #include -#if UIP_CONF_IPV6_RPL -#include "rpl.h" -#endif /* UIP_CONF_IPV6_RPL */ +#ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME +#include "net/ipv6/uip-ds6.h" +#endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-engine" +#define LOG_LEVEL LOG_LEVEL_LWM2M #ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX #ifdef LWM2M_DEVICE_MODEL_NUMBER @@ -73,342 +74,450 @@ #endif /* LWM2M_DEVICE_MODEL_NUMBER */ #endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX */ -#ifdef LWM2M_ENGINE_CONF_MAX_OBJECTS -#define MAX_OBJECTS LWM2M_ENGINE_CONF_MAX_OBJECTS -#else /* LWM2M_ENGINE_CONF_MAX_OBJECTS */ -#define MAX_OBJECTS 10 -#endif /* LWM2M_ENGINE_CONF_MAX_OBJECTS */ +#ifdef LWM2M_ENGINE_CONF_USE_RD_CLIENT +#define USE_RD_CLIENT LWM2M_ENGINE_CONF_USE_RD_CLIENT +#else +#define USE_RD_CLIENT 1 +#endif /* LWM2M_ENGINE_CONF_USE_RD_CLIENT */ -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) -#define BS_REMOTE_PORT UIP_HTONS(5685) +#if USE_RD_CLIENT +#include "lwm2m-rd-client.h" +#endif -static const lwm2m_object_t *objects[MAX_OBJECTS]; -static char endpoint[32]; -static char rd_data[128]; /* allocate some data for the RD */ +/* 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) +#define RSC_WRITABLE(x) ((x & LWM2M_RESOURCE_WRITE) > 0) +#define RSC_UNSPECIFIED(x) ((x & LWM2M_RESOURCE_OP_MASK) == 0) -PROCESS(lwm2m_rd_client, "LWM2M Engine"); +/* invalid instance ID - ffff object ID */ +#define NO_INSTANCE 0xffffffff -static uip_ipaddr_t server_ipaddr; -static uint16_t server_port = REMOTE_PORT; -static uip_ipaddr_t bs_server_ipaddr; -static uint16_t bs_server_port = BS_REMOTE_PORT; +/* This is a double-buffer for generating BLOCKs in CoAP - the idea + is that typical LWM2M resources will fit 1 block unless they themselves + handle BLOCK transfer - having a double sized buffer makes it possible + to allow writing more than one block before sending the full block. + The RFC seems to indicate that all blocks execept the last one should + be full. +*/ +static uint8_t d_buf[COAP_MAX_BLOCK_SIZE * 2]; +static lwm2m_buffer_t lwm2m_buf = { + .len = 0, .size = COAP_MAX_BLOCK_SIZE * 2, .buffer = d_buf +}; +static lwm2m_object_instance_t instance_buffer; -static uint8_t use_bootstrap = 0; -static uint8_t has_bootstrap_server_info = 0; -static uint8_t use_registration = 0; -static uint8_t has_registration_server_info = 0; -static uint8_t registered = 0; -static uint8_t bootstrapped = 0; /* bootstrap made... */ +/* obj-id / ... */ +static uint16_t lwm2m_buf_lock[4]; +static uint64_t lwm2m_buf_lock_timeout = 0; -void lwm2m_device_init(void); -void lwm2m_security_init(void); -void lwm2m_server_init(void); +static lwm2m_write_opaque_callback current_opaque_callback; +static int current_opaque_offset = 0; + +static coap_handler_status_t lwm2m_handler_callback(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, + uint16_t buffer_size, + int32_t *offset); +static lwm2m_object_instance_t * +next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, lwm2m_object_instance_t *last); + +static struct { + uint16_t object_id; + uint16_t instance_id; + uint16_t token_len; + uint8_t token[COAP_TOKEN_LEN]; + /* in the future also a timeout */ +} created; + + +COAP_HANDLER(lwm2m_handler, lwm2m_handler_callback); +LIST(object_list); +LIST(generic_object_list); -static const lwm2m_instance_t *get_first_instance_of_object(uint16_t id, lwm2m_context_t *context); -static const lwm2m_instance_t *get_instance(const lwm2m_object_t *object, lwm2m_context_t *context, int depth); -static const lwm2m_resource_t *get_resource(const lwm2m_instance_t *instance, lwm2m_context_t *context); /*---------------------------------------------------------------------------*/ -static void -client_chunk_handler(void *response) +static lwm2m_object_t * +get_object(uint16_t object_id) { -#if (DEBUG) & DEBUG_PRINT - const uint8_t *chunk; - - int len = coap_get_payload(response, &chunk); - - PRINTF("|%.*s\n", len, (char *)chunk); -#endif /* (DEBUG) & DEBUG_PRINT */ -} -/*---------------------------------------------------------------------------*/ -static int -index_of(const uint8_t *data, int offset, int len, uint8_t c) -{ - if(offset < 0) { - return offset; - } - for(; offset < len; offset++) { - if(data[offset] == c) { - return offset; + lwm2m_object_t *object; + for(object = list_head(generic_object_list); + object != NULL; + object = object->next) { + if(object->impl && object->impl->object_id == object_id) { + return object; } } - return -1; + return NULL; } /*---------------------------------------------------------------------------*/ static int -has_network_access(void) +has_non_generic_object(uint16_t object_id) { -#if UIP_CONF_IPV6_RPL - if(rpl_get_any_dag() == NULL) { + lwm2m_object_instance_t *instance; + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(instance->object_id == object_id) { + return 1; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_instance(uint16_t object_id, uint16_t instance_id, lwm2m_object_t **o) +{ + lwm2m_object_instance_t *instance; + lwm2m_object_t *object; + + if(o) { + *o = NULL; + } + + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(instance->object_id == object_id) { + if(instance->instance_id == instance_id || + instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + return instance; + } + } + } + + object = get_object(object_id); + if(object != NULL) { + if(o) { + *o = object; + } + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + return object->impl->get_first(NULL); + } + return object->impl->get_by_id(instance_id, NULL); + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_instance_by_context(const lwm2m_context_t *context, lwm2m_object_t **o) +{ + if(context->level < 2) { + return get_instance(context->object_id, LWM2M_OBJECT_INSTANCE_NONE, o); + } + return get_instance(context->object_id, context->object_instance_id, o); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +call_instance(lwm2m_object_instance_t *instance, lwm2m_context_t *context) +{ + if(context->level < 3) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + + if(instance == NULL) { + /* No instance */ + return LWM2M_STATUS_NOT_FOUND; + } + + if(instance->callback == NULL) { + return LWM2M_STATUS_ERROR; + } + + return instance->callback(instance, context); +} +/*---------------------------------------------------------------------------*/ +/* This is intended to switch out a block2 transfer buffer + * It assumes that ctx containts the double buffer and that the outbuf is to + * be the new buffer in ctx. + */ +static int +double_buffer_flush(lwm2m_buffer_t *ctxbuf, lwm2m_buffer_t *outbuf, int size) +{ + /* Copy the data from the double buffer in ctx to the outbuf and move data */ + /* If the buffer is less than size - we will output all and get remaining down + to zero */ + if(ctxbuf->len < size) { + size = ctxbuf->len; + } + if(ctxbuf->len >= size && outbuf->size >= size) { + LOG_DBG("Double buffer - copying out %d bytes remaining: %d\n", + size, ctxbuf->len - size); + memcpy(outbuf->buffer, ctxbuf->buffer, size); + memcpy(ctxbuf->buffer, &ctxbuf->buffer[size], + ctxbuf->len - size); + ctxbuf->len -= size; + outbuf->len = size; + return outbuf->len; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static inline const char * +get_method_as_string(coap_resource_flags_t method) +{ + if(method == METHOD_GET) { + return "GET"; + } else if(method == METHOD_POST) { + return "POST"; + } else if(method == METHOD_PUT) { + return "PUT"; + } else if(method == METHOD_DELETE) { + return "DELETE"; + } else { + return "UNKNOWN"; + } +} +/*--------------------------------------------------------------------------*/ +static const char * +get_status_as_string(lwm2m_status_t status) +{ + static char buffer[8]; + switch(status) { + case LWM2M_STATUS_OK: + return "OK"; + case LWM2M_STATUS_ERROR: + return "ERROR"; + case LWM2M_STATUS_WRITE_ERROR: + return "WRITE ERROR"; + case LWM2M_STATUS_READ_ERROR: + return "READ ERROR"; + case LWM2M_STATUS_BAD_REQUEST: + return "BAD REQUEST"; + case LWM2M_STATUS_UNAUTHORIZED: + return "UNAUTHORIZED"; + case LWM2M_STATUS_FORBIDDEN: + return "FORBIDDEN"; + case LWM2M_STATUS_NOT_FOUND: + return "NOT FOUND"; + case LWM2M_STATUS_OPERATION_NOT_ALLOWED: + return "OPERATION NOT ALLOWED"; + case LWM2M_STATUS_NOT_ACCEPTABLE: + return "NOT ACCEPTABLE"; + case LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT: + return "UNSUPPORTED CONTENT FORMAT"; + case LWM2M_STATUS_NOT_IMPLEMENTED: + return "NOT IMPLEMENTED"; + case LWM2M_STATUS_SERVICE_UNAVAILABLE: + return "SERVICE UNAVAILABLE"; + default: + snprintf(buffer, sizeof(buffer) - 1, "<%u>", status); + return buffer; + } +} +/*--------------------------------------------------------------------------*/ +static int +parse_path(const char *path, int path_len, + uint16_t *oid, uint16_t *iid, uint16_t *rid) +{ + int ret; + int pos; + uint16_t val; + char c = 0; + + /* get object id */ + LOG_DBG("parse PATH: \""); + LOG_DBG_COAP_STRING(path, path_len); + LOG_DBG_("\"\n"); + + ret = 0; + pos = 0; + do { + val = 0; + /* we should get a value first - consume all numbers */ + while(pos < path_len && (c = path[pos]) >= '0' && c <= '9') { + val = val * 10 + (c - '0'); + pos++; + } + /* Slash will mote thing forward - and the end will be when pos == pl */ + if(c == '/' || pos == path_len) { + /* PRINTF("Setting %u = %u\n", ret, val); */ + if(ret == 0) *oid = val; + if(ret == 1) *iid = val; + if(ret == 2) *rid = val; + ret++; + pos++; + } else { + /* PRINTF("Error: illegal char '%c' at pos:%d\n", c, pos); */ + return -1; + } + } while(pos < path_len); + return ret; +} +/*--------------------------------------------------------------------------*/ +static int +lwm2m_engine_parse_context(const char *path, int path_len, + coap_message_t *request, coap_message_t *response, + uint8_t *outbuf, size_t outsize, + lwm2m_context_t *context) +{ + int ret; + if(context == NULL || path == NULL) { return 0; } -#endif /* UIP_CONF_IPV6_RPL */ - return 1; + + ret = parse_path(path, path_len, &context->object_id, + &context->object_instance_id, &context->resource_id); + + if(ret > 0) { + context->level = ret; + } + + return ret; +} + +/*---------------------------------------------------------------------------*/ +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb) +{ + /* Here we should set the callback for the opaque that we are currently generating... */ + /* And we should in the future associate the callback with the CoAP message info - MID */ + LOG_DBG("Setting opaque handler - offset: %"PRIu32",%d\n", + ctx->offset, ctx->outbuf->len); + + current_opaque_offset = 0; + current_opaque_callback = cb; } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_bootstrap_server(int use) +int +lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) { - use_bootstrap = use != 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_registration_server(int use) -{ - use_registration = use != 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_server(const uip_ipaddr_t *server, uint16_t port) -{ - uip_ipaddr_copy(&server_ipaddr, server); - if(port != 0) { - server_port = port; - } else { - server_port = REMOTE_PORT; - } - has_registration_server_info = 1; - registered = 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -static int -update_registration_server(void) -{ - if(has_registration_server_info) { - return 1; + /* remember things here - need to lock lwm2m buffer also!!! */ + static lwm2m_object_t *object; + static lwm2m_object_instance_t *instance; + int len; + /* pick size from outbuf */ + int maxsize = outbuf->size; + + if(lwm2m_buf_lock[0] != 0 && (lwm2m_buf_lock_timeout > coap_timer_uptime()) && + ((lwm2m_buf_lock[1] != 0xffff) || + (lwm2m_buf_lock[2] != 0xffff))) { + LOG_DBG("Set-RD: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + /* fail - what should we return here? */ + return 0; } -#if UIP_CONF_IPV6_RPL - { - rpl_dag_t *dag; + if(block == 0) { + LOG_DBG("Starting RD generation\n"); + /* start with simple object instances */ + instance = list_head(object_list); + object = NULL; - /* Use the DAG id as server address if no other has been specified */ - dag = rpl_get_any_dag(); - if(dag != NULL) { - uip_ipaddr_copy(&server_ipaddr, &dag->dag_id); - server_port = REMOTE_PORT; - return 1; - } - } -#endif /* UIP_CONF_IPV6_RPL */ - - return 0; -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_bootstrap_server(const uip_ipaddr_t *server, - uint16_t port) -{ - uip_ipaddr_copy(&bs_server_ipaddr, server); - if(port != 0) { - bs_server_port = port; - } else { - bs_server_port = BS_REMOTE_PORT; - } - has_bootstrap_server_info = 1; - bootstrapped = 0; - registered = 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -static int -update_bootstrap_server(void) -{ - if(has_bootstrap_server_info) { - return 1; - } - -#if UIP_CONF_IPV6_RPL - { - rpl_dag_t *dag; - - /* Use the DAG id as server address if no other has been specified */ - dag = rpl_get_any_dag(); - if(dag != NULL) { - uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); - bs_server_port = REMOTE_PORT; - return 1; - } - } -#endif /* UIP_CONF_IPV6_RPL */ - - return 0; -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(lwm2m_rd_client, ev, data) -{ - static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ - static struct etimer et; - - PROCESS_BEGIN(); - - printf("RD Client started with endpoint '%s'\n", endpoint); - - etimer_set(&et, 15 * CLOCK_SECOND); - - while(1) { - PROCESS_YIELD(); - - if(etimer_expired(&et)) { - if(!has_network_access()) { - /* Wait until for a network to join */ - } else if(use_bootstrap && bootstrapped == 0) { - if(update_bootstrap_server()) { - /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ - coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); - coap_set_header_uri_path(request, "/bs"); - coap_set_header_uri_query(request, endpoint); - - printf("Registering ID with bootstrap server ["); - uip_debug_ipaddr_print(&bs_server_ipaddr); - printf("]:%u as '%s'\n", uip_ntohs(bs_server_port), endpoint); - - COAP_BLOCKING_REQUEST(&bs_server_ipaddr, bs_server_port, request, - client_chunk_handler); - bootstrapped++; - } - } else if(use_bootstrap && bootstrapped == 1) { - lwm2m_context_t context; - const lwm2m_instance_t *instance = NULL; - const lwm2m_resource_t *rsc; - const uint8_t *first; - int len; - - PRINTF("*** Bootstrap - checking for server info...\n"); - - /* get the security object */ - instance = get_first_instance_of_object(LWM2M_OBJECT_SECURITY_ID, &context); - if(instance != NULL) { - /* get the server URI */ - context.resource_id = LWM2M_SECURITY_SERVER_URI; - rsc = get_resource(instance, &context); - first = lwm2m_object_get_resource_string(rsc, &context); - len = lwm2m_object_get_resource_strlen(rsc, &context); - if(first != NULL && len > 0) { - int start, end; - uip_ipaddr_t addr; - int32_t port; - uint8_t secure = 0; - - PRINTF("**** Found security instance using: %.*s\n", len, first); - /* TODO Should verify it is a URI */ - - /* Check if secure */ - secure = strncmp((const char *)first, "coaps:", 6) == 0; - - /* Only IPv6 supported */ - start = index_of(first, 0, len, '['); - end = index_of(first, start, len, ']'); - if(start > 0 && end > start && - uiplib_ipaddrconv((const char *)&first[start], &addr)) { - if(first[end + 1] == ':' && - lwm2m_plain_text_read_int(first + end + 2, len - end - 2, &port)) { - } else if(secure) { - /** - * Secure CoAP should use a different port but for now - * the same port is used. - */ - port = COAP_DEFAULT_PORT; - } else { - port = COAP_DEFAULT_PORT; - } - PRINTF("Server address "); - PRINT6ADDR(&addr); - PRINTF(" port %" PRId32 "%s\n", port, secure ? " (secure)" : ""); - if(secure) { - printf("Secure CoAP requested but not supported - can not bootstrap\n"); - } else { - lwm2m_engine_register_with_server(&addr, - UIP_HTONS((uint16_t)port)); - bootstrapped++; - } - } else { - printf("** failed to parse URI %.*s\n", len, first); - } - } - } - - if(bootstrapped == 1) { - /* Not ready. Lets retry with the bootstrap server again */ - bootstrapped = 0; - } - - } else if(use_registration && !registered && - update_registration_server()) { - int pos; - int len, i, j; - registered = 1; - - /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ - coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); - coap_set_header_uri_path(request, "/rd"); - coap_set_header_uri_query(request, endpoint); - - /* generate the rd data */ - pos = 0; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] != NULL) { - for(j = 0; j < objects[i]->count; j++) { - if(objects[i]->instances[j].flag & LWM2M_INSTANCE_FLAG_USED) { - len = snprintf(&rd_data[pos], sizeof(rd_data) - pos, - "%s<%d/%d>", pos > 0 ? "," : "", - objects[i]->id, objects[i]->instances[j].id); - if(len > 0 && len < sizeof(rd_data) - pos) { - pos += len; - } - } - } - } - } - - coap_set_payload(request, (uint8_t *)rd_data, pos); - - printf("Registering with ["); - uip_debug_ipaddr_print(&server_ipaddr); - printf("]:%u lwm2m endpoint '%s': '%.*s'\n", uip_ntohs(server_port), - endpoint, pos, rd_data); - COAP_BLOCKING_REQUEST(&server_ipaddr, server_port, request, - client_chunk_handler); + if(instance == NULL) { + /* No simple object instances available */ + object = list_head(generic_object_list); + if(object == NULL) { + /* No objects of any kind available */ + return 0; } - /* for now only register once... registered = 0; */ - etimer_set(&et, 15 * CLOCK_SECOND); + if(object->impl != NULL) { + instance = object->impl->get_first(NULL); + } + } + + lwm2m_buf_lock[0] = 1; /* lock "flag" */ + lwm2m_buf_lock[1] = 0xffff; + lwm2m_buf_lock[2] = 0xffff; + lwm2m_buf_lock[3] = 0xffff; + } else { + /* object and instance was static... */ + } + + lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; + + LOG_DBG("Generating RD list:"); + while(instance != NULL || object != NULL) { + int pos = lwm2m_buf.len; + if(instance != NULL) { + len = snprintf((char *) &lwm2m_buf.buffer[pos], + lwm2m_buf.size - pos, (pos > 0 || block > 0) ? "," : "", + instance->object_id, instance->instance_id); + LOG_DBG_((pos > 0 || block > 0) ? "," : "", + instance->object_id, instance->instance_id); + } else if(object->impl != NULL) { + len = snprintf((char *) &lwm2m_buf.buffer[pos], + lwm2m_buf.size - pos, + (pos > 0 || block > 0) ? "," : "", + object->impl->object_id); + LOG_DBG_((pos > 0 || block > 0) ? "," : "", + object->impl->object_id); + } else { + len = 0; + } + lwm2m_buf.len += len; + if(instance != NULL) { + instance = next_object_instance(NULL, object, instance); + } + + if(instance == NULL) { + if(object == NULL) { + /* + * No object and no instance - we are done with simple object instances. + */ + object = list_head(generic_object_list); + } else { + /* + * Object exists but not an instance - instances for this object are + * done - go to next. + */ + object = object->next; + } + + if(object != NULL && object->impl != NULL) { + instance = object->impl->get_first(NULL); + } + + if(instance == NULL && object == NULL && lwm2m_buf.len <= maxsize) { + /* Data generation is done. No more messages are needed after this. */ + break; + } + } + + if(lwm2m_buf.len >= maxsize) { + LOG_DBG_("\n"); + LOG_DBG("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + /* If the produced data is larger than a CoAP block we need to send + this now */ + double_buffer_flush(&lwm2m_buf, outbuf, maxsize); + /* there will be more - keep lock! */ + return 1; } } - PROCESS_END(); + LOG_DBG_("\n"); + double_buffer_flush(&lwm2m_buf, outbuf, maxsize); + /* unlock the buffer */ + lwm2m_buf_lock[0] = 0; + return 0; } /*---------------------------------------------------------------------------*/ void lwm2m_engine_init(void) { -#ifdef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME + list_init(object_list); + list_init(generic_object_list); - snprintf(endpoint, sizeof(endpoint) - 1, - "?ep=" LWM2M_ENGINE_CLIENT_ENDPOINT_NAME); +#ifdef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME + const char *endpoint = LWM2M_ENGINE_CLIENT_ENDPOINT_NAME; #else /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ - + static char endpoint[32]; int len, i; uint8_t state; uip_ipaddr_t *ipaddr; - char client[sizeof(endpoint)]; len = strlen(LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX); /* ensure that this fits with the hex-nums */ - if(len > sizeof(client) - 13) { - len = sizeof(client) - 13; + if(len > sizeof(endpoint) - 13) { + len = sizeof(endpoint) - 13; } - memcpy(client, LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX, len); + for(i = 0; i < len; i++) { + if(LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX[i] == ' ') { + endpoint[i] = '-'; + } else { + endpoint[i] = LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX[i]; + } + } /* pick an IP address that is PREFERRED or TENTATIVE */ ipaddr = NULL; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { @@ -424,705 +533,1110 @@ lwm2m_engine_init(void) for(i = 0; i < 6; i++) { /* assume IPv6 for now */ uint8_t b = ipaddr->u8[10 + i]; - client[len++] = (b >> 4) > 9 ? 'A' - 10 + (b >> 4) : '0' + (b >> 4); - client[len++] = (b & 0xf) > 9 ? 'A' - 10 + (b & 0xf) : '0' + (b & 0xf); + endpoint[len++] = (b >> 4) > 9 ? 'A' - 10 + (b >> 4) : '0' + (b >> 4); + endpoint[len++] = (b & 0xf) > 9 ? 'A' - 10 + (b & 0xf) : '0' + (b & 0xf); } } /* a zero at end of string */ - client[len] = 0; - /* create endpoint */ - snprintf(endpoint, sizeof(endpoint) - 1, "?ep=%s", client); + endpoint[len] = 0; #endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ - rest_init_engine(); - process_start(&lwm2m_rd_client, NULL); + coap_engine_init(); + + /* Register the CoAP handler for lightweight object handling */ + coap_add_handler(&lwm2m_handler); + +#if USE_RD_CLIENT + lwm2m_rd_client_init(endpoint); +#endif } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_default_objects(void) -{ - lwm2m_security_init(); - lwm2m_server_init(); - lwm2m_device_init(); -} -/*---------------------------------------------------------------------------*/ -static int -parse_next(const char **path, int *path_len, uint16_t *value) -{ - char c; - *value = 0; - /* printf("parse_next: %p %d\n", *path, *path_len); */ - if(*path_len == 0) { - return 0; - } - while(*path_len > 0) { - c = **path; - (*path)++; - *path_len = *path_len - 1; - if(c >= '0' && c <= '9') { - *value = *value * 10 + (c - '0'); - } else if(c == '/') { - return 1; - } else { - /* error */ - return -4; - } - } - return 1; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_engine_parse_context(const lwm2m_object_t *object, - const char *path, int path_len, - lwm2m_context_t *context) -{ - int ret; - if(context == NULL || object == NULL || path == NULL) { - return 0; - } - memset(context, 0, sizeof(lwm2m_context_t)); - /* get object id */ - ret = 0; - ret += parse_next(&path, &path_len, &context->object_id); - ret += parse_next(&path, &path_len, &context->object_instance_id); - ret += parse_next(&path, &path_len, &context->resource_id); - - /* Set default reader/writer */ - context->reader = &lwm2m_plain_text_reader; - context->writer = &oma_tlv_writer; - - return ret; -} -/*---------------------------------------------------------------------------*/ -const lwm2m_object_t * -lwm2m_engine_get_object(uint16_t id) -{ - int i; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] != NULL && objects[i]->id == id) { - return objects[i]; - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_engine_register_object(const lwm2m_object_t *object) -{ - int i; - int found = 0; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] == NULL) { - objects[i] = object; - found = 1; - break; - } - } - rest_activate_resource(lwm2m_object_get_coap_resource(object), - (char *)object->path); - return found; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_first_instance_of_object(uint16_t id, lwm2m_context_t *context) -{ - const lwm2m_object_t *object; - int i; - - object = lwm2m_engine_get_object(id); - if(object == NULL) { - /* No object with the specified id found */ - return NULL; - } - - /* Initialize the context */ - memset(context, 0, sizeof(lwm2m_context_t)); - context->object_id = id; - - for(i = 0; i < object->count; i++) { - if(object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) { - context->object_instance_id = object->instances[i].id; - context->object_instance_index = i; - return &object->instances[i]; - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_instance(const lwm2m_object_t *object, lwm2m_context_t *context, int depth) -{ - int i; - if(depth > 1) { - PRINTF("lwm2m: searching for instance %u\n", context->object_instance_id); - for(i = 0; i < object->count; i++) { - PRINTF(" Instance %d -> %u (used: %d)\n", i, object->instances[i].id, - (object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) != 0); - if(object->instances[i].id == context->object_instance_id && - object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) { - context->object_instance_index = i; - return &object->instances[i]; - } - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_resource_t * -get_resource(const lwm2m_instance_t *instance, lwm2m_context_t *context) -{ - int i; - if(instance != NULL) { - PRINTF("lwm2m: searching for resource %u\n", context->resource_id); - for(i = 0; i < instance->count; i++) { - PRINTF(" Resource %d -> %u\n", i, instance->resources[i].id); - if(instance->resources[i].id == context->resource_id) { - context->resource_index = i; - return &instance->resources[i]; - } - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -/** - * @brief Write a list of object instances as a CoRE Link-format list - */ -static int -write_object_instances_link(const lwm2m_object_t *object, - char *buffer, size_t size) -{ - const lwm2m_instance_t *instance; - int len, rdlen, i; - - PRINTF("", object->id); - rdlen = snprintf(buffer, size, "", - object->id); - if(rdlen < 0 || rdlen >= size) { - return -1; - } - - for(i = 0; i < object->count; i++) { - if((object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) == 0) { - continue; - } - instance = &object->instances[i]; - PRINTF(",", object->id, instance->id); - - len = snprintf(&buffer[rdlen], size - rdlen, - ",<%d/%d>", object->id, instance->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - } - return rdlen; -} -/*---------------------------------------------------------------------------*/ -static int -write_rd_link_data(const lwm2m_object_t *object, - const lwm2m_instance_t *instance, - char *buffer, size_t size) -{ - const lwm2m_resource_t *resource; - int len, rdlen, i; - - PRINTF("<%d/%d>", object->id, instance->id); - rdlen = snprintf(buffer, size, "<%d/%d>", - object->id, instance->id); - if(rdlen < 0 || rdlen >= size) { - return -1; - } - - for(i = 0; i < instance->count; i++) { - resource = &instance->resources[i]; - PRINTF(",<%d/%d/%d>", object->id, instance->id, resource->id); - - len = snprintf(&buffer[rdlen], size - rdlen, - ",<%d/%d/%d>", object->id, instance->id, resource->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - } - return rdlen; -} -/*---------------------------------------------------------------------------*/ -static int -write_rd_json_data(const lwm2m_context_t *context, - const lwm2m_object_t *object, - const lwm2m_instance_t *instance, - char *buffer, size_t size) -{ - const lwm2m_resource_t *resource; - const char *s = ""; - int len, rdlen, i; - - PRINTF("{\"e\":["); - rdlen = snprintf(buffer, size, "{\"e\":["); - if(rdlen < 0 || rdlen >= size) { - return -1; - } - - for(i = 0, len = 0; i < instance->count; i++) { - resource = &instance->resources[i]; - len = 0; - if(lwm2m_object_is_resource_string(resource)) { - const uint8_t *value; - uint16_t slen; - value = lwm2m_object_get_resource_string(resource, context); - slen = lwm2m_object_get_resource_strlen(resource, context); - if(value != NULL) { - PRINTF("%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, - resource->id, slen, value); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, - resource->id, slen, value); - } - } else if(lwm2m_object_is_resource_int(resource)) { - int32_t value; - if(lwm2m_object_get_resource_int(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, - resource->id, value); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, - resource->id, value); - } - } else if(lwm2m_object_is_resource_floatfix(resource)) { - int32_t value; - if(lwm2m_object_get_resource_floatfix(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, resource->id, - value / LWM2M_FLOAT32_FRAC); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"v\":", s, resource->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - - len = lwm2m_plain_text_write_float32fix((uint8_t *)&buffer[rdlen], - size - rdlen, - value, LWM2M_FLOAT32_BITS); - if(len == 0) { - return -1; - } - rdlen += len; - - if(rdlen < size) { - buffer[rdlen] = '}'; - } - len = 1; - } - } else if(lwm2m_object_is_resource_boolean(resource)) { - int value; - if(lwm2m_object_get_resource_boolean(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, - value ? "true" : "false"); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, - value ? "true" : "false"); - } - } - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - if(len > 0) { - s = ","; - } - } - PRINTF("]}\n"); - len = snprintf(&buffer[rdlen], size - rdlen, "]}"); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - - return rdlen; -} -/*---------------------------------------------------------------------------*/ -/** - * @brief Set the writer pointer to the proper writer based on the Accept: header +/* + * Set the writer pointer to the proper writer based on the Accept: header * - * @param[in] context LWM2M context to operate on - * @param[in] accept Accept type number from CoAP headers + * param[in] context LWM2M context to operate on + * param[in] accept Accept type number from CoAP headers * - * @return The content type of the response if the selected writer is used + * return The content type of the response if the selected writer is used */ static unsigned int lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) { switch(accept) { case LWM2M_TLV: - context->writer = &oma_tlv_writer; + case LWM2M_OLD_TLV: + context->writer = &lwm2m_tlv_writer; break; case LWM2M_TEXT_PLAIN: case TEXT_PLAIN: context->writer = &lwm2m_plain_text_writer; break; case LWM2M_JSON: + case LWM2M_OLD_JSON: case APPLICATION_JSON: context->writer = &lwm2m_json_writer; break; default: - PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept); + LOG_WARN("Unknown Accept type %u, using LWM2M plain text\n", accept); context->writer = &lwm2m_plain_text_writer; /* Set the response type to plain text */ accept = LWM2M_TEXT_PLAIN; break; } + context->content_type = accept; return accept; } /*---------------------------------------------------------------------------*/ -/** - * @brief Set the reader pointer to the proper reader based on the Content-format: header +/* + * Set the reader pointer to the proper reader based on the Content-format: header * - * @param[in] context LWM2M context to operate on - * @param[in] content_format Content-type type number from CoAP headers + * param[in] context LWM2M context to operate on + * param[in] content_format Content-type type number from CoAP headers */ static void lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format) { switch(content_format) { case LWM2M_TLV: - context->reader = &oma_tlv_reader; + case LWM2M_OLD_TLV: + context->reader = &lwm2m_tlv_reader; + break; + case LWM2M_JSON: + case LWM2M_OLD_JSON: + context->reader = &lwm2m_plain_text_reader; break; case LWM2M_TEXT_PLAIN: case TEXT_PLAIN: context->reader = &lwm2m_plain_text_reader; break; default: - PRINTF("Unknown content type %u, using LWM2M plain text\n", accept); + LOG_WARN("Unknown content type %u, using LWM2M plain text\n", + content_format); context->reader = &lwm2m_plain_text_reader; break; } } + /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset) +/* Lightweight object instances */ +/*---------------------------------------------------------------------------*/ +static uint32_t last_instance_id = NO_INSTANCE; +static int last_rsc_pos; + +/* Multi read will handle read of JSON / TLV or Discovery (Link Format) */ +static lwm2m_status_t +perform_multi_resource_read_op(lwm2m_object_t *object, + lwm2m_object_instance_t *instance, + lwm2m_context_t *ctx) { - int len; - const char *url; - unsigned int format; - unsigned int accept; - unsigned int content_type; - int depth; - lwm2m_context_t context; - rest_resource_flags_t method; - const lwm2m_instance_t *instance; -#if (DEBUG) & DEBUG_PRINT - const char *method_str; -#endif /* (DEBUG) & DEBUG_PRINT */ + int size = ctx->outbuf->size; + int len = 0; + uint8_t initialized = 0; /* used for commas, etc */ + uint8_t num_read = 0; + lwm2m_buffer_t *outbuf; - method = REST.get_method_type(request); - - len = REST.get_url(request, &url); - if(!REST.get_header_content_type(request, &format)) { - PRINTF("No format given. Assume text plain...\n"); - format = LWM2M_TEXT_PLAIN; - } else if(format == TEXT_PLAIN) { - /* CoAP content format text plain - assume LWM2M text plain */ - format = LWM2M_TEXT_PLAIN; - } - if(!REST.get_header_accept(request, &accept)) { - PRINTF("No Accept header, using same as Content-format...\n"); - accept = format; + if(instance == NULL) { + /* No existing instance */ + return LWM2M_STATUS_NOT_FOUND; } - depth = lwm2m_engine_parse_context(object, url, len, &context); - PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, - context.object_instance_id, context.resource_id, depth); + if(ctx->level < 3 && + (ctx->content_type == LWM2M_TEXT_PLAIN || + ctx->content_type == TEXT_PLAIN || + ctx->content_type == LWM2M_OLD_OPAQUE)) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } - /* Select reader and writer based on provided Content type and Accept headers */ - lwm2m_engine_select_reader(&context, format); - content_type = lwm2m_engine_select_writer(&context, accept); + /* copy out the out-buffer as read will use its own - will be same for disoc when + read is fixed */ + outbuf = ctx->outbuf; -#if (DEBUG) & DEBUG_PRINT - /* for debugging */ - if(method == METHOD_GET) { - method_str = "GET"; - } else if(method == METHOD_POST) { - method_str = "POST"; - } else if(method == METHOD_PUT) { - method_str = "PUT"; - } else if(method == METHOD_DELETE) { - method_str = "DELETE"; + /* Currently we only handle one incoming read request at a time - so we return + BUZY or service unavailable */ + if(lwm2m_buf_lock[0] != 0 && (lwm2m_buf_lock_timeout > coap_timer_uptime()) && + ((lwm2m_buf_lock[1] != ctx->object_id) || + (lwm2m_buf_lock[2] != ctx->object_instance_id) || + (lwm2m_buf_lock[3] != ctx->resource_id))) { + LOG_DBG("Multi-read: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + return LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + LOG_DBG("MultiRead: %d/%d/%d lv:%d offset:%"PRIu32"\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, + ctx->level, ctx->offset); + + /* Make use of the double buffer */ + ctx->outbuf = &lwm2m_buf; + + if(ctx->offset == 0) { + /* First GET request - need to setup all buffers and reset things here */ + last_instance_id = + ((uint32_t)instance->object_id << 16) | instance->instance_id; + last_rsc_pos = 0; + /* reset any callback */ + current_opaque_callback = NULL; + /* reset lwm2m_buf_len - so that we can use the double-size buffer */ + lwm2m_buf_lock[0] = 1; /* lock "flag" */ + lwm2m_buf_lock[1] = ctx->object_id; + lwm2m_buf_lock[2] = ctx->object_instance_id; + lwm2m_buf_lock[3] = ctx->resource_id; + lwm2m_buf.len = 0; + /* Here we should print top node */ } else { - method_str = "UNKNOWN"; - } - PRINTF("%s Called Path:%.*s Format:%d ID:%d bsize:%u\n", method_str, len, - url, format, object->id, preferred_size); - if(format == LWM2M_TEXT_PLAIN) { - /* a string */ - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - if(plen > 0) { - PRINTF("Data: '%.*s'\n", plen, (char *)data); + /* offset > 0 - assume that we are already in a disco or multi get*/ + instance = get_instance(last_instance_id >> 16, last_instance_id & 0xffff, + &object); + + /* we assume that this was initialized */ + initialized = 1; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; + if(instance == NULL) { + ctx->offset = -1; + ctx->outbuf->buffer[0] = ' '; } } -#endif /* (DEBUG) & DEBUG_PRINT */ + lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; - instance = get_instance(object, &context, depth); + while(instance != NULL) { + /* Do the discovery or read */ + if(instance->resource_ids != NULL && instance->resource_count > 0) { + /* show all the available resources (or read all) */ + while(last_rsc_pos < instance->resource_count) { + LOG_DBG("READ: 0x%"PRIx32" 0x%x 0x%x lv:%d\n", + instance->resource_ids[last_rsc_pos], + RSC_ID(instance->resource_ids[last_rsc_pos]), + ctx->resource_id, ctx->level); - /* from POST */ - if(depth > 1 && instance == NULL) { - if(method != METHOD_PUT && method != METHOD_POST) { - PRINTF("Error - do not have instance %d\n", context.object_instance_id); - REST.set_response_status(response, NOT_FOUND_4_04); - return; - } else { - const uint8_t *data; - int i, len, plen, pos; - oma_tlv_t tlv; - PRINTF(">>> CREATE ? %d/%d\n", context.object_id, - context.object_instance_id); + /* Check if this is a object read or if it is the correct resource */ + if(ctx->level < 3 || ctx->resource_id == RSC_ID(instance->resource_ids[last_rsc_pos])) { + /* ---------- Discovery operation ------------- */ + /* If this is a discovery all the object, instance, and resource triples should be + generted */ + if(ctx->operation == LWM2M_OP_DISCOVER) { + int dim = 0; + len = snprintf((char *) &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, + (ctx->outbuf->len == 0 && ctx->offset == 0) ? "":",", + instance->object_id, instance->instance_id, + RSC_ID(instance->resource_ids[last_rsc_pos])); + if(instance->resource_dim_callback != NULL && + (dim = instance->resource_dim_callback(instance, + RSC_ID(instance->resource_ids[last_rsc_pos]))) > 0) { + len += snprintf((char *) &ctx->outbuf->buffer[ctx->outbuf->len + len], + ctx->outbuf->size - ctx->outbuf->len - len, ";dim=%d", dim); + } + /* here we have "read" out something */ + num_read++; + ctx->outbuf->len += len; + if(len < 0 || ctx->outbuf->len >= size) { + double_buffer_flush(ctx->outbuf, outbuf, size); - for(i = 0; i < object->count; i++) { - if((object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) == 0) { - /* allocate this instance */ - object->instances[i].flag |= LWM2M_INSTANCE_FLAG_USED; - object->instances[i].id = context.object_instance_id; - context.object_instance_index = i; - PRINTF("Created instance: %d\n", context.object_instance_id); - REST.set_response_status(response, CREATED_2_01); - instance = &object->instances[i]; - break; - } - } + LOG_DBG("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + /* switch buffer */ + ctx->outbuf = outbuf; + ctx->writer_flags |= WRITER_HAS_MORE; + ctx->offset += size; + return LWM2M_STATUS_OK; + } + /* ---------- Read operation ------------- */ + } else if(ctx->operation == LWM2M_OP_READ) { + lwm2m_status_t success; + uint8_t lv; - if(instance == NULL) { - /* could for some reason not create the instance */ - REST.set_response_status(response, NOT_ACCEPTABLE_4_06); - return; - } + lv = ctx->level; - plen = REST.get_request_payload(request, &data); - if(plen == 0) { - /* do nothing more */ - return; - } - PRINTF("Payload: "); - for(i = 0; i < plen; i++) { - PRINTF("%02x", data[i]); - } - PRINTF("\n"); + /* Do not allow a read on a non-readable */ + if(lv == 3 && !RSC_READABLE(instance->resource_ids[last_rsc_pos])) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + /* Set the resource ID is ctx->level < 3 */ + if(lv < 3) { + ctx->resource_id = RSC_ID(instance->resource_ids[last_rsc_pos]); + } + if(lv < 2) { + ctx->object_instance_id = instance->instance_id; + } - pos = 0; - do { - len = oma_tlv_read(&tlv, (uint8_t *)&data[pos], plen - pos); - PRINTF("Found TLV type=%u id=%u len=%lu\n", - tlv.type, tlv.id, (unsigned long)tlv.length); - /* here we need to do callbacks or write value */ - if(tlv.type == OMA_TLV_TYPE_RESOURCE) { - context.resource_id = tlv.id; - const lwm2m_resource_t *rsc = get_resource(instance, &context); - if(rsc != NULL) { - /* write the value to the resource */ - if(lwm2m_object_is_resource_string(rsc)) { - PRINTF(" new string value for /%d/%d/%d = %.*s\n", - context.object_id, context.object_instance_id, - context.resource_id, (int)tlv.length, tlv.value); - lwm2m_object_set_resource_string(rsc, &context, - tlv.length, tlv.value); - } else if(lwm2m_object_is_resource_int(rsc)) { - PRINTF(" new int value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, oma_tlv_get_int32(&tlv)); - lwm2m_object_set_resource_int(rsc, &context, - oma_tlv_get_int32(&tlv)); - } else if(lwm2m_object_is_resource_floatfix(rsc)) { - int32_t value; - if(oma_tlv_float32_to_fix(&tlv, &value, LWM2M_FLOAT32_BITS)) { - PRINTF(" new float value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, value >> LWM2M_FLOAT32_BITS); - lwm2m_object_set_resource_floatfix(rsc, &context, value); - } else { - PRINTF(" new float value for /%d/%d/%d: FAILED\n", - context.object_id, context.object_instance_id, - context.resource_id); + if(RSC_READABLE(instance->resource_ids[last_rsc_pos])) { + ctx->level = 3; + if(!initialized) { + /* Now we need to initialize the object writing for this new object */ + len = ctx->writer->init_write(ctx); + ctx->outbuf->len += len; + LOG_DBG("INIT WRITE len:%d size:%"PRIu16"\n", len, ctx->outbuf->size); + initialized = 1; } - } else if(lwm2m_object_is_resource_boolean(rsc)) { - PRINTF(" new boolean value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, oma_tlv_get_int32(&tlv)); - lwm2m_object_set_resource_boolean(rsc, &context, - oma_tlv_get_int32(&tlv) != 0); + + if(current_opaque_callback == NULL) { + LOG_DBG("Doing the callback to the resource %d\n", ctx->outbuf->len); + /* No special opaque callback to handle - use regular callback */ + success = instance->callback(instance, ctx); + LOG_DBG("After the callback to the resource %d: %s\n", + ctx->outbuf->len, get_status_as_string(success)); + + if(success != LWM2M_STATUS_OK) { + /* What to do here? */ + LOG_DBG("Callback failed: %s\n", get_status_as_string(success)); + if(lv < 3) { + if(success == LWM2M_STATUS_NOT_FOUND) { + /* ok with a not found during a multi read - what more + is ok? */ + } else { + lwm2m_buf_lock[0] = 0; + return success; + } + } else { + lwm2m_buf_lock[0] = 0; + return success; + } + } + } + if(current_opaque_callback != NULL) { + uint32_t old_offset = ctx->offset; + int num_write = COAP_MAX_BLOCK_SIZE - ctx->outbuf->len; + /* Check if the callback did set a opaque callback function - then + we should produce data via that callback until the opaque has fully + been handled */ + ctx->offset = current_opaque_offset; + /* LOG_DBG("Calling the opaque handler %x\n", ctx->writer_flags); */ + success = current_opaque_callback(instance, ctx, num_write); + if((ctx->writer_flags & WRITER_HAS_MORE) == 0) { + /* This opaque stream is now done! */ + /* LOG_DBG("Setting opaque callback to null - it is done!\n"); */ + current_opaque_callback = NULL; + } else if(ctx->outbuf->len < COAP_MAX_BLOCK_SIZE) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_ERROR; + } + current_opaque_offset += num_write; + ctx->offset = old_offset; + /* LOG_DBG("Setting back offset to: %d\n", ctx->offset); */ + } + + /* here we have "read" out something */ + num_read++; + /* We will need to handle no-success and other things */ + LOG_DBG("Called %u/%u/%u outlen:%u %s\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, + ctx->outbuf->len, get_status_as_string(success)); + + /* we need to handle full buffer, etc here also! */ + ctx->level = lv; + } else { + LOG_DBG("Resource %u not readable\n", + RSC_ID(instance->resource_ids[last_rsc_pos])); } } } - pos = pos + len; - } while(len > 0 && pos < plen); + if(current_opaque_callback == NULL) { + /* This resource is now done - (only when the opaque is also done) */ + last_rsc_pos++; + } else { + LOG_DBG("Opaque is set - continue with that.\n"); + } + + if(ctx->outbuf->len >= COAP_MAX_BLOCK_SIZE) { + LOG_DBG("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + /* If the produced data is larger than a CoAP block we need to send + this now */ + if(ctx->outbuf->len < 2 * COAP_MAX_BLOCK_SIZE) { + /* We assume that size is equal to COAP_MAX_BLOCK_SIZE here */ + double_buffer_flush(ctx->outbuf, outbuf, size); + + LOG_DBG("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + /* switch buffer */ + ctx->outbuf = outbuf; + ctx->writer_flags |= WRITER_HAS_MORE; + ctx->offset += size; + /* OK - everything went well... but we have more. - keep the lock here! */ + return LWM2M_STATUS_OK; + } else { + LOG_WARN("*** ERROR Overflow?\n"); + return LWM2M_STATUS_ERROR; + } + } + } } - return; + instance = next_object_instance(ctx, object, instance); + if(instance != NULL) { + last_instance_id = + ((uint32_t)instance->object_id << 16) | instance->instance_id; + } else { + last_instance_id = NO_INSTANCE; + } + if(ctx->operation == LWM2M_OP_READ) { + LOG_DBG("END Writer %d ->", ctx->outbuf->len); + len = ctx->writer->end_write(ctx); + ctx->outbuf->len += len; + LOG_DBG("%d\n", ctx->outbuf->len); + } + + initialized = 0; + last_rsc_pos = 0; } - if(depth == 3) { - const lwm2m_resource_t *resource = get_resource(instance, &context); - size_t content_len = 0; - if(resource == NULL) { - PRINTF("Error - do not have resource %d\n", context.resource_id); - REST.set_response_status(response, NOT_FOUND_4_04); - return; - } - /* HANDLE PUT */ - if(method == METHOD_PUT) { - if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.write != NULL) { - /* pick a reader ??? */ - if(format == LWM2M_TEXT_PLAIN) { - /* a string */ - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - context.reader = &lwm2m_plain_text_reader; - PRINTF("PUT Callback with data: '%.*s'\n", plen, data); - /* no specific reader for plain text */ - content_len = resource->value.callback.write(&context, data, plen, - buffer, preferred_size); - PRINTF("content_len:%u\n", (unsigned int)content_len); - REST.set_response_status(response, CHANGED_2_04); - } else { - PRINTF("PUT callback with format %d\n", format); - REST.set_response_status(response, NOT_ACCEPTABLE_4_06); - } - } else { - PRINTF("PUT - no write callback\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } else { - PRINTF("PUT on non-callback resource!\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); + /* did not read anything even if we should have - on single item */ + if(num_read == 0 && ctx->level == 3) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_NOT_FOUND; + } + + /* seems like we are done! - flush buffer */ + len = double_buffer_flush(ctx->outbuf, outbuf, size); + ctx->outbuf = outbuf; + ctx->offset += len; + + /* If there is still data in the double-buffer - indicate that so that we get another + callback */ + if(lwm2m_buf.len > 0) { + ctx->writer_flags |= WRITER_HAS_MORE; + } else { + /* OK - everything went well we are done, unlock and return */ + lwm2m_buf_lock[0] = 0; + } + + LOG_DBG("At END: Copied lwm2m buf %d\n", len); + + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(lwm2m_context_t *context, lwm2m_object_t *object) +{ + lwm2m_object_instance_t *instance; + if(object == NULL || object->impl == NULL || + object->impl->create_instance == NULL) { + return NULL; + } + + /* NOTE: context->object_instance_id needs to be set before calling */ + instance = object->impl->create_instance(context->object_instance_id, NULL); + if(instance != NULL) { + LOG_DBG("Created instance: %u/%u\n", context->object_id, context->object_instance_id); + coap_set_status_code(context->response, CREATED_2_01); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + } + return instance; +} +/*---------------------------------------------------------------------------*/ +#define MODE_NONE 0 +#define MODE_INSTANCE 1 +#define MODE_VALUE 2 +#define MODE_READY 3 + +static lwm2m_object_instance_t * +get_or_create_instance(lwm2m_context_t *ctx, lwm2m_object_t *object, + uint16_t *c) +{ + lwm2m_object_instance_t *instance; + + instance = get_instance_by_context(ctx, NULL); + LOG_DBG("Instance: %u/%u/%u = %p\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id, instance); + /* by default we assume that the instance is not created... so we set flag to zero */ + if(c != NULL) { + *c = LWM2M_OBJECT_INSTANCE_NONE; + } + if(instance == NULL) { + instance = create_instance(ctx, object); + if(instance != NULL) { + if(c != NULL) { + *c = instance->instance_id; } - /* HANDLE GET */ - } else if(method == METHOD_GET) { - if(lwm2m_object_is_resource_string(resource)) { - const uint8_t *value; - value = lwm2m_object_get_resource_string(resource, &context); - if(value != NULL) { - uint16_t len = lwm2m_object_get_resource_strlen(resource, &context); - PRINTF("Get string value: %.*s\n", (int)len, (char *)value); - content_len = context.writer->write_string(&context, buffer, - preferred_size, (const char *)value, len); - } - } else if(lwm2m_object_is_resource_int(resource)) { - int32_t value; - if(lwm2m_object_get_resource_int(resource, &context, &value)) { - content_len = context.writer->write_int(&context, buffer, preferred_size, value); - } - } else if(lwm2m_object_is_resource_floatfix(resource)) { - int32_t value; - if(lwm2m_object_get_resource_floatfix(resource, &context, &value)) { - /* export FLOATFIX */ - PRINTF("Exporting %d-bit fix as float: %" PRId32 "\n", - LWM2M_FLOAT32_BITS, value); - content_len = context.writer->write_float32fix(&context, buffer, - preferred_size, value, LWM2M_FLOAT32_BITS); - } - } else if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.read != NULL) { - content_len = resource->value.callback.read(&context, - buffer, preferred_size); - } else { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - return; - } - } - if(content_len > 0) { - REST.set_response_payload(response, buffer, content_len); - REST.set_header_content_type(response, content_type); - } else { - /* failed to produce output - it is an internal error */ - REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00); - } - /* Handle POST */ - } else if(method == METHOD_POST) { - if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.exec != NULL) { - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - PRINTF("Execute Callback with data: '%.*s'\n", plen, data); - content_len = resource->value.callback.exec(&context, - data, plen, - buffer, preferred_size); - REST.set_response_status(response, CHANGED_2_04); - } else { - PRINTF("Execute callback - no exec callback\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } else { - PRINTF("Resource post but no callback resource\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } - } else if(depth == 2) { - /* produce an instance response */ - if(method != METHOD_GET) { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } else if(instance == NULL) { - REST.set_response_status(response, NOT_FOUND_4_04); - } else { - int rdlen; - if(accept == APPLICATION_LINK_FORMAT) { - rdlen = write_rd_link_data(object, instance, - (char *)buffer, preferred_size); - } else { - rdlen = write_rd_json_data(&context, object, instance, - (char *)buffer, preferred_size); - } - if(rdlen < 0) { - PRINTF("Failed to generate instance response\n"); - REST.set_response_status(response, SERVICE_UNAVAILABLE_5_03); - return; - } - REST.set_response_payload(response, buffer, rdlen); - if(accept == APPLICATION_LINK_FORMAT) { - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); - } else { - REST.set_header_content_type(response, LWM2M_JSON); - } - } - } else if(depth == 1) { - /* produce a list of instances */ - if(method != METHOD_GET) { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } else { - int rdlen; - PRINTF("Sending instance list for object %u\n", object->id); - /* TODO: if(accept == APPLICATION_LINK_FORMAT) { */ - rdlen = write_object_instances_link(object, (char *)buffer, preferred_size); - if(rdlen < 0) { - PRINTF("Failed to generate object response\n"); - REST.set_response_status(response, SERVICE_UNAVAILABLE_5_03); - return; - } - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); - REST.set_response_payload(response, buffer, rdlen); + created.instance_id = instance->instance_id; + created.object_id = instance->object_id; + created.token_len = MIN(COAP_TOKEN_LEN, ctx->request->token_len); + memcpy(&created.token, ctx->request->token, created.token_len); } } + return instance; +} +/*---------------------------------------------------------------------------*/ +static int +check_write(lwm2m_context_t *ctx, lwm2m_object_instance_t *instance, int rid) +{ + int i; + if(instance->resource_ids != NULL && instance->resource_count > 0) { + int count = instance->resource_count; + for(i = 0; i < count; i++) { + if(RSC_ID(instance->resource_ids[i]) == rid) { + if(RSC_WRITABLE(instance->resource_ids[i])) { + /* yes - writable */ + return 1; + } + if(RSC_UNSPECIFIED(instance->resource_ids[i]) && + created.instance_id == instance->instance_id && + created.object_id == instance->object_id && + created.token_len == ctx->request->token_len && + memcmp(&created.token, ctx->request->token, + created.token_len) == 0) { + /* yes - writeable at create - never otherwise - sec / srv */ + return 1; + } + break; + } + } + } + /* Resource did not exist... - Ignore to avoid problems. */ + if(created.instance_id == instance->instance_id && + created.object_id == instance->object_id && + created.token_len == ctx->request->token_len && + memcmp(&created.token, ctx->request->token, + created.token_len) == 0) { + LOG_DBG("Ignoring resource %u/%u/%d in newly created instance\n", + created.object_id, created.instance_id, rid); + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +process_tlv_write(lwm2m_context_t *ctx, lwm2m_object_t *object, + int rid, uint8_t *data, int len) +{ + lwm2m_object_instance_t *instance; + uint16_t created = LWM2M_OBJECT_INSTANCE_NONE; + ctx->inbuf->buffer = data; + ctx->inbuf->pos = 0; + ctx->inbuf->size = len; + ctx->level = 3; + ctx->resource_id = rid; + LOG_DBG(" Doing callback to %u/%u/%u\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id); + instance = get_or_create_instance(ctx, object, &created); + if(instance != NULL && instance->callback != NULL) { + if(check_write(ctx, instance, rid)) { + return instance->callback(instance, ctx); + } else { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + } + return LWM2M_STATUS_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int last_tlv_id = 0; + +static lwm2m_status_t +perform_multi_resource_write_op(lwm2m_object_t *object, + lwm2m_object_instance_t *instance, + lwm2m_context_t *ctx, int format) +{ + /* Only for JSON and TLV formats */ + uint16_t oid = 0, iid = 0, rid = 0; + uint8_t olv = 0; + uint8_t mode = 0; + uint8_t *inbuf; + int inpos; + size_t insize; + int i; + uint16_t created = LWM2M_OBJECT_INSTANCE_NONE; + + olv = ctx->level; + inbuf = ctx->inbuf->buffer; + inpos = ctx->inbuf->pos; + insize = ctx->inbuf->size; + + if(format == LWM2M_JSON || format == LWM2M_OLD_JSON) { + struct json_data json; + + while(lwm2m_json_next_token(ctx, &json)) { + LOG_DBG("JSON: '"); + for(i = 0; i < json.name_len; i++) { + LOG_DBG_("%c", json.name[i]); + } + LOG_DBG_("':'"); + for(i = 0; i < json.value_len; i++) { + LOG_DBG_("%c", json.value[i]); + } + LOG_DBG_("'\n"); + + if(json.name[0] == 'n') { + i = parse_path((const char *) json.value, json.value_len, &oid, &iid, &rid); + if(i > 0) { + if(ctx->level == 1) { + ctx->level = 3; + ctx->object_instance_id = oid; + ctx->resource_id = iid; + + instance = get_or_create_instance(ctx, object, &created); + } + if(instance != NULL && instance->callback != NULL) { + mode |= MODE_INSTANCE; + } else { + /* Failure... */ + return LWM2M_STATUS_ERROR; + } + } + } else { + /* HACK - assume value node - can it be anything else? */ + mode |= MODE_VALUE; + /* update values */ + inbuf = ctx->inbuf->buffer; + inpos = ctx->inbuf->pos; + + ctx->inbuf->buffer = json.value; + ctx->inbuf->pos = 0; + ctx->inbuf->size = json.value_len; + } + + if(mode == MODE_READY) { + /* allow write if just created - otherwise not */ + if(!check_write(ctx, instance, ctx->resource_id)) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + if(instance->callback(instance, ctx) != LWM2M_STATUS_OK) { + /* TODO what to do here */ + } + mode = MODE_NONE; + ctx->inbuf->buffer = inbuf; + ctx->inbuf->pos = inpos; + ctx->inbuf->size = insize; + ctx->level = olv; + } + } + } else if(format == LWM2M_TLV || format == LWM2M_OLD_TLV) { + size_t len; + lwm2m_tlv_t tlv; + int tlvpos = 0; + lwm2m_status_t status; + + /* For handling blockwise (BLOCK1) write */ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + /* NOTE: this assumes that a BLOCK1 non-first block is not a part of a + small TLV but rather a large opaque - this needs to be fixed in the + future */ + + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + LOG_DBG("CoAP BLOCK1: %"PRIu32"/%d/%d offset:%"PRIu32 + " LWM2M CTX->offset=%"PRIu32"\n", + num, more, size, offset, ctx->offset); + LOG_DBG("Last TLV ID:%d final:%d\n", last_tlv_id, + lwm2m_object_is_final_incoming(ctx)); + if(offset > 0) { + status = process_tlv_write(ctx, object, last_tlv_id, + inbuf, size); + return status; + } + } + + while(tlvpos < insize) { + len = lwm2m_tlv_read(&tlv, &inbuf[tlvpos], insize - tlvpos); + LOG_DBG("Got TLV format First is: type:%d id:%d len:%d (p:%d len:%d/%d)\n", + tlv.type, tlv.id, (int) tlv.length, + (int) tlvpos, (int) len, (int) insize); + if(tlv.type == LWM2M_TLV_TYPE_OBJECT_INSTANCE) { + lwm2m_tlv_t tlv2; + int len2; + int pos = 0; + ctx->object_instance_id = tlv.id; + if(tlv.length == 0) { + /* Create only - no data */ + if((instance = create_instance(ctx, object)) == NULL) { + return LWM2M_STATUS_ERROR; + } + } + while(pos < tlv.length && (len2 = lwm2m_tlv_read(&tlv2, &tlv.value[pos], + tlv.length - pos))) { + LOG_DBG(" TLV type:%d id:%d len:%d (len:%d/%d)\n", + tlv2.type, tlv2.id, (int)tlv2.length, + (int)len2, (int)insize); + if(tlv2.type == LWM2M_TLV_TYPE_RESOURCE) { + last_tlv_id = tlv2.id; + status = process_tlv_write(ctx, object, tlv2.id, + (uint8_t *)&tlv.value[pos], len2); + if(status != LWM2M_STATUS_OK) { + return status; + } + } + pos += len2; + } + } else if(tlv.type == LWM2M_TLV_TYPE_RESOURCE) { + status = process_tlv_write(ctx, object, tlv.id, &inbuf[tlvpos], len); + if(status != LWM2M_STATUS_OK) { + return status; + } + coap_set_status_code(ctx->response, CHANGED_2_04); + } + tlvpos += len; + } + } else if(format == LWM2M_TEXT_PLAIN || + format == TEXT_PLAIN || + format == LWM2M_OLD_OPAQUE) { + return call_instance(instance, ctx); + + } else { + /* Unsupported format */ + return LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT; + } + + /* Here we have a success! */ + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +lwm2m_object_instance_t * +lwm2m_engine_get_instance_buffer(void) +{ + return &instance_buffer; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_has_instance(uint16_t object_id, uint16_t instance_id) +{ + return get_instance(object_id, instance_id, NULL) != NULL; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_add_object(lwm2m_object_instance_t *object) +{ + lwm2m_object_instance_t *instance; + uint16_t min_id = 0xffff; + uint16_t max_id = 0; + int found = 0; + + if(object == NULL || object->callback == NULL) { + /* Insufficient object configuration */ + LOG_DBG("failed to register NULL object\n"); + return 0; + } + if(get_object(object->object_id) != NULL) { + /* A generic object with this id has already been registered */ + LOG_DBG("object with id %u already registered\n", object->object_id); + return 0; + } + + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(object->object_id == instance->object_id) { + if(object->instance_id == instance->instance_id) { + LOG_DBG("object with id %u/%u already registered\n", + instance->object_id, instance->instance_id); + return 0; + } + + found++; + if(instance->instance_id > max_id) { + max_id = instance->instance_id; + } + if(instance->instance_id < min_id) { + min_id = instance->instance_id; + } + } + } + + if(object->instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* No instance id has been assigned yet */ + if(found == 0) { + /* First object with this id */ + object->instance_id = 0; + } else if(min_id > 0) { + object->instance_id = min_id - 1; + } else { + object->instance_id = max_id + 1; + } + } + list_add(object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + return 1; } /*---------------------------------------------------------------------------*/ void -lwm2m_engine_delete_handler(const lwm2m_object_t *object, void *request, - void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +lwm2m_engine_remove_object(lwm2m_object_instance_t *object) +{ + list_remove(object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_add_generic_object(lwm2m_object_t *object) +{ + if(object == NULL || object->impl == NULL + || object->impl->get_first == NULL + || object->impl->get_next == NULL + || object->impl->get_by_id == NULL) { + LOG_WARN("failed to register NULL object\n"); + return 0; + } + if(get_object(object->impl->object_id) != NULL) { + /* A generic object with this id has already been registered */ + LOG_WARN("object with id %u already registered\n", + object->impl->object_id); + return 0; + } + if(has_non_generic_object(object->impl->object_id)) { + /* An object with this id has already been registered */ + LOG_WARN("object with id %u already registered\n", + object->impl->object_id); + return 0; + } + list_add(generic_object_list, object); + +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + + return 1; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_engine_remove_generic_object(lwm2m_object_t *object) +{ + list_remove(generic_object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, + lwm2m_object_instance_t *last) +{ + if(context != NULL && context->level >= 2) { + /* Only single instance */ + return NULL; + } + + /* There has to be a last to get a next */ + if(last == NULL) { + return NULL; + } + + if(object == NULL) { + for(last = last->next; last != NULL; last = last->next) { + /* if no context is given - this will just give the next object */ + if(context == NULL || last->object_id == context->object_id) { + return last; + } + } + return NULL; + } + return object->impl->get_next(last, NULL); +} +/*---------------------------------------------------------------------------*/ +static coap_handler_status_t +lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { - int len; const char *url; + int url_len; + unsigned int format; + unsigned int accept; + int depth; lwm2m_context_t context; + lwm2m_object_t *object; + lwm2m_object_instance_t *instance; + uint32_t bnum; + uint8_t bmore; + uint16_t bsize; + uint32_t boffset; + lwm2m_status_t success; + lwm2m_buffer_t inbuf; + lwm2m_buffer_t outbuf; - len = REST.get_url(request, &url); - PRINTF("*** DELETE URI:'%.*s' called... - responding with DELETED.\n", - len, url); - len = lwm2m_engine_parse_context(object, url, len, &context); - PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, - context.object_instance_id, context.resource_id, len); + /* Initialize the context */ + memset(&context, 0, sizeof(context)); + memset(&outbuf, 0, sizeof(outbuf)); + memset(&inbuf, 0, sizeof(inbuf)); - REST.set_response_status(response, DELETED_2_02); + context.outbuf = &outbuf; + context.inbuf = &inbuf; + + /* Set CoAP request/response for now */ + context.request = request; + context.response = response; + + /* Set out buffer */ + context.outbuf->buffer = buffer; + context.outbuf->size = buffer_size; + + /* Set input buffer */ + if(offset != NULL) { + context.offset = *offset; + } + context.inbuf->size = coap_get_payload(request, (const uint8_t **)&context.inbuf->buffer); + context.inbuf->pos = 0; + + /* 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 +#if LWM2M_CONF_ENTITY_TOO_LARGE_BLOCK1 + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + uint16_t bsize; + coap_get_header_block1(request, NULL, NULL, &bsize, NULL); + + LOG_DBG("Block1 size:%d\n", bsize); + if(bsize > COAP_MAX_BLOCK_SIZE) { + LOG_WARN("Entity too large: %u...\n", bsize); + coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13); + coap_set_header_size1(response, COAP_MAX_BLOCK_SIZE); + return COAP_HANDLER_STATUS_PROCESSED; + } + } +#endif + + /* Set default reader/writer */ + context.reader = &lwm2m_plain_text_reader; + context.writer = &lwm2m_tlv_writer; + + + url_len = coap_get_header_uri_path(request, &url); + + if(url_len == 2 && strncmp("bs", url, 2) == 0) { + LOG_INFO("BOOTSTRAPPED!!!\n"); + coap_set_status_code(response, CHANGED_2_04); + return COAP_HANDLER_STATUS_PROCESSED; + } + + depth = lwm2m_engine_parse_context(url, url_len, request, response, + buffer, buffer_size, &context); + if(depth < 0) { + /* Not a LWM2M context */ + return COAP_HANDLER_STATUS_CONTINUE; + } + + LOG_DBG("%s URL:'", get_method_as_string(coap_get_method_type(request))); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("' CTX:%u/%u/%u dp:%u bs:%d\n", context.object_id, context.object_instance_id, + context.resource_id, depth, buffer_size); + /* Get format and accept */ + if(!coap_get_header_content_format(request, &format)) { + LOG_DBG("No format given. Assume text plain...\n"); + format = TEXT_PLAIN; + } else if(format == LWM2M_TEXT_PLAIN) { + /* CoAP content format text plain - assume LWM2M text plain */ + format = TEXT_PLAIN; + } + if(!coap_get_header_accept(request, &accept)) { + if(format == TEXT_PLAIN && depth < 3) { + LOG_DBG("No Accept header, assume JSON\n"); + accept = LWM2M_JSON; + } else { + LOG_DBG("No Accept header, using same as content-format: %d\n", format); + accept = format; + } + } + + /* + * 1 => Object only + * 2 => Object and Instance + * 3 => Object and Instance and Resource + */ + if(depth < 1) { + /* No possible object id found in URL - ignore request unless delete all */ + if(coap_get_method_type(request) == METHOD_DELETE) { + LOG_DBG("This is a delete all - for bootstrap...\n"); + context.operation = LWM2M_OP_DELETE; + coap_set_status_code(response, DELETED_2_02); + + /* Delete all dynamic objects that can be deleted */ + for(object = list_head(generic_object_list); + object != NULL; + object = object->next) { + if(object->impl != NULL && object->impl->delete_instance != NULL) { + object->impl->delete_instance(LWM2M_OBJECT_INSTANCE_NONE, NULL); + } + } +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + return COAP_HANDLER_STATUS_PROCESSED; + } + return COAP_HANDLER_STATUS_CONTINUE; + } + + instance = get_instance_by_context(&context, &object); + + /* + * Check if we found either instance or object. Instance means we found an + * existing instance and generic objects means we might create an instance. + */ + if(instance == NULL && object == NULL) { + /* No matching object/instance found - ignore request */ + return COAP_HANDLER_STATUS_CONTINUE; + } + + LOG_INFO("Context: %u/%u/%u found: %d\n", + context.object_id, context.object_instance_id, + context.resource_id, depth); + + /* + * Select reader and writer based on provided Content type and + * Accept headers. + */ + lwm2m_engine_select_reader(&context, format); + lwm2m_engine_select_writer(&context, accept); + + switch(coap_get_method_type(request)) { + case METHOD_PUT: + /* can also be write atts */ + context.operation = LWM2M_OP_WRITE; + coap_set_status_code(response, CHANGED_2_04); + break; + case METHOD_POST: + if(context.level < 2) { + /* write to a instance */ + context.operation = LWM2M_OP_WRITE; + coap_set_status_code(response, CHANGED_2_04); + } else if(context.level == 3) { + context.operation = LWM2M_OP_EXECUTE; + coap_set_status_code(response, CHANGED_2_04); + } + break; + case METHOD_GET: + if(accept == APPLICATION_LINK_FORMAT) { + context.operation = LWM2M_OP_DISCOVER; + } else { + context.operation = LWM2M_OP_READ; + } + coap_set_status_code(response, CONTENT_2_05); + break; + case METHOD_DELETE: + context.operation = LWM2M_OP_DELETE; + coap_set_status_code(response, DELETED_2_02); + break; + default: + break; + } + + if(LOG_DBG_ENABLED) { + /* for debugging */ + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] %s Format:%d ID:%d bsize:%u offset:%"PRId32"\n", + get_method_as_string(coap_get_method_type(request)), + format, context.object_id, buffer_size, + offset != NULL ? *offset : 0); + if(format == TEXT_PLAIN) { + /* a string */ + const uint8_t *data; + int plen = coap_get_payload(request, &data); + if(plen > 0) { + LOG_DBG("Data: '"); + LOG_DBG_COAP_STRING((const char *)data, plen); + LOG_DBG_("'\n"); + } + } + } + + /* PUT/POST - e.g. write will not send in offset here - Maybe in the future? */ + if((offset != NULL && *offset == 0) && + coap_is_option(request, COAP_OPTION_BLOCK1)) { + coap_get_header_block1(request, &bnum, &bmore, &bsize, &boffset); + context.offset = boffset; + } + + /* This is a discovery operation */ + switch(context.operation) { + case LWM2M_OP_DISCOVER: + /* Assume only one disco at a time... */ + success = perform_multi_resource_read_op(object, instance, &context); + break; + case LWM2M_OP_READ: + success = perform_multi_resource_read_op(object, instance, &context); + break; + case LWM2M_OP_WRITE: + success = perform_multi_resource_write_op(object, instance, &context, format); + break; + case LWM2M_OP_EXECUTE: + success = call_instance(instance, &context); + break; + case LWM2M_OP_DELETE: + if(object != NULL && object->impl != NULL && + object->impl->delete_instance != NULL) { + object->impl->delete_instance(context.object_instance_id, &success); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + } else { + success = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + break; + default: + success = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + break; + } + + if(success == LWM2M_STATUS_OK) { + /* Handle blockwise 1 */ + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + LOG_DBG("Setting BLOCK 1 num:%"PRIu32" o2:%"PRIu32" o:%"PRId32"\n", bnum, boffset, + (offset != NULL ? *offset : 0)); + coap_set_header_block1(response, bnum, 0, bsize); + } + + if(context.outbuf->len > 0) { + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] replying with %u bytes\n", context.outbuf->len); + coap_set_payload(response, context.outbuf->buffer, context.outbuf->len); + coap_set_header_content_format(response, context.content_type); + + if(offset != NULL) { + LOG_DBG("Setting new offset: oo %"PRIu32 + ", no: %"PRIu32"\n", *offset, context.offset); + if(context.writer_flags & WRITER_HAS_MORE) { + *offset = context.offset; + } else { + /* this signals to CoAP that there is no more CoAP messages to expect */ + *offset = -1; + } + } + } else { + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] no data in reply\n"); + } + } else { + switch(success) { + case LWM2M_STATUS_FORBIDDEN: + coap_set_status_code(response, FORBIDDEN_4_03); + break; + case LWM2M_STATUS_NOT_FOUND: + coap_set_status_code(response, NOT_FOUND_4_04); + break; + case LWM2M_STATUS_OPERATION_NOT_ALLOWED: + coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05); + break; + case LWM2M_STATUS_NOT_ACCEPTABLE: + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + break; + case LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT: + coap_set_status_code(response, UNSUPPORTED_MEDIA_TYPE_4_15); + break; + default: + /* Failed to handle the request */ + coap_set_status_code(response, INTERNAL_SERVER_ERROR_5_00); + break; + } + LOG_WARN("["); + LOG_WARN_COAP_STRING(url, url_len); + LOG_WARN("] resource failed: %s\n", get_status_as_string(success)); + } + return COAP_HANDLER_STATUS_PROCESSED; +} +/*---------------------------------------------------------------------------*/ +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); + } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-engine.h b/os/services/lwm2m/lwm2m-engine.h index 5512a326d..62a667e99 100644 --- a/os/services/lwm2m/lwm2m-engine.h +++ b/os/services/lwm2m/lwm2m-engine.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -52,31 +52,68 @@ /* LWM2M / CoAP Content-Formats */ typedef enum { LWM2M_TEXT_PLAIN = 1541, - LWM2M_TLV = 1542, - LWM2M_JSON = 1543, - LWM2M_OPAQUE = 1544 + LWM2M_TLV = 11542, + LWM2M_JSON = 11543, + LWM2M_OLD_TLV = 1542, + LWM2M_OLD_JSON = 1543, + LWM2M_OLD_OPAQUE = 1544 } lwm2m_content_format_t; void lwm2m_engine_init(void); -void lwm2m_engine_register_default_objects(void); -void lwm2m_engine_use_bootstrap_server(int use); -void lwm2m_engine_use_registration_server(int use); -void lwm2m_engine_register_with_server(const uip_ipaddr_t *server, uint16_t port); -void lwm2m_engine_register_with_bootstrap_server(const uip_ipaddr_t *server, uint16_t port); -const lwm2m_object_t *lwm2m_engine_get_object(uint16_t id); +int lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block); -int lwm2m_engine_register_object(const lwm2m_object_t *object); +typedef lwm2m_status_t +(* lwm2m_object_instance_callback_t)(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); +typedef int +(* lwm2m_resource_dim_callback_t)(lwm2m_object_instance_t *object, + uint16_t resource_id); -void lwm2m_engine_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); +#define LWM2M_OBJECT_INSTANCE_NONE 0xffff + +struct lwm2m_object_instance { + lwm2m_object_instance_t *next; + uint16_t object_id; + uint16_t instance_id; + /* an array of resource IDs for discovery, etc */ + const lwm2m_resource_id_t *resource_ids; + uint16_t resource_count; + /* the callback for requests */ + lwm2m_object_instance_callback_t callback; + lwm2m_resource_dim_callback_t resource_dim_callback; +}; + +typedef struct { + uint16_t object_id; + lwm2m_object_instance_t *(* create_instance)(uint16_t instance_id, + lwm2m_status_t *status); + int (* delete_instance)(uint16_t instance_id, lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_first)(lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_next)(lwm2m_object_instance_t *instance, + lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_by_id)(uint16_t instance_id, + lwm2m_status_t *status); +} lwm2m_object_impl_t; + +typedef struct lwm2m_object lwm2m_object_t; +struct lwm2m_object { + lwm2m_object_t *next; + const lwm2m_object_impl_t *impl; +}; + +lwm2m_object_instance_t *lwm2m_engine_get_instance_buffer(void); + +int lwm2m_engine_has_instance(uint16_t object_id, uint16_t instance_id); +int lwm2m_engine_add_object(lwm2m_object_instance_t *object); +void lwm2m_engine_remove_object(lwm2m_object_instance_t *object); +int lwm2m_engine_add_generic_object(lwm2m_object_t *object); +void lwm2m_engine_remove_generic_object(lwm2m_object_t *object); +void lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, + uint16_t resource); + +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); -void lwm2m_engine_delete_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); #endif /* LWM2M_ENGINE_H */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-firmware.c b/os/services/lwm2m/lwm2m-firmware.c new file mode 100644 index 000000000..e89c3dab4 --- /dev/null +++ b/os/services/lwm2m/lwm2m-firmware.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT 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 + * @{ + * + * Code for firmware object of lwm2m + * + */ + +#include "lwm2m-engine.h" +#include "lwm2m-firmware.h" +#include "coap.h" +#include +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-firmware" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#define UPDATE_PACKAGE 0 +#define UPDATE_PACKAGE_URI 1 +#define UPDATE_UPDATE 2 +#define UPDATE_STATE 3 +#define UPDATE_RESULT 5 + +#define STATE_IDLE 1 +#define STATE_DOWNLOADING 2 +#define STATE_DOWNLOADED 3 + +#define RESULT_DEFAULT 0 +#define RESULT_SUCCESS 1 +#define RESULT_NO_STORAGE 2 +#define RESULT_OUT_OF_MEM 3 +#define RESULT_CONNECTION_LOST 4 +#define RESULT_CRC_FAILED 5 +#define RESULT_UNSUPPORTED_FW 6 +#define RESULT_INVALID_URI 7 + + +static uint8_t state = STATE_IDLE; +static uint8_t result = RESULT_DEFAULT; + +static lwm2m_object_instance_t reg_object; + +static const lwm2m_resource_id_t resources[] = + { WO(UPDATE_PACKAGE), + WO(UPDATE_PACKAGE_URI), + RO(UPDATE_STATE), + RO(UPDATE_RESULT), + EX(UPDATE_UPDATE) + }; + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + LOG_DBG("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id, ctx->level); + + if(ctx->level == 1 || ctx->level == 2) { + /* Should not happen - as it will be taken care of by the lwm2m engine itself. */ + return LWM2M_STATUS_ERROR; + } + + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case UPDATE_STATE: + lwm2m_object_write_int(ctx, state); /* 1 means idle */ + return LWM2M_STATUS_OK; + case UPDATE_RESULT: + lwm2m_object_write_int(ctx, result); /* 0 means default */ + return LWM2M_STATUS_OK; + } + } else if(ctx->operation == LWM2M_OP_WRITE) { + + if(LOG_DBG_ENABLED) { + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + LOG_DBG("CoAP BLOCK1: %"PRIu32"/%u/%u offset:%"PRIu32 + " LWM2M CTX->offset=%"PRIu32"\n", + num, more, size, offset, ctx->offset); + } + } + + switch(ctx->resource_id) { + case UPDATE_PACKAGE: + /* The firmware is written */ + LOG_DBG("Firmware received: %"PRIu32" %d fin:%d\n", ctx->offset, + (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); + if(lwm2m_object_is_final_incoming(ctx)) { + state = STATE_DOWNLOADED; + } else { + state = STATE_DOWNLOADING; + } + return LWM2M_STATUS_OK; + case UPDATE_PACKAGE_URI: + /* The firmware URI is written */ + LOG_DBG("Firmware URI received: %"PRIu32" %d fin:%d\n", ctx->offset, + (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); + if(LOG_DBG_ENABLED) { + int i; + LOG_DBG("Data: '"); + for(i = 0; i < ctx->inbuf->size; i++) { + LOG_DBG_("%c", ctx->inbuf->buffer[i]); + } + LOG_DBG_("'\n"); + } + return LWM2M_STATUS_OK; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE && ctx->resource_id == UPDATE_UPDATE) { + /* Perform the update operation */ + if(state == STATE_DOWNLOADED) { + return LWM2M_STATUS_OK; + } + /* Failure... */ + } + return LWM2M_STATUS_ERROR; +} + +/*---------------------------------------------------------------------------*/ +void +lwm2m_firmware_init(void) +{ + reg_object.object_id = 5; + reg_object.instance_id = 0; + reg_object.callback = lwm2m_callback; + reg_object.resource_ids = resources; + reg_object.resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t); + + lwm2m_engine_add_object(®_object); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-firmware.h b/os/services/lwm2m/lwm2m-firmware.h new file mode 100644 index 000000000..2b83922cd --- /dev/null +++ b/os/services/lwm2m/lwm2m-firmware.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT 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 + * @{ + * + * Code for firmware object of lwm2m + * + */ + +#ifndef LWM2M_FIRMWARE_H_ +#define LWM2M_FIRMWARE_H_ + +void lwm2m_firmware_init(void); + +#endif /* LWM2M_FIRMWARE_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-json.c b/os/services/lwm2m/lwm2m-json.c index 8924ceb8c..8ad8be9c4 100644 --- a/os/services/lwm2m/lwm2m-json.c +++ b/os/services/lwm2m/lwm2m-json.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -38,6 +38,7 @@ * Implementation of the Contiki OMA LWM2M JSON writer * \author * Joakim NohlgÃ¥rd + * Joakim Eriksson added JSON reader parts */ #include "lwm2m-object.h" @@ -48,43 +49,201 @@ #include #include -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-json" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ +/* {"e":[{"n":"111/1","v":123},{"n":"111/2","v":42}]} */ + +/* Begin String */ +#define T_NONE 0 +#define T_STRING_B 1 +#define T_STRING 2 +#define T_NAME 4 +#define T_VNUM 5 +#define T_OBJ 6 +#define T_VAL 7 + +/* Simlified JSON style reader for reading in values from a LWM2M JSON + string */ +int +lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json) +{ + int pos = ctx->inbuf->pos; + uint8_t type = T_NONE; + uint8_t vpos_start = 0; + uint8_t vpos_end = 0; + uint8_t cont; + uint8_t wscount = 0; + + json->name_len = 0; + json->value_len = 0; + + cont = 1; + /* We will be either at start, or at a specific position */ + while(pos < ctx->inbuf->size && cont) { + uint8_t c = ctx->inbuf->buffer[pos++]; + switch(c) { + case '{': type = T_OBJ; break; + case '}': + case ',': + if(type == T_VAL || type == T_STRING) { + json->value = &ctx->inbuf->buffer[vpos_start]; + json->value_len = vpos_end - vpos_start - wscount; + type = T_NONE; + cont = 0; + } + wscount = 0; + break; + case '\\': + /* stuffing */ + if(pos < ctx->inbuf->size) { + pos++; + vpos_end = pos; + } + break; + case '"': + if(type == T_STRING_B) { + type = T_STRING; + vpos_end = pos - 1; + wscount = 0; + } else { + type = T_STRING_B; + vpos_start = pos; + } + break; + case ':': + if(type == T_STRING) { + json->name = &ctx->inbuf->buffer[vpos_start]; + json->name_len = vpos_end - vpos_start; + vpos_start = vpos_end = pos; + type = T_VAL; + } else { + /* Could be in string or at illegal pos */ + if(type != T_STRING_B) { + LOG_DBG("ERROR - illegal ':'\n"); + } + } + break; + /* ignore whitespace */ + case ' ': + case '\n': + case '\t': + if(type != T_STRING_B) { + if(vpos_start == pos - 1) { + vpos_start = pos; + } else { + wscount++; + } + } + default: + vpos_end = pos; + } + } + + if(cont == 0 && pos < ctx->inbuf->size) { + ctx->inbuf->pos = pos; + } + /* OK if cont == 0 othewise we failed */ + return cont == 0 && pos < ctx->inbuf->size; +} /*---------------------------------------------------------------------------*/ static size_t -write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +init_write(lwm2m_context_t *ctx) +{ + int len = snprintf((char *)&ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, "{\"bn\":\"/%u/%u/\",\"e\":[", + ctx->object_id, ctx->object_instance_id); + ctx->writer_flags = 0; /* set flags to zero */ + if((len < 0) || (len >= ctx->outbuf->size)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + int len = snprintf((char *)&ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, "]}"); + if((len < 0) || (len >= ctx->outbuf->size - ctx->outbuf->len)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +enter_sub(lwm2m_context_t *ctx) +{ + /* set some flags in state */ + LOG_DBG("Enter sub-resource rsc=%d\n", ctx->resource_id); + ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +exit_sub(lwm2m_context_t *ctx) +{ + /* clear out state info */ + LOG_DBG("Exit sub-resource rsc=%d\n", ctx->resource_id); + ctx->writer_flags &= ~WRITER_RESOURCE_INSTANCE; + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_boolean(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value) { - int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"bv\":%s}]}\n", ctx->resource_id, value ? "true" : "false"); + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; + int len; + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"bv\":%s}", sep, ctx->resource_id, ctx->resource_instance_id, value ? "true" : "false"); + } else { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"bv\":%s}", sep, ctx->resource_id, value ? "true" : "false"); + } if((len < 0) || (len >= outlen)) { return 0; } + LOG_DBG("JSON: Write bool:%s\n", outbuf); + + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_int(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value) { - int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":%" PRId32 "}]}\n", ctx->resource_id, value); + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; + int len; + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"v\":%"PRId32"}", sep, ctx->resource_id, ctx->resource_instance_id, value); + } else { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"v\":%"PRId32"}", sep, ctx->resource_id, value); + } if((len < 0) || (len >= outlen)) { return 0; } + LOG_DBG("Write int:%s\n", outbuf); + + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_float32fix(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits) { + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; size_t len = 0; int res; - res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":", ctx->resource_id); + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"v\":", sep, ctx->resource_id, ctx->resource_instance_id); + } else { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"v\":", sep, ctx->resource_id); + } if(res <= 0 || res >= outlen) { return 0; } @@ -96,23 +255,31 @@ write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } len += res; outlen -= res; - res = snprintf((char *)&outbuf[len], outlen, "}]}\n"); + res = snprintf((char *)&outbuf[len], outlen, "}"); if((res <= 0) || (res >= outlen)) { return 0; } len += res; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t stringlen) { + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; size_t i; size_t len = 0; int res; - PRINTF("{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); - res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + LOG_DBG("{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"sv\":\"", sep, + ctx->resource_id, ctx->resource_instance_id); + } else { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"sv\":\"", sep, + ctx->resource_id); + } if(res < 0 || res >= outlen) { return 0; } @@ -121,7 +288,7 @@ write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, /* Escape special characters */ /* TODO: Handle UTF-8 strings */ if(value[i] < '\x20') { - PRINTF("\\x%x", value[i]); + LOG_DBG_("\\x%x", value[i]); res = snprintf((char *)&outbuf[len], outlen - len, "\\x%x", value[i]); if((res < 0) || (res >= (outlen - len))) { return 0; @@ -129,34 +296,44 @@ write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, len += res; continue; } else if(value[i] == '"' || value[i] == '\\') { - PRINTF("\\"); + LOG_DBG_("\\"); outbuf[len] = '\\'; ++len; if(len >= outlen) { return 0; } } - PRINTF("%c", value[i]); + LOG_DBG_("%c", value[i]); outbuf[len] = value[i]; ++len; if(len >= outlen) { return 0; } } - PRINTF("\"}]}\n"); - res = snprintf((char *)&outbuf[len], outlen - len, "\"}]}\n"); + LOG_DBG_("\"}\n"); + res = snprintf((char *)&outbuf[len], outlen - len, "\"}"); if((res < 0) || (res >= (outlen - len))) { return 0; } + + LOG_DBG("JSON: Write string:%s\n", outbuf); + len += res; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ const lwm2m_writer_t lwm2m_json_writer = { + init_write, + end_write, + enter_sub, + exit_sub, write_int, write_string, write_float32fix, write_boolean }; +/*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-json.h b/os/services/lwm2m/lwm2m-json.h index bc1a1e32a..8267d0246 100644 --- a/os/services/lwm2m/lwm2m-json.h +++ b/os/services/lwm2m/lwm2m-json.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -45,7 +45,17 @@ #include "lwm2m-object.h" +struct json_data { + uint8_t type; /* S,B,V */ + uint8_t *name; + uint8_t *value; + uint8_t name_len; + uint8_t value_len; +}; + extern const lwm2m_writer_t lwm2m_json_writer; +int lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json); + #endif /* LWM2M_JSON_H_ */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-object.c b/os/services/lwm2m/lwm2m-object.c deleted file mode 100644 index 2f5ddb6ed..000000000 --- a/os/services/lwm2m/lwm2m-object.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2015, Yanzi Networks 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 - * Implementation of the Contiki OMA LWM2M object API - * \author - * Joakim Eriksson - * Niclas Finne - */ - -#include "lwm2m-object.h" -#include -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_string(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -const uint8_t * -lwm2m_object_get_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context) -{ - if(resource == NULL || context == NULL) { - return NULL; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE) { - return resource->value.string.value; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - return *(resource->value.stringvar.var); - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count) { - return resource->value.stringvararr.var + - resource->value.stringvararr.size * context->object_instance_index; - } - return NULL; - } - /* Not a string */ - return NULL; -} -/*---------------------------------------------------------------------------*/ -uint16_t -lwm2m_object_get_resource_strlen(const lwm2m_resource_t *resource, - const lwm2m_context_t *context) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE) { - return resource->value.string.len; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - return *(resource->value.stringvar.len); - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count) { - return resource->value.stringvararr.len[context->object_instance_index]; - } - return 0; - } - /* Not a string */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - uint16_t len, const uint8_t *string) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - if(len > resource->value.stringvar.size) { - /* Too large */ - return 0; - } - memcpy(resource->value.stringvar.var, string, len); - *(resource->value.stringvar.len) = len; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count && - len <= resource->value.stringvararr.size) { - memcpy(resource->value.stringvararr.var + - resource->value.stringvararr.size * context->object_instance_index, - string, len); - resource->value.stringvararr.len[context->object_instance_index] = len; - return 1; - } - return 0; - } - /* Not a string variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_int(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VALUE) { - *value = resource->value.integer.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE) { - *value = *(resource->value.integervar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.integervararr.count) { - *value = resource->value.integervararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not an integer */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE) { - *(resource->value.integervar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.integervararr.count) { - resource->value.integervararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not an integer variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_floatfix(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE) { - *value = resource->value.floatfix.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE) { - *value = *(resource->value.floatfixvar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.floatfixvararr.count) { - *value = resource->value.floatfixvararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not an float */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE) { - *(resource->value.floatfixvar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.floatfixvararr.count) { - resource->value.floatfixvararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not an float variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_boolean(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE) { - *value = resource->value.boolean.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE) { - *value = *(resource->value.booleanvar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.booleanvararr.count) { - *value = resource->value.booleanvararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not a boolean */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE) { - *(resource->value.booleanvar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.booleanvararr.count) { - resource->value.booleanvararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not a boolean variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/os/services/lwm2m/lwm2m-object.h b/os/services/lwm2m/lwm2m-object.h index a5ff53ac4..c6c582a35 100644 --- a/os/services/lwm2m/lwm2m-object.h +++ b/os/services/lwm2m/lwm2m-object.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,15 +34,15 @@ */ /** - * \defgroup oma-lwm2m An implementation of OMA LWM2M + * \defgroup lwm2m An implementation of LWM2M * @{ * - * This application is an implementation of OMA Lightweight M2M. + * This is an implementation of OMA Lightweight M2M (LWM2M). */ /** * \file - * Header file for the Contiki OMA LWM2M object API + * Header file for the LWM2M object API * \author * Joakim Eriksson * Niclas Finne @@ -51,8 +51,24 @@ #ifndef LWM2M_OBJECT_H_ #define LWM2M_OBJECT_H_ -#include "net/app-layer/coap/rest-engine.h" -#include "net/app-layer/coap/coap-observe.h" +#include "coap.h" +#include "coap-observe.h" + +/* Operation permissions on the resources - read/write/execute */ +#define LWM2M_RESOURCE_READ 0x10000 +#define LWM2M_RESOURCE_WRITE 0x20000 +#define LWM2M_RESOURCE_EXECUTE 0x40000 +#define LWM2M_RESOURCE_OP_MASK 0x70000 + +/* The resource id type of lwm2m objects - 16 bits for the ID - the rest + is flags */ +typedef uint32_t lwm2m_resource_id_t; + +/* Defines for the resource definition array */ +#define RO(x) (x | LWM2M_RESOURCE_READ) +#define WO(x) (x | LWM2M_RESOURCE_WRITE) +#define RW(x) (x | LWM2M_RESOURCE_READ | LWM2M_RESOURCE_WRITE) +#define EX(x) (x | LWM2M_RESOURCE_EXECUTE) #define LWM2M_OBJECT_SECURITY_ID 0 #define LWM2M_OBJECT_SERVER_ID 1 @@ -63,291 +79,281 @@ #define LWM2M_OBJECT_LOCATION_ID 6 #define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID 7 -#define LWM2M_SECURITY_SERVER_URI 0 -#define LWM2M_SECURITY_BOOTSTRAP_SERVER 1 -#define LWM2M_SECURITY_MODE 2 -#define LWM2M_SECURITY_CLIENT_PKI 3 -#define LWM2M_SECURITY_SERVER_PKI 4 -#define LWM2M_SECURITY_KEY 5 -#define LWM2M_SECURITY_SHORT_SERVER_ID 10 +typedef enum { + LWM2M_OP_NONE, + LWM2M_OP_READ, + LWM2M_OP_DISCOVER, + LWM2M_OP_WRITE, + LWM2M_OP_WRITE_ATTR, + LWM2M_OP_EXECUTE, + LWM2M_OP_CREATE, + LWM2M_OP_DELETE +} lwm2m_operation_t; -/* Pre-shared key mode */ -#define LWM2M_SECURITY_MODE_PSK 0 -/* Raw Public Key mode */ -#define LWM2M_SECURITY_MODE_RPK 1 -/* Certificate mode */ -#define LWM2M_SECURITY_MODE_CERTIFICATE 2 -/* NoSec mode */ -#define LWM2M_SECURITY_MODE_NOSEC 3 +typedef enum { + LWM2M_STATUS_OK, -#define LWM2M_OBJECT_STR_HELPER(x) (uint8_t *) #x -#define LWM2M_OBJECT_STR(x) LWM2M_OBJECT_STR_HELPER(x) + /* Internal server error */ + LWM2M_STATUS_ERROR, + /* Error from writer */ + LWM2M_STATUS_WRITE_ERROR, + /* Error from reader */ + LWM2M_STATUS_READ_ERROR, -#define LWM2M_OBJECT_PATH_STR_HELPER(x) #x -#define LWM2M_OBJECT_PATH_STR(x) LWM2M_OBJECT_PATH_STR_HELPER(x) + LWM2M_STATUS_BAD_REQUEST, + LWM2M_STATUS_UNAUTHORIZED, + LWM2M_STATUS_FORBIDDEN, + LWM2M_STATUS_NOT_FOUND, + LWM2M_STATUS_OPERATION_NOT_ALLOWED, + LWM2M_STATUS_NOT_ACCEPTABLE, + LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT, + + LWM2M_STATUS_NOT_IMPLEMENTED, + LWM2M_STATUS_SERVICE_UNAVAILABLE, +} lwm2m_status_t; + +/* remember that we have already output a value - can be between two block's */ +#define WRITER_OUTPUT_VALUE 1 +#define WRITER_RESOURCE_INSTANCE 2 +#define WRITER_HAS_MORE 4 + +typedef struct lwm2m_reader lwm2m_reader_t; +typedef struct lwm2m_writer lwm2m_writer_t; + +typedef struct lwm2m_object_instance lwm2m_object_instance_t; + +typedef struct { + uint16_t len; /* used for current length of the data in the buffer */ + uint16_t pos; /* position in the buffer - typically write position or similar */ + uint16_t size; + uint8_t *buffer; +} lwm2m_buffer_t; -struct lwm2m_reader; -struct lwm2m_writer; /* Data model for OMA LWM2M objects */ typedef struct lwm2m_context { uint16_t object_id; uint16_t object_instance_id; uint16_t resource_id; - uint8_t object_instance_index; - uint8_t resource_index; - /* TODO - add uint16_t resource_instance_id */ + uint16_t resource_instance_id; - const struct lwm2m_reader *reader; - const struct lwm2m_writer *writer; + uint8_t resource_index; + uint8_t resource_instance_index; /* for use when stepping to next sub-resource if having multiple */ + uint8_t level; /* 0/1/2/3 = 3 = resource */ + lwm2m_operation_t operation; + + coap_message_t *request; + coap_message_t *response; + + unsigned int content_type; + lwm2m_buffer_t *outbuf; + lwm2m_buffer_t *inbuf; + + uint8_t out_mark_pos_oi; /* mark pos for last object instance */ + uint8_t out_mark_pos_ri; /* mark pos for last resource instance */ + + uint32_t offset; /* If we do blockwise - this needs to change */ + + /* Info on last_instance read/write */ + uint16_t last_instance; + uint16_t last_value_len; + + uint8_t writer_flags; /* flags for reader/writer */ + const lwm2m_reader_t *reader; + const lwm2m_writer_t *writer; } lwm2m_context_t; /* LWM2M format writer for the various formats supported */ -typedef struct lwm2m_writer { - size_t (* write_int)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value); - size_t (* write_string)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen); - size_t (* write_float32fix)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits); - size_t (* write_boolean)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value); -} lwm2m_writer_t; +struct lwm2m_writer { + size_t (* init_write)(lwm2m_context_t *ctx); + size_t (* end_write)(lwm2m_context_t *ctx); + /* For sub-resources */ + size_t (* enter_resource_instance)(lwm2m_context_t *ctx); + size_t (* exit_resource_instance)(lwm2m_context_t *ctx); + size_t (* write_int)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value); + size_t (* write_string)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen); + size_t (* write_float32fix)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits); + size_t (* write_boolean)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value); + size_t (* write_opaque_header)(lwm2m_context_t *ctx, size_t total_size); +}; -typedef struct lwm2m_reader { - size_t (* read_int)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value); - size_t (* read_string)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen); - size_t (* read_float32fix)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits); - size_t (* read_boolean)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value); -} lwm2m_reader_t; +struct lwm2m_reader { + size_t (* read_int)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value); + size_t (* read_string)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen); + size_t (* read_float32fix)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits); + size_t (* read_boolean)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value); +}; -typedef struct lwm2m_value_callback { - int (* read)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen); - int (* write)(lwm2m_context_t *ctx, - const uint8_t *buffer, size_t len, - uint8_t *outbuf, size_t outlen); - int (* exec)(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, - uint8_t *outbuf, size_t outlen); -} lwm2m_value_callback_t; +typedef lwm2m_status_t +(* lwm2m_write_opaque_callback)(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write); -#define LWM2M_RESOURCE_TYPE_STR_VALUE 1 -#define LWM2M_RESOURCE_TYPE_STR_VARIABLE 2 -#define LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY 3 -#define LWM2M_RESOURCE_TYPE_INT_VALUE 4 -#define LWM2M_RESOURCE_TYPE_INT_VARIABLE 5 -#define LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY 6 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE 7 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE 8 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY 9 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE 10 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE 11 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY 12 -#define LWM2M_RESOURCE_TYPE_CALLBACK 16 -#define LWM2M_RESOURCE_TYPE_INSTANCES 17 - -typedef struct lwm2m_resource { - uint16_t id; - uint8_t type; /* indicate value type and multi-instance resource */ - union { - struct { - uint16_t len; - const uint8_t *value; - } string; - struct { - uint16_t size; - uint16_t *len; - uint8_t **var; - } stringvar; - struct { - uint16_t count; - uint16_t size; - /* string var array with counting entries */ - uint16_t *len; - uint8_t *var; - } stringvararr; - struct { - int32_t value; - } integer; - struct { - int32_t *var; - } integervar; - struct { - /* used for multiple instances (dynamic) NOTE: this is an index into - the instance so having two instances means that there is need for - allocation of two ints here */ - uint16_t count; - int32_t *var; /* used as an array? */ - } integervararr; - struct { - int32_t value; - } floatfix; - struct { - int32_t *var; - } floatfixvar; - struct { - uint16_t count; - int32_t *var; - } floatfixvararr; - struct { - int value; - } boolean; - struct { - int *var; - } booleanvar; - struct { - uint16_t count; - int *var; - } booleanvararr; - lwm2m_value_callback_t callback; - /* lwm2m_resource *resources[]; TO BE ADDED LATER*/ - } value; -} lwm2m_resource_t; - -#define LWM2M_INSTANCE_FLAG_USED 1 - -typedef struct lwm2m_instance { - uint16_t id; - uint16_t count; - uint16_t flag; - const lwm2m_resource_t *resources; -} lwm2m_instance_t; - -typedef struct lwm2m_object { - uint16_t id; - uint16_t count; - const char *path; - resource_t *coap_resource; - lwm2m_instance_t *instances; -} lwm2m_object_t; - -#define LWM2M_RESOURCES(name, ...) \ - static const lwm2m_resource_t name[] = { __VA_ARGS__ } - -#define LWM2M_RESOURCE_STRING(id, s) \ - { id, LWM2M_RESOURCE_TYPE_STR_VALUE, .value.string.len = sizeof(s) - 1, .value.string.value = (uint8_t *) s } - -#define LWM2M_RESOURCE_STRING_VAR(id, s, l, v) \ - { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE, .value.stringvar.size = (s), .value.stringvar.len = (l), .value.stringvar.var = (v) } - -#define LWM2M_RESOURCE_STRING_VAR_ARR(id, c, s, l, v) \ - { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY, .value.stringvararr.count = c, .value.stringvararr.size = s, .value.stringvararr.len = l, .value.stringvararr.var = (uint8_t *) v } - -#define LWM2M_RESOURCE_INTEGER(id, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VALUE, .value.integer.value = (v) } - -#define LWM2M_RESOURCE_INTEGER_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE, .value.integervar.var = (v) } - -#define LWM2M_RESOURCE_INTEGER_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY, .value.integervararr.count = (c), .value.integervararr.var = (v) } - -#define LWM2M_RESOURCE_FLOATFIX(id, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE, .value.floatfix.value = (v) } - -#define LWM2M_RESOURCE_FLOATFIX_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE, .value.floatfixvar.var = (v) } - -#define LWM2M_RESOURCE_FLOATFIX_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY, .value.floatfixvararr.count = (c), .value.floatfixvararr.var = (v) } - -#define LWM2M_RESOURCE_BOOLEAN(id, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE, .value.boolean.value = (v) } - -#define LWM2M_RESOURCE_BOOLEAN_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE, .value.booleanvar.var = (v) } - -#define LWM2M_RESOURCE_BOOLEAN_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY, .value.booleanvararr.count = (c), .value.booleanvararr.var = (v) } - -#define LWM2M_RESOURCE_CALLBACK(id, ...) \ - { id, LWM2M_RESOURCE_TYPE_CALLBACK, .value.callback = __VA_ARGS__ } - -#define LWM2M_INSTANCE(id, resources) \ - { id, sizeof(resources)/sizeof(lwm2m_resource_t), LWM2M_INSTANCE_FLAG_USED, resources } - -#define LWM2M_INSTANCE_UNUSED(id, resources) \ - { id, sizeof(resources)/sizeof(lwm2m_resource_t), 0, resources } - -#define LWM2M_INSTANCES(name, ...) \ - static lwm2m_instance_t name[] = { __VA_ARGS__ } - -#define LWM2M_OBJECT(name, id, instances) \ - static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static resource_t rest_rsc_##name = { NULL, NULL, HAS_SUB_RESOURCES | IS_OBSERVABLE, NULL, lwm2m_get_h_##name, lwm2m_post_h_##name, lwm2m_put_h_##name, lwm2m_delete_h_##name, { NULL } }; \ - static const lwm2m_object_t name = { id, sizeof(instances)/sizeof(lwm2m_instance_t), LWM2M_OBJECT_PATH_STR(id), &rest_rsc_##name, instances}; \ - static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_delete_handler(&name, request, response, buffer, preferred_size, offset); } - -/* how do we register attributes in the above resource here ??? */ - -int lwm2m_object_is_resource_string(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_int(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_floatfix(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_boolean(const lwm2m_resource_t *resource); - -static inline int -lwm2m_object_is_resource_callback(const lwm2m_resource_t *resource) -{ - return resource != NULL && resource->type == LWM2M_RESOURCE_TYPE_CALLBACK; -} - -const uint8_t * -lwm2m_object_get_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context); - -uint16_t -lwm2m_object_get_resource_strlen(const lwm2m_resource_t *resource, - const lwm2m_context_t *context); - -int -lwm2m_object_set_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - uint16_t len, const uint8_t *string); - -int -lwm2m_object_get_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value); - -int -lwm2m_object_set_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value); - -int -lwm2m_object_get_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value); - -int -lwm2m_object_set_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value); - -int -lwm2m_object_get_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int *value); - -int -lwm2m_object_set_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int value); - -static inline resource_t * -lwm2m_object_get_coap_resource(const lwm2m_object_t *object) -{ - return (resource_t *)object->coap_resource; -} +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); static inline void -lwm2m_object_notify_observers(const lwm2m_object_t *object, char *path) +lwm2m_notify_observers(char *path) { - coap_notify_observers_sub(lwm2m_object_get_coap_resource(object), path); + coap_notify_observers_sub(NULL, path); +} + +static inline size_t +lwm2m_object_read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) +{ + return ctx->reader->read_int(ctx, inbuf, len, value); +} + +static inline size_t +lwm2m_object_read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen) +{ + return ctx->reader->read_string(ctx, inbuf, len, value, strlen); +} + +static inline size_t +lwm2m_object_read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) +{ + return ctx->reader->read_float32fix(ctx, inbuf, len, value, bits); +} + +static inline size_t +lwm2m_object_read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) +{ + return ctx->reader->read_boolean(ctx, inbuf, len, value); +} + +static inline size_t +lwm2m_object_write_int(lwm2m_context_t *ctx, int32_t value) +{ + size_t s; + s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_string(lwm2m_context_t *ctx, const char *value, size_t strlen) +{ + size_t s; + s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, strlen); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_float32fix(lwm2m_context_t *ctx, int32_t value, int bits) +{ + size_t s; + s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, bits); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_boolean(lwm2m_context_t *ctx, int value) +{ + size_t s; + s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline int +lwm2m_object_write_opaque_stream(lwm2m_context_t *ctx, int size, lwm2m_write_opaque_callback cb) +{ + /* 1. - create a header of either OPAQUE (nothing) or TLV if the format is TLV */ + size_t s; + if(ctx->writer->write_opaque_header != NULL) { + s = ctx->writer->write_opaque_header(ctx, size); + ctx->outbuf->len += s; + } else { + return 0; + } + /* 2. - set the callback so that future data will be grabbed from the callback */ + lwm2m_engine_set_opaque_callback(ctx, cb); + return 1; +} + +/* Resource instance functions (_ri)*/ + +static inline size_t +lwm2m_object_write_enter_ri(lwm2m_context_t *ctx) +{ + if(ctx->writer->enter_resource_instance != NULL) { + size_t s; + s = ctx->writer->enter_resource_instance(ctx); + ctx->outbuf->len += s; + return s; + } + return 0; +} + +static inline size_t +lwm2m_object_write_exit_ri(lwm2m_context_t *ctx) +{ + if(ctx->writer->exit_resource_instance != NULL) { + size_t s; + s = ctx->writer->exit_resource_instance(ctx); + ctx->outbuf->len += s; + return s; + } + return 0; +} + +static inline size_t +lwm2m_object_write_int_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_string_ri(lwm2m_context_t *ctx, uint16_t id, const char *value, size_t strlen) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, strlen); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_float32fix_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value, int bits) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, bits); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_boolean_ri(lwm2m_context_t *ctx, uint16_t id, int value) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline int +lwm2m_object_is_final_incoming(lwm2m_context_t *ctx) +{ + uint8_t more; + if(coap_get_header_block1(ctx->request, NULL, &more, NULL, NULL)) { + return !more; + } + /* If we do not know this is final... it might not be... */ + return 0; } #include "lwm2m-engine.h" diff --git a/os/services/lwm2m/lwm2m-plain-text.c b/os/services/lwm2m/lwm2m-plain-text.c index b2bc5dcbe..bbd293aa0 100644 --- a/os/services/lwm2m/lwm2m-plain-text.c +++ b/os/services/lwm2m/lwm2m-plain-text.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -47,13 +47,23 @@ #include #include -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-plain-text" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ +static size_t +init_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + return 0; +} /*---------------------------------------------------------------------------*/ size_t lwm2m_plain_text_read_int(const uint8_t *inbuf, size_t len, int32_t *value) @@ -109,15 +119,16 @@ lwm2m_plain_text_read_float32fix(const uint8_t *inbuf, size_t len, if(frac > 1) { *value += ((counter << bits) / frac); } - PRINTF("READ FLOATFIX: \"%.*s\" => int(%ld) frac(%ld) f=%ld Value=%ld\n", - (int)len, (char *)inbuf, - (long)integerpart, - (long)counter, - (long)frac, - (long)*value); + LOG_DBG("READ FLOATFIX: \"%.*s\" => int(%ld) frac(%ld) f=%ld Value=%ld\n", + (int)len, (char *)inbuf, + (long)integerpart, + (long)counter, + (long)frac, + (long)*value); if(neg) { *value = -*value; } + return i; } /*---------------------------------------------------------------------------*/ @@ -153,7 +164,7 @@ lwm2m_plain_text_write_float32fix(uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_boolean(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value) { if(outlen > 0) { @@ -168,7 +179,7 @@ write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_int(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value) { int n = snprintf((char *)outbuf, outlen, "%ld", (long)value); @@ -179,24 +190,30 @@ write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_float32fix(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits) { return lwm2m_plain_text_write_float32fix(outbuf, outlen, value, bits); } /*---------------------------------------------------------------------------*/ static size_t -write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t stringlen) { - int n = snprintf((char *)outbuf, outlen, "%.*s", (int) stringlen, value); - if(n < 0 || n >= outlen) { + int totlen = stringlen; + if(stringlen >= outlen) { return 0; } - return n; + memmove(outbuf, value, totlen); + outbuf[totlen] = 0; + return totlen; } /*---------------------------------------------------------------------------*/ const lwm2m_writer_t lwm2m_plain_text_writer = { + init_write, + end_write, + NULL, /* No support for sub resources here! */ + NULL, write_int, write_string, write_float32fix, @@ -204,14 +221,16 @@ const lwm2m_writer_t lwm2m_plain_text_writer = { }; /*---------------------------------------------------------------------------*/ static size_t -read_int(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) { - return lwm2m_plain_text_read_int(inbuf, len, value); + int size = lwm2m_plain_text_read_int(inbuf, len, value); + ctx->last_value_len = size; + return size; } /*---------------------------------------------------------------------------*/ static size_t -read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t stringlen) { if(stringlen <= len) { @@ -220,23 +239,28 @@ read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, } memcpy(value, inbuf, len); value[len] = '\0'; + ctx->last_value_len = len; return len; } /*---------------------------------------------------------------------------*/ static size_t -read_float32fix(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) { - return lwm2m_plain_text_read_float32fix(inbuf, len, value, bits); + int size; + size = lwm2m_plain_text_read_float32fix(inbuf, len, value, bits); + ctx->last_value_len = size; + return size; } /*---------------------------------------------------------------------------*/ static size_t -read_boolean(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) { if(len > 0) { if(*inbuf == '1' || *inbuf == '0') { *value = *inbuf == '1' ? 1 : 0; + ctx->last_value_len = 1; return 1; } } diff --git a/os/services/lwm2m/lwm2m-plain-text.h b/os/services/lwm2m/lwm2m-plain-text.h index bf12a118c..7922a8ce8 100644 --- a/os/services/lwm2m/lwm2m-plain-text.h +++ b/os/services/lwm2m/lwm2m-plain-text.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c new file mode 100644 index 000000000..0f904ee4d --- /dev/null +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2015-2018, Yanzi Networks 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 engine + * Registration and bootstrap client + * \author + * Joakim Eriksson + * Niclas Finne + * Joel Hoglund + */ + +#include "lwm2m-engine.h" +#include "lwm2m-object.h" +#include "lwm2m-device.h" +#include "lwm2m-plain-text.h" +#include "lwm2m-json.h" +#include "lwm2m-rd-client.h" +#include "coap.h" +#include "coap-engine.h" +#include "coap-endpoint.h" +#include "coap-callback-api.h" +#include "lwm2m-security.h" +#include +#include +#include + +#if UIP_CONF_IPV6_RPL +#include "rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-rd-client" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#ifndef LWM2M_DEFAULT_CLIENT_LIFETIME +#define LWM2M_DEFAULT_CLIENT_LIFETIME 30 /* sec */ +#endif + +#define MAX_RD_UPDATE_WAIT 5000 + +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define BS_REMOTE_PORT UIP_HTONS(5685) + +#define STATE_MACHINE_UPDATE_INTERVAL 500 + +static struct lwm2m_session_info session_info; +static coap_request_state_t rd_request_state; + +static coap_message_t request[1]; /* This way the message can be treated as pointer as usual. */ + +/* The states for the RD client state machine */ +/* When node is unregistered it ends up in UNREGISTERED + and this is going to be there until use X or Y kicks it + back into INIT again */ +#define INIT 0 +#define WAIT_NETWORK 1 +#define DO_BOOTSTRAP 3 +#define BOOTSTRAP_SENT 4 +#define BOOTSTRAP_DONE 5 +#define DO_REGISTRATION 6 +#define REGISTRATION_SENT 7 +#define REGISTRATION_DONE 8 +#define UPDATE_SENT 9 +#define DEREGISTER 10 +#define DEREGISTER_SENT 11 +#define DEREGISTER_FAILED 12 +#define DEREGISTERED 13 + +#define FLAG_RD_DATA_DIRTY 0x01 +#define FLAG_RD_DATA_UPDATE_TRIGGERED 0x02 +#define FLAG_RD_DATA_UPDATE_ON_DIRTY 0x10 + +static uint8_t rd_state = 0; +static uint8_t rd_flags = FLAG_RD_DATA_UPDATE_ON_DIRTY; +static uint64_t wait_until_network_check = 0; +static uint64_t last_update; +static uint64_t last_rd_progress = 0; + +static char query_data[64]; /* allocate some data for queries and updates */ +static uint8_t rd_data[128]; /* allocate some data for the RD */ + +static uint32_t rd_block1; +static uint8_t rd_more; +static coap_timer_t rd_timer; +static void (*rd_callback)(coap_request_state_t *state); + +static coap_timer_t block1_timer; + +static void check_periodic_observations(); +static void update_callback(coap_request_state_t *state); + +static int +set_rd_data(coap_message_t *request) +{ + lwm2m_buffer_t outbuf; + + /* setup the output buffer */ + outbuf.buffer = rd_data; + outbuf.size = sizeof(rd_data); + outbuf.len = 0; + + /* this will also set the request payload */ + rd_more = lwm2m_engine_set_rd_data(&outbuf, 0); + coap_set_payload(request, rd_data, outbuf.len); + + if(rd_more) { + /* set the first block here */ + LOG_DBG("Setting block1 in request\n"); + coap_set_header_block1(request, 0, 1, sizeof(rd_data)); + } + return outbuf.len; +} +/*---------------------------------------------------------------------------*/ +static void +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); + + snprintf(query_data, sizeof(query_data) - 1, "?lt=%d&b=%s", session_info.lifetime, session_info.binding); + LOG_DBG("UPDATE:%s %s\n", session_info.assigned_ep, query_data); + coap_set_header_uri_query(request, query_data); + + if((triggered || rd_flags & FLAG_RD_DATA_UPDATE_ON_DIRTY) && (rd_flags & FLAG_RD_DATA_DIRTY)) { + rd_flags &= ~FLAG_RD_DATA_DIRTY; + set_rd_data(request); + rd_callback = update_callback; + } +} +/*---------------------------------------------------------------------------*/ +static int +has_network_access(void) +{ +#if UIP_CONF_IPV6_RPL +/* NATIVE PLATFORM is not really running RPL */ +#ifndef CONTIKI_TARGET_NATIVE + if(rpl_get_any_dag() == NULL) { + return 0; + } +#endif +#endif /* UIP_CONF_IPV6_RPL */ + return 1; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_rd_client_is_registered(void) +{ + return rd_state == REGISTRATION_DONE || rd_state == UPDATE_SENT; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_use_bootstrap_server(int use) +{ + session_info.use_bootstrap = use != 0; + if(session_info.use_bootstrap) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +/* will take another argument when we support multiple sessions */ +void +lwm2m_rd_client_set_session_callback(session_callback_t cb) +{ + session_info.callback = cb; +} +/*---------------------------------------------------------------------------*/ +static void +perform_session_callback(int state) +{ + if(session_info.callback != NULL) { + LOG_DBG("Performing session callback: %d cb:%p\n", + state, session_info.callback); + session_info.callback(&session_info, state); + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_use_registration_server(int use) +{ + session_info.use_registration = use != 0; + if(session_info.use_registration) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +uint16_t +lwm2m_rd_client_get_lifetime(void) +{ + return session_info.lifetime; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_lifetime(uint16_t lifetime) +{ + if(lifetime > 0) { + session_info.lifetime = lifetime; + } else { + session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME; + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_update_rd(void) +{ + rd_flags |= FLAG_RD_DATA_DIRTY; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_automatic_update(int update) +{ + rd_flags = (rd_flags & ~FLAG_RD_DATA_UPDATE_ON_DIRTY) | + (update != 0 ? FLAG_RD_DATA_UPDATE_ON_DIRTY : 0); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_register_with_server(const coap_endpoint_t *server) +{ + coap_endpoint_copy(&session_info.server_ep, server); + session_info.has_registration_server_info = 1; + session_info.registered = 0; + if(session_info.use_registration) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +static int +update_registration_server(void) +{ + if(session_info.has_registration_server_info) { + return 1; + } + +#if UIP_CONF_IPV6_RPL + { + rpl_dag_t *dag; + + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL) { + /* create coap-endpoint? */ + /* uip_ipaddr_copy(&server_ipaddr, &dag->dag_id); */ + /* server_port = REMOTE_PORT; */ + return 1; + } + } +#endif /* UIP_CONF_IPV6_RPL */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server) +{ + coap_endpoint_copy(&session_info.bs_server_ep, server); + session_info.has_bs_server_info = 1; + session_info.bootstrapped = 0; + session_info.registered = 0; + if(session_info.use_bootstrap) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_rd_client_deregister(void) +{ + if(lwm2m_rd_client_is_registered()) { + rd_state = DEREGISTER; + return 1; + } + /* Not registered */ + return 0; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_update_triggered(void) +{ + rd_flags |= FLAG_RD_DATA_UPDATE_TRIGGERED; + /* Here we need to do an CoAP timer poll - to get a quick request transmission! */ +} +/*---------------------------------------------------------------------------*/ +static int +update_bootstrap_server(void) +{ + if(session_info.has_bs_server_info) { + return 1; + } + +#if UIP_CONF_IPV6_RPL + { + rpl_dag_t *dag; + + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL) { + /* create coap endpoint */ + /* uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); */ + /* bs_server_port = REMOTE_PORT; */ + return 1; + } + } +#endif /* UIP_CONF_IPV6_RPL */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * A client initiated bootstrap starts with a POST to /bs?ep={session_info.ep}, + * on the bootstrap server. The server should reply with 2.04. + * The server will thereafter do DELETE and or PUT to write new client objects. + * The bootstrap finishes with the server doing POST to /bs on the client. + * + * Page 64 in 07 April 2016 spec. + * + * TODO + */ +static void +bootstrap_callback(coap_request_state_t *state) +{ + LOG_DBG("Bootstrap callback Response: %d, ", state->response != NULL); + if(state->response) { + if(CHANGED_2_04 == state->response->code) { + LOG_DBG_("Considered done!\n"); + rd_state = BOOTSTRAP_DONE; + return; + } + /* Possible error response codes are 4.00 Bad request & 4.15 Unsupported content format */ + LOG_DBG_("Failed with code %d. Retrying\n", state->response->code); + /* TODO Application callback? */ + rd_state = INIT; + } else if(BOOTSTRAP_SENT == rd_state) { /* this can handle double invocations */ + /* Failure! */ + LOG_DBG("Bootstrap failed! Retry?"); + rd_state = DO_BOOTSTRAP; + } else { + LOG_DBG("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +produce_more_rd(void) +{ + lwm2m_buffer_t outbuf; + + LOG_DBG("GOT Continue!\n"); + + /* setup the output buffer */ + outbuf.buffer = rd_data; + outbuf.size = sizeof(rd_data); + outbuf.len = 0; + + rd_block1++; + + /* this will also set the request payload */ + rd_more = lwm2m_engine_set_rd_data(&outbuf, rd_block1); + coap_set_payload(request, rd_data, outbuf.len); + + LOG_DBG("Setting block1 in request - block: %d more: %d\n", + (int)rd_block1, (int)rd_more); + coap_set_header_block1(request, rd_block1, rd_more, sizeof(rd_data)); + + coap_send_request(&rd_request_state, &session_info.server_ep, request, rd_callback); +} +/*---------------------------------------------------------------------------*/ +static void +block1_rd_callback(coap_timer_t *timer) +{ + produce_more_rd(); +} +/*---------------------------------------------------------------------------*/ +/* + * Page 65-66 in 07 April 2016 spec. + */ +static void +registration_callback(coap_request_state_t *state) +{ + LOG_DBG("Registration callback. Response: %d, ", state->response != NULL); + if(state->response) { + /* check state and possibly set registration to done */ + /* If we get a continue - we need to call the rd generator one more time */ + if(CONTINUE_2_31 == state->response->code) { + /* We assume that size never change?! */ + coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); + coap_timer_set_callback(&block1_timer, block1_rd_callback); + coap_timer_set(&block1_timer, 1); /* delay 1 ms */ + LOG_DBG_("Continue\n"); + } else if(CREATED_2_01 == state->response->code) { + if(state->response->location_path_len < LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN) { + memcpy(session_info.assigned_ep, state->response->location_path, + 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 */ + rd_state = REGISTRATION_DONE; + /* remember the last reg time */ + last_update = coap_timer_uptime(); + LOG_DBG_("Done (assigned EP='%s')!\n", session_info.assigned_ep); + perform_session_callback(LWM2M_RD_CLIENT_REGISTERED); + return; + } + + LOG_DBG_("failed to handle assigned EP: '"); + LOG_DBG_COAP_STRING(state->response->location_path, + state->response->location_path_len); + LOG_DBG_("'. Re-init network.\n"); + } else { + /* Possible error response codes are 4.00 Bad request & 4.03 Forbidden */ + LOG_DBG_("failed with code %d. Re-init network\n", state->response->code); + } + /* TODO Application callback? */ + rd_state = INIT; + /* remember last progress time */ + last_rd_progress = coap_timer_uptime(); + } else { + LOG_DBG_("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +/* + * Page 65-66 in 07 April 2016 spec. + */ +static void +update_callback(coap_request_state_t *state) +{ + LOG_DBG("Update callback. Response: %d, ", state->response != NULL); + + if(state->response) { + /* If we get a continue - we need to call the rd generator one more time */ + if(CONTINUE_2_31 == state->response->code) { + /* We assume that size never change?! */ + LOG_DBG_("Continue\n"); + coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); + coap_timer_set_callback(&block1_timer, block1_rd_callback); + coap_timer_set(&block1_timer, 1); /* delay 1 ms */ + } else if(CHANGED_2_04 == state->response->code) { + LOG_DBG_("Done!\n"); + /* remember the last reg time */ + last_update = coap_timer_uptime(); + rd_state = REGISTRATION_DONE; + rd_flags &= ~FLAG_RD_DATA_UPDATE_TRIGGERED; + } else { + /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */ + LOG_DBG_("Failed with code %d. Retrying registration\n", + state->response->code); + rd_state = DO_REGISTRATION; + } + /* remember last progress */ + last_rd_progress = coap_timer_uptime(); + } else { + LOG_DBG("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +deregister_callback(coap_request_state_t *state) +{ + LOG_DBG("Deregister callback. Response Code: %d\n", + state->response != NULL ? state->response->code : 0); + + if(state->response && (DELETED_2_02 == state->response->code)) { + LOG_DBG("Deregistration success\n"); + rd_state = DEREGISTERED; + perform_session_callback(LWM2M_RD_CLIENT_DEREGISTERED); + } else { + LOG_DBG("Deregistration failed\n"); + if(rd_state == DEREGISTER_SENT) { + rd_state = DEREGISTER_FAILED; + perform_session_callback(LWM2M_RD_CLIENT_DEREGISTER_FAILED); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +recover_from_rd_delay(void) +{ + /* This can be improved in the future... */ + rd_state = INIT; +} +/*---------------------------------------------------------------------------*/ +/* CoAP timer callback */ +static void +periodic_process(coap_timer_t *timer) +{ + uint64_t now; + + /* reschedule the CoAP timer */ + coap_timer_reset(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); + now = coap_timer_uptime(); + + LOG_DBG("RD Client - state: %d, ms: %lu\n", rd_state, + (unsigned long)coap_timer_uptime()); + + switch(rd_state) { + case INIT: + LOG_DBG("RD Client started with endpoint '%s' and client lifetime %d\n", session_info.ep, session_info.lifetime); + rd_state = WAIT_NETWORK; + break; + case WAIT_NETWORK: + if(now > wait_until_network_check) { + /* check each 10 seconds before next check */ + LOG_DBG("Checking for network... %lu\n", + (unsigned long)wait_until_network_check); + wait_until_network_check = now + 10000; + if(has_network_access()) { + /* Either do bootstrap then registration */ + if(session_info.use_bootstrap) { + rd_state = DO_BOOTSTRAP; + } else { + rd_state = DO_REGISTRATION; + } + } + /* Otherwise wait until for a network to join */ + } + break; + case DO_BOOTSTRAP: + if(session_info.use_bootstrap && session_info.bootstrapped == 0) { + if(update_bootstrap_server()) { + /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, "/bs"); + + snprintf(query_data, sizeof(query_data) - 1, "?ep=%s", session_info.ep); + coap_set_header_uri_query(request, query_data); + LOG_INFO("Registering ID with bootstrap server ["); + LOG_INFO_COAP_EP(&session_info.bs_server_ep); + LOG_INFO_("] as '%s'\n", query_data); + + coap_send_request(&rd_request_state, &session_info.bs_server_ep, + request, bootstrap_callback); + + rd_state = BOOTSTRAP_SENT; + } + } + break; + case BOOTSTRAP_SENT: + /* Just wait for bootstrap to be done... */ + break; + case BOOTSTRAP_DONE: + /* check that we should still use bootstrap */ + if(session_info.use_bootstrap) { + lwm2m_security_server_t *security; + LOG_DBG("*** Bootstrap - checking for server info...\n"); + /* get the security object - ignore bootstrap servers */ + for(security = lwm2m_security_get_first(); + security != NULL; + security = lwm2m_security_get_next(security)) { + if(security->bootstrap == 0) { + break; + } + } + + if(security != NULL) { + /* get the server URI */ + if(security->server_uri_len > 0) { + uint8_t secure = 0; + + LOG_DBG("**** Found security instance using: "); + LOG_DBG_COAP_STRING((const char *)security->server_uri, + security->server_uri_len); + LOG_DBG_(" (len %d) \n", security->server_uri_len); + /* TODO Should verify it is a URI */ + /* Check if secure */ + secure = strncmp((const char *)security->server_uri, + "coaps:", 6) == 0; + + if(!coap_endpoint_parse((const char *)security->server_uri, + security->server_uri_len, + &session_info.server_ep)) { + LOG_DBG("Failed to parse server URI!\n"); + } else { + LOG_DBG("Server address:"); + LOG_DBG_COAP_EP(&session_info.server_ep); + LOG_DBG_("\n"); + if(secure) { + LOG_DBG("Secure CoAP requested but not supported - can not bootstrap\n"); + } else { + lwm2m_rd_client_register_with_server(&session_info.server_ep); + session_info.bootstrapped++; + } + } + } else { + LOG_DBG("** failed to parse URI "); + LOG_DBG_COAP_STRING((const char *)security->server_uri, + security->server_uri_len); + LOG_DBG_("\n"); + } + } + + /* if we did not register above - then fail this and restart... */ + if(session_info.bootstrapped == 0) { + /* Not ready. Lets retry with the bootstrap server again */ + rd_state = DO_BOOTSTRAP; + } else { + rd_state = DO_REGISTRATION; + } + } + break; + case DO_REGISTRATION: + if(!coap_endpoint_is_connected(&session_info.server_ep)) { + /* Not connected... wait a bit... and retry connection */ + coap_endpoint_connect(&session_info.server_ep); + LOG_DBG("Wait until connected... \n"); + return; + } + if(session_info.use_registration && !session_info.registered && + update_registration_server()) { + int len; + + /* prepare request, TID was set by COAP_BLOCKING_REQUEST() */ + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, "/rd"); + + snprintf(query_data, sizeof(query_data) - 1, "?ep=%s<=%d&b=%s", session_info.ep, session_info.lifetime, session_info.binding); + coap_set_header_uri_query(request, query_data); + + len = set_rd_data(request); + rd_callback = registration_callback; + + LOG_INFO("Registering with ["); + LOG_INFO_COAP_EP(&session_info.server_ep); + LOG_INFO_("] lwm2m endpoint '%s': '", query_data); + if(len) { + LOG_INFO_COAP_STRING((const char *)rd_data, len); + } + LOG_INFO_("' More:%d\n", rd_more); + + coap_send_request(&rd_request_state, &session_info.server_ep, + request, registration_callback); + last_rd_progress = coap_timer_uptime(); + rd_state = REGISTRATION_SENT; + } + break; + case REGISTRATION_SENT: + /* just wait until the callback kicks us to the next state... */ + if(last_rd_progress + MAX_RD_UPDATE_WAIT < coap_timer_uptime()) { + /* Timeout on the update - something is wrong? */ + recover_from_rd_delay(); + } + break; + case REGISTRATION_DONE: + /* All is done! */ + + check_periodic_observations(); /* TODO: manage periodic observations */ + + /* check if it is time for the next update */ + if((rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED) || + ((uint32_t)session_info.lifetime * 500) <= now - last_update) { + /* triggered or time to send an update to the server, at half-time! sec vs ms */ + 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; + + case UPDATE_SENT: + /* just wait until the callback kicks us to the next state... */ + if(last_rd_progress + MAX_RD_UPDATE_WAIT < coap_timer_uptime()) { + /* Timeout on the update - something is wrong? */ + recover_from_rd_delay(); + } + break; + case DEREGISTER: + LOG_INFO("DEREGISTER %s\n", session_info.assigned_ep); + coap_init_message(request, COAP_TYPE_CON, COAP_DELETE, 0); + coap_set_header_uri_path(request, session_info.assigned_ep); + coap_send_request(&rd_request_state, &session_info.server_ep, request, + deregister_callback); + rd_state = DEREGISTER_SENT; + break; + case DEREGISTER_SENT: + break; + case DEREGISTER_FAILED: + break; + case DEREGISTERED: + break; + + default: + LOG_WARN("Unhandled state: %d\n", rd_state); + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_init(const char *ep) +{ + session_info.ep = ep; + /* default binding U = UDP, UQ = UDP Q-mode*/ + session_info.binding = "U"; + if(session_info.lifetime == 0) { + session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME; + } + 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); +} +/*---------------------------------------------------------------------------*/ +static void +check_periodic_observations(void) +{ +/* TODO */ +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-rd-client.h b/os/services/lwm2m/lwm2m-rd-client.h new file mode 100644 index 000000000..7fba7e0ae --- /dev/null +++ b/os/services/lwm2m/lwm2m-rd-client.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016-2018, SICS Swedish ICT 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 the Contiki OMA LWM2M Registration and Bootstrap + * Client. + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#ifndef LWM2M_RD_CLIENT_H_ +#define LWM2M_RD_CLIENT_H_ + +#define LWM2M_RD_CLIENT_BOOTSTRAPPED 1 +#define LWM2M_RD_CLIENT_REGISTERED 2 +#define LWM2M_RD_CLIENT_DEREGISTERED 3 +#define LWM2M_RD_CLIENT_DEREGISTER_FAILED 4 +#define LWM2M_RD_CLIENT_DISCONNECTED 5 + +#include "lwm2m-object.h" + +struct lwm2m_session_info; +typedef void (*session_callback_t)(struct lwm2m_session_info *session, int status); + +int lwm2m_rd_client_is_registered(void); +void lwm2m_rd_client_use_bootstrap_server(int use); +void lwm2m_rd_client_use_registration_server(int use); +void lwm2m_rd_client_register_with_server(const coap_endpoint_t *server); +void lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server); +uint16_t lwm2m_rd_client_get_lifetime(void); +void lwm2m_rd_client_set_lifetime(uint16_t lifetime); +/* Indicate that something in the object list have changed */ +void lwm2m_rd_client_set_update_rd(void); +/* Control if the object list should be automatically updated at updates of lifetime */ +void lwm2m_rd_client_set_automatic_update(int update); +/* trigger an immediate update */ +void lwm2m_rd_client_update_triggered(void); + +int lwm2m_rd_client_deregister(void); +void lwm2m_rd_client_init(const char *ep); + +void lwm2m_rd_client_set_session_callback(session_callback_t cb); + +#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 */ + +/*---------------------------------------------------------------------------*/ +/*- Server session-*Currently single session only*---------------------------*/ +/*---------------------------------------------------------------------------*/ +struct lwm2m_session_info { + const char *ep; + const char *binding; + char assigned_ep[LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN]; + uint16_t lifetime; + coap_endpoint_t bs_server_ep; + coap_endpoint_t server_ep; + uint8_t use_bootstrap; + uint8_t has_bs_server_info; + uint8_t use_registration; + uint8_t has_registration_server_info; + uint8_t registered; + uint8_t bootstrapped; /* bootstrap done */ + session_callback_t callback; +}; + +#endif /* LWM2M_RD_CLIENT_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index 953279b4d..5fe0c31cb 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -43,70 +43,411 @@ */ #include +#include +#include #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "lwm2m-server.h" +#include "lwm2m-security.h" +#include "coap-keystore.h" +#include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-security" +#define LOG_LEVEL LOG_LEVEL_LWM2M -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT -/* hoping that we do not get more than 64 bytes... */ -#define MAX_SIZE 64 +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); -static int32_t bs_arr[MAX_COUNT]; -static int32_t secmode_arr[MAX_COUNT]; -static int32_t sid_arr[MAX_COUNT]; +static lwm2m_object_instance_t *get_by_id(uint16_t instance_id, + lwm2m_status_t *status); -static char server_uri[MAX_COUNT][MAX_SIZE]; -static uint16_t su_len[MAX_COUNT]; -static char client_id[MAX_COUNT][MAX_SIZE]; -static uint16_t client_id_len[MAX_COUNT]; -static char server_id[MAX_COUNT][MAX_SIZE]; -static uint16_t server_id_len[MAX_COUNT]; -static char psk_key[MAX_COUNT][MAX_SIZE]; -static uint16_t psk_key_len[MAX_COUNT]; -static lwm2m_instance_t security_instances[MAX_COUNT]; +static const lwm2m_resource_id_t resources[] = { + LWM2M_SECURITY_SERVER_URI_ID, LWM2M_SECURITY_BOOTSTRAP_SERVER_ID, + LWM2M_SECURITY_MODE_ID, LWM2M_SECURITY_CLIENT_PKI_ID, + LWM2M_SECURITY_SERVER_PKI_ID, LWM2M_SECURITY_KEY_ID, + LWM2M_SECURITY_SHORT_SERVER_ID +}; -LWM2M_RESOURCES(security_resources, - LWM2M_RESOURCE_STRING_VAR_ARR(0, MAX_COUNT, MAX_SIZE, su_len, server_uri), - LWM2M_RESOURCE_INTEGER_VAR_ARR(1, MAX_COUNT, bs_arr), - LWM2M_RESOURCE_INTEGER_VAR_ARR(2, MAX_COUNT, secmode_arr), - LWM2M_RESOURCE_STRING_VAR_ARR(3, MAX_COUNT, MAX_SIZE, client_id_len, client_id), - LWM2M_RESOURCE_STRING_VAR_ARR(4, MAX_COUNT, MAX_SIZE, server_id_len, server_id), - /* TODO This should not be readable! */ - LWM2M_RESOURCE_STRING_VAR_ARR(5, MAX_COUNT, MAX_SIZE, psk_key_len, psk_key), - LWM2M_RESOURCE_INTEGER_VAR_ARR(10, MAX_COUNT, sid_arr) - ); -LWM2M_OBJECT(security, 0, security_instances); +LIST(instances_list); +static lwm2m_security_server_t instances[MAX_COUNT]; +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + int i; + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + /* An instance with this id is already registered */ + if(status) { + *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + return NULL; + } + + for(i = 0; i < MAX_COUNT; i++) { + if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + memset(&instances[i], 0, sizeof(instances[i])); + instances[i].instance.callback = lwm2m_callback; + instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID; + instances[i].instance.instance_id = instance_id; + instances[i].instance.resource_ids = resources; + instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + list_add(instances_list, &instances[i].instance); + + LOG_DBG("Create new security instance %u\n", instance_id); + return &instances[i].instance; + } + } + + if(status) { + *status = LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static int +delete_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* Remove all instances */ + while((instance = list_pop(instances_list)) != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + return 1; + } + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + list_remove(instances_list, instance); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_first(lwm2m_status_t *status) +{ + return list_head(instances_list); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) +{ + return instance == NULL ? NULL : instance->next; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_by_id(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + for(instance = list_head(instances_list); + instance != NULL; + instance = instance->next) { + if(instance->instance_id == instance_id) { + return instance; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + /* NOTE: the create operation will only create an instance and should + avoid reading out data */ + int32_t value; + int iv; + lwm2m_security_server_t *security; + security = (lwm2m_security_server_t *) object; + + if(ctx->operation == LWM2M_OP_WRITE) { + /* Handle the writes */ + switch(ctx->resource_id) { + case LWM2M_SECURITY_SERVER_URI_ID: + LOG_DBG("Writing security URI value: len: %"PRId16"\n", ctx->inbuf->size); + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->server_uri, LWM2M_SECURITY_URI_SIZE); + /* This is string... */ + security->server_uri_len = ctx->last_value_len; + break; + case LWM2M_SECURITY_BOOTSTRAP_SERVER_ID: + value = lwm2m_object_read_boolean(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &iv); + if(value > 0) { + LOG_DBG("Set Bootstrap: %d\n", iv); + security->bootstrap = (uint8_t) iv; + } else { + LOG_WARN("Failed to set bootstrap\n"); + } + break; + case LWM2M_SECURITY_MODE_ID: + { + int32_t v2; + value = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v2); + LOG_DBG("Writing security MODE value: %"PRId32" len: %d\n", v2, + (int)ctx->inbuf->size); + security->security_mode = v2; + } + break; + case LWM2M_SECURITY_CLIENT_PKI_ID: + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->public_key, LWM2M_SECURITY_KEY_SIZE); + security->public_key_len = ctx->last_value_len; + + LOG_DBG("Writing client PKI: len: %"PRIu16" '", ctx->last_value_len); + LOG_DBG_COAP_STRING((const char *)security->public_key, + ctx->last_value_len); + LOG_DBG_("'\n"); + break; + case LWM2M_SECURITY_KEY_ID: + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->secret_key, LWM2M_SECURITY_KEY_SIZE); + security->secret_key_len = ctx->last_value_len; + + LOG_DBG("Writing secret key: len: %"PRIu16" '", ctx->last_value_len); + LOG_DBG_COAP_STRING((const char *)security->secret_key, + ctx->last_value_len); + LOG_DBG_("'\n"); + + break; + } + } else if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_SECURITY_SERVER_URI_ID: + lwm2m_object_write_string(ctx, (const char *) security->server_uri, + security->server_uri_len); + break; + default: + return LWM2M_STATUS_ERROR; + } + } + return LWM2M_STATUS_OK; +} + +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_get_first(void) +{ + return list_head(instances_list); +} +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_get_next(lwm2m_security_server_t *last) +{ + return last == NULL ? NULL : (lwm2m_security_server_t *)last->instance.next; +} +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_add_server(uint16_t instance_id, + uint16_t server_id, + const uint8_t *server_uri, + uint8_t server_uri_len) +{ + lwm2m_security_server_t *server; + int i; + + if(server_uri_len > LWM2M_SECURITY_URI_SIZE) { + LOG_WARN("too long server URI: %u\n", server_uri_len); + return NULL; + } + + for(server = lwm2m_security_get_first(); + server != NULL; + server = lwm2m_security_get_next(server)) { + if(server->server_id == server_id) { + if(server->instance.instance_id != instance_id) { + LOG_WARN("wrong instance id\n"); + return NULL; + } + /* Correct server id and instance id */ + break; + } else if(server->instance.instance_id == instance_id) { + LOG_WARN("wrong server id\n"); + return NULL; + } + } + + if(server == NULL) { + for(i = 0; i < MAX_COUNT; i++) { + if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + memset(&instances[i], 0, sizeof(instances[i])); + instances[i].instance.callback = lwm2m_callback; + instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID; + instances[i].instance.instance_id = instance_id; + instances[i].instance.resource_ids = resources; + instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + list_add(instances_list, &instances[i].instance); + server = &instances[i]; + } + } + if(server == NULL) { + LOG_WARN("no space for more servers\n"); + return NULL; + } + } + + memcpy(server->server_uri, server_uri, server_uri_len); + server->server_uri_len = server_uri_len; + + return server; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_security_set_server_psk(lwm2m_security_server_t *server, + const uint8_t *identity, + uint8_t identity_len, + const uint8_t *key, + uint8_t key_len) +{ + if(server == NULL || identity == NULL || key == NULL) { + return 0; + } + if(identity_len > LWM2M_SECURITY_KEY_SIZE) { + LOG_WARN("too large identity: %u\n", identity_len); + return 0; + } + if(key_len > LWM2M_SECURITY_KEY_SIZE) { + LOG_WARN("too large identity: %u\n", key_len); + return 0; + } + memcpy(server->public_key, identity, identity_len); + server->public_key_len = identity_len; + memcpy(server->secret_key, key, key_len); + server->secret_key_len = key_len; + + server->security_mode = LWM2M_SECURITY_MODE_PSK; + + return 1; +} +/*---------------------------------------------------------------------------*/ +static const lwm2m_object_impl_t impl = { + .object_id = LWM2M_OBJECT_SECURITY_ID, + .get_first = get_first, + .get_next = get_next, + .get_by_id = get_by_id, + .create_instance = create_instance, + .delete_instance = delete_instance, +}; +static lwm2m_object_t reg_object = { + .impl = &impl, +}; +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M +static int +get_psk_info(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info) +{ + /* Find matching security object based on address */ + lwm2m_security_server_t *e; + coap_endpoint_t ep; + + if(info == NULL || address_info == NULL) { + return 0; + } + + for(e = lwm2m_security_get_first(); + e != NULL; + e = lwm2m_security_get_next(e)) { + if(e->server_uri_len == 0) { + continue; + } + if(e->security_mode != LWM2M_SECURITY_MODE_PSK) { + /* Only PSK supported for now */ + continue; + } + if(!coap_endpoint_parse((char *)e->server_uri, e->server_uri_len, &ep)) { + /* Failed to parse URI to endpoint */ + LOG_DBG("failed to parse server URI "); + LOG_DBG_COAP_STRING((char *)e->server_uri, e->server_uri_len); + LOG_DBG_("\n"); + continue; + } + if(!coap_endpoint_cmp(address_info, &ep)) { + /* Wrong server */ + LOG_DBG("wrong server "); + LOG_DBG_COAP_EP(address_info); + LOG_DBG_(" != "); + LOG_DBG_COAP_EP(&ep); + LOG_DBG_("\n"); + continue; + } + if(info->identity_len > 0 && info->identity != NULL) { + /* Searching for a specific identity */ + if(info->identity_len != e->public_key_len || + memcmp(info->identity, e->public_key, info->identity_len)) { + /* Identity not matching */ + LOG_DBG("identity not matching\n"); + continue; + } + } + /* Found security information for this server */ + LOG_DBG("found security match!\n"); + break; + } + + if(e == NULL) { + /* No matching security object found */ + return 0; + } + + if(info->identity == NULL || info->identity_len == 0) { + /* Identity requested */ + info->identity = e->public_key; + info->identity_len = e->public_key_len; + return 1; + } + + if(e->secret_key_len == 0) { + /* No secret key / password */ + return 0; + } + + info->key = e->secret_key; + info->key_len = e->secret_key_len; + return 1; +} +static const coap_keystore_t key_store = { + .coap_get_psk_info = get_psk_info +}; +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ +#endif /* WITH_DTLS */ /*---------------------------------------------------------------------------*/ void lwm2m_security_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE_UNUSED(0, security_resources); int i; - /* Initialize the instances */ - for(i = 0; i < MAX_COUNT; i++) { - security_instances[i] = template; - security_instances[i].id = i; - } + LOG_INFO("init\n"); - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle. - */ - PRINTF("*** Init lwm2m-security\n"); - lwm2m_engine_register_object(&security); + list_init(instances_list); + + for(i = 0; i < MAX_COUNT; i++) { + instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + if(lwm2m_engine_add_generic_object(®_object)) { + +#ifdef WITH_DTLS +#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M + /* Security object handler added - register keystore */ + coap_set_keystore(&key_store); + LOG_DBG("registered keystore\n"); +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ +#endif /* WITH_DTLS */ + + } else { + LOG_WARN("failed to register\n"); + } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-security.h b/os/services/lwm2m/lwm2m-security.h new file mode 100644 index 000000000..9fb3df78f --- /dev/null +++ b/os/services/lwm2m/lwm2m-security.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017, SICS Swedish ICT + * 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 + * @{ + * + */ +#ifndef LWM2M_SECURITY_H +#define LWM2M_SECURITY_H + +#define LWM2M_SECURITY_SERVER_URI_ID 0 +#define LWM2M_SECURITY_BOOTSTRAP_SERVER_ID 1 +#define LWM2M_SECURITY_MODE_ID 2 +#define LWM2M_SECURITY_CLIENT_PKI_ID 3 +#define LWM2M_SECURITY_SERVER_PKI_ID 4 +#define LWM2M_SECURITY_KEY_ID 5 +#define LWM2M_SECURITY_SHORT_SERVER_ID 10 + +/* Pre-shared key mode */ +#define LWM2M_SECURITY_MODE_PSK 0 +/* Raw Public Key mode */ +#define LWM2M_SECURITY_MODE_RPK 1 +/* Certificate mode */ +#define LWM2M_SECURITY_MODE_CERTIFICATE 2 +/* NoSec mode */ +#define LWM2M_SECURITY_MODE_NOSEC 3 + +#ifdef LWM2M_SECURITY_CONF_URI_SIZE +#define LWM2M_SECURITY_URI_SIZE LWM2M_SECURITY_CONF_URI_SIZE +#else /* LWM2M_SECURITY_CONF_URI_SIZE */ +#define LWM2M_SECURITY_URI_SIZE 64 +#endif /* LWM2M_SECURITY_CONF_URI_SIZE */ + +#ifdef LWM2M_SECURITY_CONF_KEY_SIZE +#define LWM2M_SECURITY_KEY_SIZE LWM2M_SECURITY_CONF_KEY_SIZE +#else /* LWM2M_SECURITY_CONF_KEY_SIZE */ +#define LWM2M_SECURITY_KEY_SIZE 32 +#endif /* LWM2M_SECURITY_CONF_KEY_SIZE */ + +typedef struct { + lwm2m_object_instance_t instance; + uint16_t server_id; + uint8_t bootstrap; + uint8_t security_mode; + uint8_t server_uri[LWM2M_SECURITY_URI_SIZE]; + uint8_t server_uri_len; + uint8_t public_key[LWM2M_SECURITY_KEY_SIZE]; + uint8_t public_key_len; + uint8_t secret_key[LWM2M_SECURITY_KEY_SIZE]; + uint8_t secret_key_len; + uint8_t server_public_key[LWM2M_SECURITY_KEY_SIZE]; + uint8_t server_public_key_len; +} lwm2m_security_server_t; + +lwm2m_security_server_t *lwm2m_security_get_first(void); +lwm2m_security_server_t *lwm2m_security_get_next(lwm2m_security_server_t *last); + +lwm2m_security_server_t *lwm2m_security_add_server(uint16_t instance_id, + uint16_t server_id, + const uint8_t *server_uri, + uint8_t server_uri_len); + +int lwm2m_security_set_server_psk(lwm2m_security_server_t *server, + const uint8_t *identity, + uint8_t identity_len, + const uint8_t *key, + uint8_t key_len); + +void lwm2m_security_init(void); + +#endif /* LWM2M_SECURITY_H */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-server.c b/os/services/lwm2m/lwm2m-server.c index 9de678682..67b2c45ba 100644 --- a/os/services/lwm2m/lwm2m-server.c +++ b/os/services/lwm2m/lwm2m-server.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -43,51 +43,253 @@ */ #include +#include "lib/list.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "lwm2m-server.h" +#include "lwm2m-rd-client.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-server" +#define LOG_LEVEL LOG_LEVEL_LWM2M -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT -static int32_t sid_arr[MAX_COUNT]; -static int32_t lifetime_arr[MAX_COUNT]; -static lwm2m_instance_t server_instances[MAX_COUNT]; +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); -LWM2M_RESOURCES(server_resources, - LWM2M_RESOURCE_INTEGER_VAR_ARR(0, MAX_COUNT, sid_arr), - LWM2M_RESOURCE_INTEGER_VAR_ARR(1, MAX_COUNT, lifetime_arr), - ); -LWM2M_OBJECT(server, 1, server_instances); +static lwm2m_object_instance_t *create_instance(uint16_t instance_id, + lwm2m_status_t *status); +static int delete_instance(uint16_t instance_id, lwm2m_status_t *status); +static lwm2m_object_instance_t *get_first(lwm2m_status_t *status); +static lwm2m_object_instance_t *get_next(lwm2m_object_instance_t *instance, + lwm2m_status_t *status); +static lwm2m_object_instance_t *get_by_id(uint16_t instance_id, + lwm2m_status_t *status); + +static const lwm2m_resource_id_t resources[] = { + RO(LWM2M_SERVER_SHORT_SERVER_ID), + RW(LWM2M_SERVER_LIFETIME_ID), + EX(LWM2M_SERVER_REG_UPDATE_TRIGGER_ID) +}; + +static const lwm2m_object_impl_t impl = { + .object_id = LWM2M_OBJECT_SERVER_ID, + .get_first = get_first, + .get_next = get_next, + .get_by_id = get_by_id, + .create_instance = create_instance, + .delete_instance = delete_instance, +}; +static lwm2m_object_t server_object = { + .impl = &impl, +}; + +LIST(server_list); +static lwm2m_server_t server_instances[MAX_COUNT]; +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + int i; + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + /* An instance with this id is already registered */ + if(status) { + *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + return NULL; + } + + for(i = 0; i < MAX_COUNT; i++) { + if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + server_instances[i].instance.callback = lwm2m_callback; + server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID; + server_instances[i].instance.instance_id = instance_id; + server_instances[i].instance.resource_ids = resources; + server_instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + server_instances[i].server_id = 0; + server_instances[i].lifetime = 0; + list_add(server_list, &server_instances[i].instance); + + if(status) { + *status = LWM2M_STATUS_OK; + } + + return &server_instances[i].instance; + } + } + + if(status) { + *status = LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static int +delete_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + + if(status) { + *status = LWM2M_STATUS_OK; + } + + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* Remove all instances */ + while((instance = list_pop(server_list)) != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + return 1; + } + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + list_remove(server_list, instance); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_first(lwm2m_status_t *status) +{ + if(status) { + *status = LWM2M_STATUS_OK; + } + return list_head(server_list); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) +{ + if(status) { + *status = LWM2M_STATUS_OK; + } + return instance == NULL ? NULL : instance->next; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_by_id(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + if(status) { + *status = LWM2M_STATUS_OK; + } + for(instance = list_head(server_list); + instance != NULL; + instance = instance->next) { + if(instance->instance_id == instance_id) { + return instance; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + int32_t value; + lwm2m_server_t *server; + server = (lwm2m_server_t *) object; + + if(ctx->operation == LWM2M_OP_WRITE) { + LOG_DBG("Write to: %d\n", ctx->resource_id); + switch(ctx->resource_id) { + case LWM2M_SERVER_LIFETIME_ID: + lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &value); + server->lifetime = value; + break; + } + } else if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_SERVER_SHORT_SERVER_ID: + lwm2m_object_write_int(ctx, server->server_id); + break; + case LWM2M_SERVER_LIFETIME_ID: + lwm2m_object_write_int(ctx, server->lifetime); + break; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + switch(ctx->resource_id) { + case LWM2M_SERVER_REG_UPDATE_TRIGGER_ID: + lwm2m_rd_client_update_triggered(); + break; + } + } else { + return LWM2M_STATUS_NOT_IMPLEMENTED; + } + + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +lwm2m_server_t * +lwm2m_server_add(uint16_t instance_id, uint16_t server_id, uint32_t lifetime) +{ + lwm2m_server_t *server; + int i; + + for(server = list_head(server_list); + server; + server = (lwm2m_server_t *)server->instance.next) { + if(server->server_id == server_id) { + /* Found a matching server */ + if(server->instance.instance_id != instance_id) { + /* Non-matching instance id */ + LOG_DBG("non-matching instance id for server %u\n", server_id); + return NULL; + } + server->lifetime = lifetime; + return server; + } else if(server->instance.instance_id == instance_id) { + /* Right instance but wrong server id */ + LOG_DBG("non-matching server id for instance %u\n", instance_id); + return NULL; + } + } + + for(i = 0; i < MAX_COUNT; i++) { + if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + server_instances[i].instance.callback = lwm2m_callback; + server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID; + server_instances[i].instance.instance_id = instance_id; + server_instances[i].instance.resource_ids = resources; + server_instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + server_instances[i].server_id = server_id; + server_instances[i].lifetime = lifetime; + list_add(server_list, &server_instances[i].instance); + + return &server_instances[i]; + } + } + + LOG_WARN("no space for more servers\n"); + + return NULL; +} /*---------------------------------------------------------------------------*/ void lwm2m_server_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE_UNUSED(0, server_resources); int i; - /* Initialize the instances */ - for(i = 0; i < MAX_COUNT; i++) { - server_instances[i] = template; - server_instances[i].id = i; - } + LOG_INFO("init\n"); - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle - */ - PRINTF("*** Init lwm2m-server\n"); - lwm2m_engine_register_object(&server); + list_init(server_list); + + for(i = 0; i < MAX_COUNT; i++) { + server_instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + lwm2m_engine_add_generic_object(&server_object); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-server.h b/os/services/lwm2m/lwm2m-server.h new file mode 100644 index 000000000..733b0889d --- /dev/null +++ b/os/services/lwm2m/lwm2m-server.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, SICS Swedish ICT + * 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 + * @{ + * + */ +#ifndef LWM2M_SERVER_H +#define LWM2M_SERVER_H + +#include "contiki.h" + +#define LWM2M_SERVER_SHORT_SERVER_ID 0 +#define LWM2M_SERVER_LIFETIME_ID 1 +#define LWM2M_SERVER_BINDING_ID 7 +#define LWM2M_SERVER_REG_UPDATE_TRIGGER_ID 8 + +#ifdef LWM2M_SERVER_CONF_MAX_COUNT +#define LWM2M_SERVER_MAX_COUNT LWM2M_SERVER_CONF_MAX_COUNT +#else +#define LWM2M_SERVER_MAX_COUNT 2 +#endif + +typedef struct { + lwm2m_object_instance_t instance; + uint16_t server_id; + uint32_t lifetime; +} lwm2m_server_t; + +lwm2m_server_t *lwm2m_server_add(uint16_t instance_id, + uint16_t server_id, + uint32_t lifetime); + +void lwm2m_server_init(void); + +#endif /* LWM2M_SERVER_H */ +/** @} */ diff --git a/os/services/lwm2m/oma-tlv-reader.c b/os/services/lwm2m/lwm2m-tlv-reader.c similarity index 74% rename from os/services/lwm2m/oma-tlv-reader.c rename to os/services/lwm2m/lwm2m-tlv-reader.c index 58e1dcc54..cbeed6bd2 100644 --- a/os/services/lwm2m/oma-tlv-reader.c +++ b/os/services/lwm2m/lwm2m-tlv-reader.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -43,30 +43,32 @@ */ #include "lwm2m-object.h" -#include "oma-tlv-reader.h" -#include "oma-tlv.h" +#include "lwm2m-tlv-reader.h" +#include "lwm2m-tlv.h" +#include /*---------------------------------------------------------------------------*/ static size_t -read_int(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - *value = oma_tlv_get_int32(&tlv); + *value = lwm2m_tlv_get_int32(&tlv); + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t stringlen) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { if(stringlen <= tlv.length) { /* The outbuffer can not contain the full string including ending zero */ @@ -74,37 +76,40 @@ read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, } memcpy(value, tlv.value, tlv.length); value[tlv.length] = '\0'; + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_float32fix(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - oma_tlv_float32_to_fix(&tlv, value, bits); + lwm2m_tlv_float32_to_fix(&tlv, value, bits); + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_boolean(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - *value = oma_tlv_get_int32(&tlv) != 0; + *value = lwm2m_tlv_get_int32(&tlv) != 0; + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ -const lwm2m_reader_t oma_tlv_reader = { +const lwm2m_reader_t lwm2m_tlv_reader = { read_int, read_string, read_float32fix, diff --git a/os/services/lwm2m/oma-tlv-reader.h b/os/services/lwm2m/lwm2m-tlv-reader.h similarity index 89% rename from os/services/lwm2m/oma-tlv-reader.h rename to os/services/lwm2m/lwm2m-tlv-reader.h index 7e6540c18..15db7024d 100644 --- a/os/services/lwm2m/oma-tlv-reader.h +++ b/os/services/lwm2m/lwm2m-tlv-reader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** @@ -39,12 +39,12 @@ * Niclas Finne */ -#ifndef OMA_TLV_READER_H_ -#define OMA_TLV_READER_H_ +#ifndef LWM2M_TLV_READER_H_ +#define LWM2M_TLV_READER_H_ #include "lwm2m-object.h" -extern const lwm2m_reader_t oma_tlv_reader; +extern const lwm2m_reader_t lwm2m_tlv_reader; -#endif /* OMA_TLV_READER_H_ */ +#endif /* LWM2M_TLV_READER_H_ */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-tlv-writer.c b/os/services/lwm2m/lwm2m-tlv-writer.c new file mode 100644 index 000000000..6df16447e --- /dev/null +++ b/os/services/lwm2m/lwm2m-tlv-writer.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2015-2018, Yanzi Networks 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 TLV writer + * \author + * Joakim Eriksson + * Niclas Finne + */ + +#include "lwm2m-object.h" +#include "lwm2m-tlv.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-tlv-writer" +#define LOG_LEVEL LOG_LEVEL_NONE + +/*---------------------------------------------------------------------------*/ +static size_t +init_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_int_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int32_t value) +{ + uint8_t type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + uint16_t id = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + ctx->resource_instance_id : ctx->resource_id; + return lwm2m_tlv_write_int32(type, id, value, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_boolean_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int value) +{ + return write_int_tlv(ctx, outbuf, outlen, value != 0 ? 1 : 0); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_float32fix_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, + size_t outlen, int32_t value, int bits) +{ + uint8_t type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + uint16_t id = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + ctx->resource_instance_id : ctx->resource_id; + return lwm2m_tlv_write_float32(type, id, value, bits, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_string_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + const char *value, size_t stringlen) +{ + lwm2m_tlv_t tlv; + tlv.type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + tlv.value = (uint8_t *) value; + tlv.length = (uint32_t) stringlen; + tlv.id = ctx->resource_id; + return lwm2m_tlv_write(&tlv, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_opaque_header(lwm2m_context_t *ctx, size_t payloadsize) +{ + lwm2m_tlv_t tlv; + tlv.type = LWM2M_TLV_TYPE_RESOURCE; + tlv.value = (uint8_t *) NULL; + tlv.length = (uint32_t) payloadsize; + tlv.id = ctx->resource_id; + return lwm2m_tlv_write(&tlv, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len); +} +/*---------------------------------------------------------------------------*/ +static size_t +enter_sub(lwm2m_context_t *ctx) +{ + /* set some flags in state */ + lwm2m_tlv_t tlv; + int len = 0; + LOG_DBG("Enter sub-resource rsc=%d mark:%d\n", ctx->resource_id, ctx->outbuf->len); + ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; + tlv.type = LWM2M_TLV_TYPE_MULTI_RESOURCE; + tlv.length = 8; /* create an 8-bit TLV */ + tlv.value = NULL; + tlv.id = ctx->resource_id; + len = lwm2m_tlv_write(&tlv, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len); + /* store position for deciding where to re-write the TLV when we + know the length - NOTE: either this or memmov of buffer later... */ + ctx->out_mark_pos_ri = ctx->outbuf->len; + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +exit_sub(lwm2m_context_t *ctx) +{ + /* clear out state info */ + int pos = 2; /* this is the lenght pos */ + int len; + ctx->writer_flags &= ~WRITER_RESOURCE_INSTANCE; + + if(ctx->resource_id > 0xff) { + pos++; + } + len = ctx->outbuf->len - ctx->out_mark_pos_ri; + + LOG_DBG("Exit sub-resource rsc=%d mark:%d len=%d\n", ctx->resource_id, + ctx->out_mark_pos_ri, len); + + /* update the lenght byte... Assume TLV header is pos + 1 bytes. */ + ctx->outbuf->buffer[pos + ctx->out_mark_pos_ri] = len - (pos + 1); + return 0; +} +/*---------------------------------------------------------------------------*/ +const lwm2m_writer_t lwm2m_tlv_writer = { + init_write, + end_write, + enter_sub, + exit_sub, + write_int_tlv, + write_string_tlv, + write_float32fix_tlv, + write_boolean_tlv, + write_opaque_header +}; +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/oma-tlv-writer.h b/os/services/lwm2m/lwm2m-tlv-writer.h similarity index 89% rename from os/services/lwm2m/oma-tlv-writer.h rename to os/services/lwm2m/lwm2m-tlv-writer.h index 6ae5edd14..681ccf280 100644 --- a/os/services/lwm2m/oma-tlv-writer.h +++ b/os/services/lwm2m/lwm2m-tlv-writer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** @@ -39,12 +39,12 @@ * Niclas Finne */ -#ifndef OMA_TLV_WRITER_H_ -#define OMA_TLV_WRITER_H_ +#ifndef LWM2M_TLV_WRITER_H_ +#define LWM2M_TLV_WRITER_H_ #include "lwm2m-object.h" -extern const lwm2m_writer_t oma_tlv_writer; +extern const lwm2m_writer_t lwm2m_tlv_writer; -#endif /* OMA_TLV_WRITER_H_ */ +#endif /* LWM2M_TLV_WRITER_H_ */ /** @} */ diff --git a/os/services/lwm2m/oma-tlv.c b/os/services/lwm2m/lwm2m-tlv.c similarity index 67% rename from os/services/lwm2m/oma-tlv.c rename to os/services/lwm2m/lwm2m-tlv.c index c07df31cc..2bda7f8bb 100644 --- a/os/services/lwm2m/oma-tlv.c +++ b/os/services/lwm2m/lwm2m-tlv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -44,19 +44,16 @@ #include #include -#include "oma-tlv.h" +#include "lwm2m-tlv.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-tlv" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ static inline uint8_t -get_len_type(const oma_tlv_t *tlv) +get_len_type(const lwm2m_tlv_t *tlv) { if(tlv->length < 8) { return 0; @@ -70,7 +67,7 @@ get_len_type(const oma_tlv_t *tlv) } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len) +lwm2m_tlv_read(lwm2m_tlv_t *tlv, const uint8_t *buffer, size_t len) { uint8_t len_type; uint8_t len_pos = 1; @@ -104,7 +101,7 @@ oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len) } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_get_size(const oma_tlv_t *tlv) +lwm2m_tlv_get_size(const lwm2m_tlv_t *tlv) { size_t size; /* first hdr + len size */ @@ -117,8 +114,11 @@ oma_tlv_get_size(const oma_tlv_t *tlv) return size; } /*---------------------------------------------------------------------------*/ +/* If the tlv->value is NULL - only the header will be generated - useful for + * large strings or opaque streaming (block transfer) + */ size_t -oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) +lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t buffersize) { int pos; uint8_t len_type; @@ -127,8 +127,12 @@ oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) len_type = get_len_type(tlv); pos = 1 + len_type; /* ensure that we do not write too much */ - if(len < tlv->length + pos) { - PRINTF("OMA-TLV: Could not write the TLV - buffer overflow.\n"); + if(tlv->value != NULL && buffersize < tlv->length + pos) { + LOG_WARN("Could not write the TLV - buffer overflow.\n"); + return 0; + } + + if(buffersize < pos + 2) { return 0; } @@ -156,61 +160,75 @@ oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) } /* finally add the value */ - memcpy(&buffer[pos], tlv->value, tlv->length); - - if(DEBUG) { - int i; - PRINTF("TLV:"); - for(i = 0; i < pos + tlv->length; i++) { - PRINTF("%02x", buffer[i]); - } - PRINTF("\n"); + if(tlv->value != NULL && tlv->length > 0) { + memcpy(&buffer[pos], tlv->value, tlv->length); } - return pos + tlv->length; + if(LOG_DBG_ENABLED) { + int i; + LOG_DBG("TLV: "); + for(i = 0; i < pos + ((tlv->value != NULL) ? tlv->length : 0); i++) { + LOG_DBG_("%02x", buffer[i]); + } + LOG_DBG_("\n"); + } + + return pos + ((tlv->value != NULL) ? tlv->length : 0); } /*---------------------------------------------------------------------------*/ int32_t -oma_tlv_get_int32(const oma_tlv_t *tlv) +lwm2m_tlv_get_int32(const lwm2m_tlv_t *tlv) { int i; int32_t value = 0; - /* will probably need to handle MSB as a sign bit? */ + for(i = 0; i < tlv->length; i++) { value = (value << 8) | tlv->value[i]; } + + /* Ensure that we set all the bits above what we read in */ + if(tlv->value[0] & 0x80) { + while(i < 4) { + value = value | (0xff << (i * 8)); + i++; + } + } + return value; } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_write_int32(int16_t id, int32_t value, uint8_t *buffer, size_t len) +lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, size_t len) { - oma_tlv_t tlv; - size_t tlvlen = 0; + lwm2m_tlv_t tlv; uint8_t buf[4]; int i; - PRINTF("Exporting int32 %d %ld ", id, (long)value); + int v; + int last_bit; + LOG_DBG("Exporting int32 %d %"PRId32" ", id, value); - buf[3] = value & 0xff; - value = value >> 8; - for(i = 1; value > 0 && i < 4; i++) { + v = value < 0 ? -1 : 0; + i = 0; + do { buf[3 - i] = value & 0xff; + /* check if the last MSB indicates that we need another byte */ + last_bit = (v == 0 && (value & 0x80) > 0) || (v == -1 && (value & 0x80) == 0); value = value >> 8; - } - tlvlen = i; + i++; + } while((value != v || last_bit) && i < 4); /* export INT as TLV */ - PRINTF("len: %zu\n", tlvlen); - tlv.type = OMA_TLV_TYPE_RESOURCE; - tlv.length = tlvlen; - tlv.value = &buf[3 - (tlvlen - 1)]; + LOG_DBG("len: %d\n", i); + tlv.type = type; + tlv.length = i; + tlv.value = &buf[3 - (i - 1)]; tlv.id = id; - return oma_tlv_write(&tlv, buffer, len); + return lwm2m_tlv_write(&tlv, buffer, len); } /*---------------------------------------------------------------------------*/ /* convert fixpoint 32-bit to a IEEE Float in the byte array*/ size_t -oma_tlv_write_float32(int16_t id, int32_t value, int bits, +lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len) { int i; @@ -218,7 +236,7 @@ oma_tlv_write_float32(int16_t id, int32_t value, int bits, int32_t val = 0; int32_t v; uint8_t b[4]; - oma_tlv_t tlv; + lwm2m_tlv_t tlv; v = value; if(v < 0) { @@ -234,33 +252,38 @@ oma_tlv_write_float32(int16_t id, int32_t value, int bits, e++; } - PRINTF("Sign: %d, Fraction: %06lx 0b", value < 0, (long)val); + LOG_DBG("Sign: %d, Fraction: %06"PRIx32" 0b", value < 0, val); for(i = 0; i < 23; i++) { - PRINTF("%d", (int)((val >> (22 - i)) & 1)); + LOG_DBG_("%"PRId32"", ((val >> (22 - i)) & 1)); } - PRINTF("\nExp:%d\n", e); + LOG_DBG_("\nExp:%d\n", e); /* convert to the thing we should have */ e = e - bits + 127; + if(value == 0) { + e = 0; + } + /* is this the right byte order? */ b[0] = (value < 0 ? 0x80 : 0) | (e >> 1); b[1] = ((e & 1) << 7) | ((val >> 16) & 0x7f); b[2] = (val >> 8) & 0xff; b[3] = val & 0xff; + LOG_DBG("B=%02x%02x%02x%02x\n", b[0], b[1], b[2], b[3]); /* construct the TLV */ - tlv.type = OMA_TLV_TYPE_RESOURCE; + tlv.type = type; tlv.length = 4; tlv.value = b; tlv.id = id; - return oma_tlv_write(&tlv, buffer, len); + return lwm2m_tlv_write(&tlv, buffer, len); } /*---------------------------------------------------------------------------*/ /* convert float to fixpoint */ size_t -oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) +lwm2m_tlv_float32_to_fix(const lwm2m_tlv_t *tlv, int32_t *value, int bits) { /* TLV needs to be 4 bytes */ int e, i; @@ -269,19 +292,19 @@ oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) e = ((tlv->value[0] << 1) & 0xff) | (tlv->value[1] >> 7); val = (((long)tlv->value[1] & 0x7f) << 16) | (tlv->value[2] << 8) | tlv->value[3]; - PRINTF("Sign: %d, Fraction: %06lx 0b", val < 0, (long)val); + LOG_DBG("Sign: %d, Fraction: %06"PRIx32" 0b", val < 0, val); for(i = 0; i < 23; i++) { - PRINTF("%d", (int)((val >> (22 - i)) & 1)); + LOG_DBG_("%"PRId32"", ((val >> (22 - i)) & 1)); } - PRINTF("\nExp:%d => %d\n", e, e - 127); + LOG_DBG("\nExp:%d => %d\n", e, e - 127); e = e - 127 + bits; /* e corresponds to the number of times we need to roll the number */ - PRINTF("Actual e=%d\n", e); + LOG_DBG("Actual e=%d\n", e); e = e - 23; - PRINTF("E after sub %d\n", e); + LOG_DBG("E after sub %d\n", e); val = val | 1L << 23; if(e > 0) { val = val << e; @@ -294,3 +317,20 @@ oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) } /*---------------------------------------------------------------------------*/ /** @} */ + +#if 0 +int main(int argc, char *argv[]) +{ + lwm2m_tlv_t tlv; + uint8_t data[24]; + /* Make -1 */ + tlv.length = 2; + tlv.value = data; + data[0] = 0x00; + data[1] = 0x80, + + printf("TLV:%d\n", lwm2m_tlv_get_int32(&tlv)); + + printf("Len: %d\n", lwm2m_tlv_write_int32(0, 1, -0x88987f, data, 24)); +} +#endif diff --git a/os/services/lwm2m/oma-tlv.h b/os/services/lwm2m/lwm2m-tlv.h similarity index 65% rename from os/services/lwm2m/oma-tlv.h rename to os/services/lwm2m/lwm2m-tlv.h index 1bd5fd94a..2766263fa 100644 --- a/os/services/lwm2m/oma-tlv.h +++ b/os/services/lwm2m/lwm2m-tlv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** @@ -39,51 +39,52 @@ * Niclas Finne */ -#ifndef OAM_TLV_H_ -#define OAM_TLV_H_ +#ifndef LWM2M_TLV_H_ +#define LWM2M_TLV_H_ -#include "contiki.h" +#include +#include enum { - OMA_TLV_TYPE_OBJECT_INSTANCE = 0, - OMA_TLV_TYPE_RESOURCE_INSTANCE = 1, - OMA_TLV_TYPE_MULTI_RESOURCE = 2, - OMA_TLV_TYPE_RESOURCE = 3 + LWM2M_TLV_TYPE_OBJECT_INSTANCE = 0, + LWM2M_TLV_TYPE_RESOURCE_INSTANCE = 1, + LWM2M_TLV_TYPE_MULTI_RESOURCE = 2, + LWM2M_TLV_TYPE_RESOURCE = 3 }; -typedef uint8_t oma_tlv_type_t; +typedef uint8_t lwm2m_tlv_type_t; typedef enum { - OMA_TLV_LEN_TYPE_NO_LEN = 0, - OMA_TLV_LEN_TYPE_8BIT_LEN = 1, - OMA_TLV_LEN_TYPE_16BIT_LEN = 2, - OMA_TLV_LEN_TYPE_24BIT_LEN = 3 -} oma_tlv_len_type_t; + LWM2M_TLV_LEN_TYPE_NO_LEN = 0, + LWM2M_TLV_LEN_TYPE_8BIT_LEN = 1, + LWM2M_TLV_LEN_TYPE_16BIT_LEN = 2, + LWM2M_TLV_LEN_TYPE_24BIT_LEN = 3 +} lwm2m_tlv_len_type_t; typedef struct { - oma_tlv_type_t type; + lwm2m_tlv_type_t type; uint16_t id; /* can be 8-bit or 16-bit when serialized */ uint32_t length; const uint8_t *value; -} oma_tlv_t; +} lwm2m_tlv_t; -size_t oma_tlv_get_size(const oma_tlv_t *tlv); +size_t lwm2m_tlv_get_size(const lwm2m_tlv_t *tlv); /* read a TLV from the buffer */ -size_t oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len); +size_t lwm2m_tlv_read(lwm2m_tlv_t *tlv, const uint8_t *buffer, size_t len); /* write a TLV to the buffer */ -size_t oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t len); -int32_t oma_tlv_get_int32(const oma_tlv_t *tlv); +int32_t lwm2m_tlv_get_int32(const lwm2m_tlv_t *tlv); /* write a int as a TLV to the buffer */ -size_t oma_tlv_write_int32(int16_t id, int32_t value, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, size_t len); /* write a float converted from fixpoint as a TLV to the buffer */ -size_t oma_tlv_write_float32(int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len); /* convert TLV with float32 to fixpoint */ -size_t oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits); +size_t lwm2m_tlv_float32_to_fix(const lwm2m_tlv_t *tlv, int32_t *value, int bits); -#endif /* OAM_TLV_H_ */ +#endif /* LWM2M_TLV_H_ */ /** @} */ diff --git a/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c b/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c index fbafa4654..723b9e847 100644 --- a/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c +++ b/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c @@ -44,10 +44,7 @@ #include "orchestra.h" #include "net/ipv6/uip-ds6-route.h" #include "net/packetbuf.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" /* * The body of this rule should be compiled only when "nbr_routes" is available, diff --git a/os/services/orchestra/orchestra.c b/os/services/orchestra/orchestra.c index 3ea78ca96..8b9929c03 100644 --- a/os/services/orchestra/orchestra.c +++ b/os/services/orchestra/orchestra.c @@ -40,10 +40,12 @@ #include "orchestra.h" #include "net/packetbuf.h" #include "net/ipv6/uip-icmp6.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" diff --git a/os/services/rpl-border-router/embedded/border-router-embedded.c b/os/services/rpl-border-router/embedded/border-router-embedded.c index 8ec4bd49c..884f60a97 100644 --- a/os/services/rpl-border-router/embedded/border-router-embedded.c +++ b/os/services/rpl-border-router/embedded/border-router-embedded.c @@ -36,7 +36,7 @@ */ #include "contiki.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "dev/button-sensor.h" #include "dev/slip.h" #include "rpl-border-router.h" @@ -88,11 +88,7 @@ PROCESS_THREAD(border_router_process, ev, data) PROCESS_YIELD(); if(ev == sensors_event && data == &button_sensor) { LOG_INFO("Initiating global repair\n"); -#if UIP_CONF_IPV6_RPL_LITE - rpl_global_repair(); -#else - rpl_repair_root(RPL_DEFAULT_INSTANCE); -#endif + NETSTACK_ROUTING.global_repair("Button press"); } } diff --git a/os/services/rpl-border-router/native/Makefile.native b/os/services/rpl-border-router/native/Makefile.native index 62f7221a0..a225e1666 100644 --- a/os/services/rpl-border-router/native/Makefile.native +++ b/os/services/rpl-border-router/native/Makefile.native @@ -1,8 +1,13 @@ MODULES += os/services/slip-cmd +MODULES += os/services/shell MAKE_MAC = MAKE_MAC_OTHER MAKE_NET = MAKE_NET_IPV6 + PREFIX ?= fd00::1/64 connect-router: border-router.native sudo ./border-router.native $(PREFIX) + +connect-router-cooja: border-router.native + sudo ./border-router.native -a localhost $(PREFIX) diff --git a/os/services/rpl-border-router/native/border-router-cmds.c b/os/services/rpl-border-router/native/border-router-cmds.c index 75788a920..9d0e2eb9f 100644 --- a/os/services/rpl-border-router/native/border-router-cmds.c +++ b/os/services/rpl-border-router/native/border-router-cmds.c @@ -40,9 +40,11 @@ #include "border-router.h" #include "border-router-cmds.h" #include "dev/serial-line.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "net/ipv6/uiplib.h" #include +#include "shell.h" +#include #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" @@ -54,6 +56,56 @@ void nbr_print_stat(void); /*---------------------------------------------------------------------------*/ PROCESS(border_router_cmd_process, "Border router cmd process"); +/*---------------------------------------------------------------------------*/ +static const uint8_t * +hextoi(const uint8_t *buf, int len, int *v) +{ + *v = 0; + for(; len > 0; len--, buf++) { + if(*buf >= '0' && *buf <= '9') { + *v = (*v << 4) + ((*buf - '0') & 0xf); + } else if(*buf >= 'a' && *buf <= 'f') { + *v = (*v << 4) + ((*buf - 'a' + 10) & 0xf); + } else if(*buf >= 'A' && *buf <= 'F') { + *v = (*v << 4) + ((*buf - 'A' + 10) & 0xf); + } else { + break; + } + } + return buf; +} +/*---------------------------------------------------------------------------*/ +static const uint8_t * +dectoi(const uint8_t *buf, int len, int *v) +{ + int negative = 0; + *v = 0; + if(len <= 0) { + return buf; + } + if(*buf == '$') { + return hextoi(buf + 1, len - 1, v); + } + if(*buf == '0' && *(buf + 1) == 'x' && len > 2) { + return hextoi(buf + 2, len - 2, v); + } + if(*buf == '-') { + negative = 1; + buf++; + } + for(; len > 0; len--, buf++) { + if(*buf < '0' || *buf > '9') { + break; + } + *v = (*v * 10) + ((*buf - '0') & 0xf); + } + if(negative) { + *v = - *v; + } + return buf; +} +/*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ /* TODO: the below code needs some way of identifying from where the command */ /* comes. In this case it can be from stdin or from SLIP. */ @@ -64,35 +116,60 @@ border_router_cmd_handler(const uint8_t *data, int len) /* handle global repair, etc here */ if(data[0] == '!') { PRINTF("Got configuration message of type %c\n", data[1]); - if(data[1] == 'G' && command_context == CMD_CONTEXT_STDIO) { - /* This is supposed to be from stdin */ - printf("Performing Global Repair...\n"); -#if UIP_CONF_IPV6_RPL_LITE - rpl_global_repair(); -#else - rpl_repair_root(RPL_DEFAULT_INSTANCE); -#endif - return 1; - } else if(data[1] == 'M' && command_context == CMD_CONTEXT_RADIO) { + if(command_context == CMD_CONTEXT_STDIO) { + switch(data[1]) { + case 'G': + /* This is supposed to be from stdin */ + printf("Performing Global Repair...\n"); + NETSTACK_ROUTING.global_repair("Command"); + return 1; + case 'C': { + /* send on a set-param thing! */ + uint8_t set_param[] = {'!', 'V', 0, RADIO_PARAM_CHANNEL, 0, 0 }; + int channel = -1; + dectoi(&data[2], len - 2, &channel); + if(channel >= 0) { + set_param[5] = channel & 0xff; + write_to_slip(set_param, sizeof(set_param)); + } + return 1; + } + case 'P': { + /* send on a set-param thing! */ + uint8_t set_param[] = {'!', 'V', 0, RADIO_PARAM_PAN_ID, 0, 0 }; + int pan_id; + dectoi(&data[2], len - 2, &pan_id); + set_param[4] = (pan_id >> 8) & 0xff; + set_param[5] = pan_id & 0xff; + write_to_slip(set_param, sizeof(set_param)); + return 1; + } + default: + return 0; + } + } else if(command_context == CMD_CONTEXT_RADIO) { /* We need to know that this is from the slip-radio here. */ - PRINTF("Setting MAC address\n"); - border_router_set_mac(&data[2]); - return 1; - } else if(data[1] == 'C' && command_context == CMD_CONTEXT_RADIO) { - /* We need to know that this is from the slip-radio here. */ - printf("Channel is:%d\n", data[2]); - return 1; - } else if(data[1] == 'R' && command_context == CMD_CONTEXT_RADIO) { - /* We need to know that this is from the slip-radio here. */ - PRINTF("Packet data report for sid:%d st:%d tx:%d\n", - data[2], data[3], data[4]); - packet_sent(data[2], data[3], data[4]); - return 1; - } else if(data[1] == 'D' && command_context == CMD_CONTEXT_RADIO) { - /* We need to know that this is from the slip-radio here... */ - PRINTF("Sensor data received\n"); - border_router_set_sensors((const char *)&data[2], len - 2); - return 1; + switch(data[1]) { + case 'M': + PRINTF("Setting MAC address\n"); + border_router_set_mac(&data[2]); + return 1; + case 'V': + if(data[3] == RADIO_PARAM_CHANNEL) { + printf("Channel is %d\n", data[5]); + } + if(data[3] == RADIO_PARAM_PAN_ID) { + printf("PAN_ID is 0x%04x\n", (data[4] << 8) + data[5]); + } + return 1; + case 'R': + PRINTF("Packet data report for sid:%d st:%d tx:%d\n", + data[2], data[3], data[4]); + packet_sent(data[2], data[3], data[4]); + return 1; + default: + return 0; + } } } else if(data[0] == '?') { PRINTF("Got request message of type %c\n", data[1]); @@ -110,8 +187,14 @@ border_router_cmd_handler(const uint8_t *data, int len) cmd_send(buf, 18); return 1; } else if(data[1] == 'C' && command_context == CMD_CONTEXT_STDIO) { - /* send on! */ - write_to_slip(data, len); + /* send on a set-param thing! */ + uint8_t set_param[] = {'?', 'V', 0, RADIO_PARAM_CHANNEL}; + write_to_slip(set_param, sizeof(set_param)); + return 1; + } else if(data[1] == 'P' && command_context == CMD_CONTEXT_STDIO) { + /* send on a set-param thing! */ + uint8_t set_param[] = {'?', 'V', 0, RADIO_PARAM_PAN_ID}; + write_to_slip(set_param, sizeof(set_param)); return 1; } else if(data[1] == 'S') { border_router_print_stat(); @@ -132,17 +215,33 @@ border_router_cmd_output(const uint8_t *data, int data_len) printf("\n"); } /*---------------------------------------------------------------------------*/ +static void +serial_shell_output(const char *str) +{ + printf("%s", str); +} +/*---------------------------------------------------------------------------*/ + PROCESS_THREAD(border_router_cmd_process, ev, data) { + static struct pt shell_input_pt; PROCESS_BEGIN(); PRINTF("Started br-cmd process\n"); + + shell_init(); + while(1) { PROCESS_YIELD(); if(ev == serial_line_event_message && data != NULL) { - PRINTF("Got serial data!!! %s of len: %d\n", + PRINTF("Got serial data!!! %s of len: %lu\n", (char *)data, strlen((char *)data)); command_context = CMD_CONTEXT_STDIO; - cmd_input(data, strlen((char *)data)); + if(cmd_input(data, strlen((char *)data))) { + /* Commnand executed - all is fine */ + } else { + /* did not find command - run shell and see if ... */ + PROCESS_PT_SPAWN(&shell_input_pt, shell_input(&shell_input_pt, serial_shell_output, data)); + } } } PROCESS_END(); diff --git a/os/services/rpl-border-router/native/border-router-mac.c b/os/services/rpl-border-router/native/border-router-mac.c index 7b002183e..bcfb829b7 100644 --- a/os/services/rpl-border-router/native/border-router-mac.c +++ b/os/services/rpl-border-router/native/border-router-mac.c @@ -63,7 +63,7 @@ struct tx_callback { struct packetbuf_attr attrs[PACKETBUF_NUM_ATTRS]; struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS]; }; - +/*---------------------------------------------------------------------------*/ static struct tx_callback callbacks[MAX_CALLBACKS]; /*---------------------------------------------------------------------------*/ void @@ -111,6 +111,10 @@ send_packet(mac_callback_t sent, void *ptr) /* ack or not ? */ packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); + /* Will make it send only DATA packets... for now */ + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); + /* printf("Sending packet of type: %s \n", get_frame_type(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE))); */ + if(NETSTACK_FRAMER.create() < 0) { /* Failed to allocate space for headers */ PRINTF("br-rdc: send failed, too large header\n"); diff --git a/os/services/rpl-border-router/native/border-router-native.c b/os/services/rpl-border-router/native/border-router-native.c index 07bd322c6..3da0ef000 100644 --- a/os/services/rpl-border-router/native/border-router-native.c +++ b/os/services/rpl-border-router/native/border-router-native.c @@ -40,7 +40,8 @@ #include "contiki.h" #include "contiki-net.h" -#include "rpl.h" + +#include "net/routing/routing.h" #include "rpl-border-router.h" #include "cmd.h" #include "border-router.h" @@ -51,18 +52,11 @@ #include -#define MAX_SENSORS 4 - extern long slip_sent; extern long slip_received; static uint8_t mac_set; -static uint8_t sensor_count = 0; - -/* allocate MAX_SENSORS char[32]'s */ -static char sensors[MAX_SENSORS][32]; - extern int contiki_argc; extern char **contiki_argv; extern const char *slip_config_ipaddr; @@ -88,7 +82,7 @@ border_router_set_mac(const uint8_t *data) add them back again - a bit messy... ?*/ PROCESS_CONTEXT_BEGIN(&tcpip_process); uip_ds6_init(); - rpl_init(); + NETSTACK_ROUTING.init(); PROCESS_CONTEXT_END(&tcpip_process); mac_set = 1; @@ -101,30 +95,6 @@ border_router_print_stat() printf("bytes sent over SLIP: %ld\n", slip_sent); } /*---------------------------------------------------------------------------*/ -/* Format: ;;...;*/ -/* this function just cut at ; and store in the sensor array */ -void -border_router_set_sensors(const char *data, int len) -{ - int i; - int last_pos = 0; - int sc = 0; - for(i = 0; i < len; i++) { - if(data[i] == ';') { - sensors[sc][i - last_pos] = 0; - memcpy(sensors[sc++], &data[last_pos], i - last_pos); - last_pos = i + 1; /* skip the ';' */ - } - if(sc == MAX_SENSORS) { - sensor_count = sc; - return; - } - } - sensors[sc][len - last_pos] = 0; - memcpy(sensors[sc++], &data[last_pos], len - last_pos); - sensor_count = sc; -} -/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { static struct etimer et; diff --git a/os/services/rpl-border-router/rpl-border-router.c b/os/services/rpl-border-router/rpl-border-router.c index 59426d7f9..f07a41fdd 100644 --- a/os/services/rpl-border-router/rpl-border-router.c +++ b/os/services/rpl-border-router/rpl-border-router.c @@ -31,8 +31,8 @@ */ #include "contiki.h" +#include "net/routing/routing.h" #include "rpl-border-router.h" -#include "rpl-dag-root.h" /* Log configuration */ #include "sys/log.h" @@ -64,8 +64,8 @@ void set_prefix_64(uip_ipaddr_t *prefix_64) { prefix_set = 1; - rpl_dag_root_init(prefix_64, NULL); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_set_prefix(prefix_64, NULL); + NETSTACK_ROUTING.root_start(); } /*---------------------------------------------------------------------------*/ void diff --git a/os/services/shell/shell-commands.c b/os/services/shell/shell-commands.c index 7c14e1ef5..5e19a0dc8 100644 --- a/os/services/shell/shell-commands.c +++ b/os/services/shell/shell-commands.c @@ -58,14 +58,16 @@ #include "net/mac/tsch/tsch-log.h" #include "net/mac/tsch/tsch-private.h" #endif /* MAC_CONF_WITH_TSCH */ -#if UIP_CONF_IPV6_RPL_LITE -#include "net/rpl-lite/rpl.h" -#elif UIP_CONF_IPV6_RPL_CLASSIC -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif +#include "net/routing/routing.h" #include "net/mac/llsec802154.h" +/* For RPL-specific commands */ +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif + #include #define PING_TIMEOUT (5 * CLOCK_SECOND) @@ -98,7 +100,7 @@ ds6_nbr_state_to_str(uint8_t state) return "Unknown"; } } -#if UIP_CONF_IPV6_RPL_LITE +#if ROUTING_CONF_RPL_LITE /*---------------------------------------------------------------------------*/ static const char * rpl_state_to_str(enum rpl_dag_state state) @@ -146,7 +148,51 @@ rpl_ocp_to_str(int ocp) return "Unknown"; } } -#endif /* UIP_CONF_IPV6_RPL_LITE */ +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(cmd_rpl_status(struct pt *pt, shell_output_func output, char *args)) +{ + PT_BEGIN(pt); + + SHELL_OUTPUT(output, "RPL status:\n"); + if(!curr_instance.used) { + SHELL_OUTPUT(output, "-- Instance: None\n"); + } else { + SHELL_OUTPUT(output, "-- Instance: %u\n", curr_instance.instance_id); + if(NETSTACK_ROUTING.node_is_root()) { + SHELL_OUTPUT(output, "-- DAG root\n"); + } else { + SHELL_OUTPUT(output, "-- DAG node\n"); + } + SHELL_OUTPUT(output, "-- DAG: "); + shell_output_6addr(output, &curr_instance.dag.dag_id); + SHELL_OUTPUT(output, ", version %u\n", curr_instance.dag.version); + SHELL_OUTPUT(output, "-- Prefix: "); + shell_output_6addr(output, &curr_instance.dag.prefix_info.prefix); + SHELL_OUTPUT(output, "/%u\n", curr_instance.dag.prefix_info.length); + SHELL_OUTPUT(output, "-- MOP: %s\n", rpl_mop_to_str(curr_instance.mop)); + SHELL_OUTPUT(output, "-- OF: %s\n", rpl_ocp_to_str(curr_instance.of->ocp)); + SHELL_OUTPUT(output, "-- Hop rank increment: %u\n", curr_instance.min_hoprankinc); + SHELL_OUTPUT(output, "-- Default lifetime: %lu seconds\n", RPL_LIFETIME(curr_instance.default_lifetime)); + + SHELL_OUTPUT(output, "-- State: %s\n", rpl_state_to_str(curr_instance.dag.state)); + SHELL_OUTPUT(output, "-- Preferred parent: "); + shell_output_6addr(output, rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent)); + SHELL_OUTPUT(output, "\n"); + SHELL_OUTPUT(output, "-- Rank: %u\n", curr_instance.dag.rank); + SHELL_OUTPUT(output, "-- Lowest rank: %u (%u)\n", curr_instance.dag.lowest_rank, curr_instance.max_rankinc); + SHELL_OUTPUT(output, "-- DTSN out: %u\n", curr_instance.dtsn_out); + SHELL_OUTPUT(output, "-- DAO sequence: last sent %u, last acked %u\n", + curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_acked_seqno); + SHELL_OUTPUT(output, "-- Trickle timer: current %u, min %u, max %u, redundancy %u\n", + curr_instance.dag.dio_intcurrent, curr_instance.dio_intmin, + curr_instance.dio_intmin + curr_instance.dio_intdoubl, curr_instance.dio_redundancy); + + } + + PT_END(pt); +} +#endif /* ROUTING_CONF_RPL_LITE */ /*---------------------------------------------------------------------------*/ static void echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen) @@ -288,7 +334,6 @@ PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, char *args)) PT_END(pt); } -#if UIP_CONF_IPV6_RPL_LITE /*---------------------------------------------------------------------------*/ static PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) @@ -325,19 +370,19 @@ PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) } if(is_on) { - if(!rpl_dag_root_is_root()) { + if(!NETSTACK_ROUTING.node_is_root()) { SHELL_OUTPUT(output, "Setting as DAG root with prefix "); shell_output_6addr(output, &prefix); SHELL_OUTPUT(output, "/64\n"); - rpl_dag_root_init(&prefix, NULL); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_set_prefix(&prefix, NULL); + NETSTACK_ROUTING.root_start(); } else { SHELL_OUTPUT(output, "Node is already a DAG root\n"); } } else { - if(rpl_dag_root_is_root()) { + if(NETSTACK_ROUTING.node_is_root()) { SHELL_OUTPUT(output, "Setting as non-root node: leaving DAG\n"); - rpl_dag_poison_and_leave(); + NETSTACK_ROUTING.leave_network(); } else { SHELL_OUTPUT(output, "Node is not a DAG root\n"); } @@ -347,56 +392,12 @@ PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) } /*---------------------------------------------------------------------------*/ static -PT_THREAD(cmd_rpl_status(struct pt *pt, shell_output_func output, char *args)) -{ - PT_BEGIN(pt); - - SHELL_OUTPUT(output, "RPL status:\n"); - if(!curr_instance.used) { - SHELL_OUTPUT(output, "-- Instance: None\n"); - } else { - SHELL_OUTPUT(output, "-- Instance: %u\n", curr_instance.instance_id); - if(rpl_dag_root_is_root()) { - SHELL_OUTPUT(output, "-- DAG root\n"); - } else { - SHELL_OUTPUT(output, "-- DAG node\n"); - } - SHELL_OUTPUT(output, "-- DAG: "); - shell_output_6addr(output, &curr_instance.dag.dag_id); - SHELL_OUTPUT(output, ", version %u\n", curr_instance.dag.version); - SHELL_OUTPUT(output, "-- Prefix: "); - shell_output_6addr(output, &curr_instance.dag.prefix_info.prefix); - SHELL_OUTPUT(output, "/%u\n", curr_instance.dag.prefix_info.length); - SHELL_OUTPUT(output, "-- MOP: %s\n", rpl_mop_to_str(curr_instance.mop)); - SHELL_OUTPUT(output, "-- OF: %s\n", rpl_ocp_to_str(curr_instance.of->ocp)); - SHELL_OUTPUT(output, "-- Hop rank increment: %u\n", curr_instance.min_hoprankinc); - SHELL_OUTPUT(output, "-- Default lifetime: %lu seconds\n", RPL_LIFETIME(curr_instance.default_lifetime)); - - SHELL_OUTPUT(output, "-- State: %s\n", rpl_state_to_str(curr_instance.dag.state)); - SHELL_OUTPUT(output, "-- Preferred parent: "); - shell_output_6addr(output, rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent)); - SHELL_OUTPUT(output, "\n"); - SHELL_OUTPUT(output, "-- Rank: %u\n", curr_instance.dag.rank); - SHELL_OUTPUT(output, "-- Lowest rank: %u (%u)\n", curr_instance.dag.lowest_rank, curr_instance.max_rankinc); - SHELL_OUTPUT(output, "-- DTSN out: %u\n", curr_instance.dtsn_out); - SHELL_OUTPUT(output, "-- DAO sequence: last sent %u, last acked %u\n", - curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_acked_seqno); - SHELL_OUTPUT(output, "-- Trickle timer: current %u, min %u, max %u, redundancy %u\n", - curr_instance.dag.dio_intcurrent, curr_instance.dio_intmin, - curr_instance.dio_intmin + curr_instance.dio_intdoubl, curr_instance.dio_redundancy); - - } - - PT_END(pt); -} -/*---------------------------------------------------------------------------*/ -static PT_THREAD(cmd_rpl_global_repair(struct pt *pt, shell_output_func output, char *args)) { PT_BEGIN(pt); - SHELL_OUTPUT(output, "Triggering RPL global repair\n") - rpl_global_repair(); + SHELL_OUTPUT(output, "Triggering routing global repair\n") + NETSTACK_ROUTING.global_repair("Shell"); PT_END(pt); } @@ -406,12 +407,11 @@ PT_THREAD(cmd_rpl_local_repair(struct pt *pt, shell_output_func output, char *ar { PT_BEGIN(pt); - SHELL_OUTPUT(output, "Triggering RPL local repair\n"); - rpl_local_repair("Shell"); + SHELL_OUTPUT(output, "Triggering routing local repair\n"); + NETSTACK_ROUTING.local_repair("Shell"); PT_END(pt); } -#endif /* UIP_CONF_IPV6_RPL_LITE */ /*---------------------------------------------------------------------------*/ static PT_THREAD(cmd_ipaddr(struct pt *pt, shell_output_func output, char *args)) @@ -551,12 +551,6 @@ static PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) { uip_ds6_defrt_t *default_route; -#if RPL_WITH_NON_STORING - rpl_ns_node_t *link; -#endif /* RPL_WITH_NON_STORING */ -#if RPL_WITH_STORING - uip_ds6_route_t *route; -#endif /* RPL_WITH_STORING */ PT_BEGIN(pt); @@ -575,16 +569,17 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) SHELL_OUTPUT(output, "-- None\n"); } -#if RPL_WITH_NON_STORING - if(rpl_ns_num_nodes() > 0) { +#if UIP_CONF_IPV6_RPL + if(uip_sr_num_nodes() > 0) { + uip_sr_node_t *link; /* Our routing links */ - SHELL_OUTPUT(output, "Routing links (%u in total):\n", rpl_ns_num_nodes()); - link = rpl_ns_node_head(); + SHELL_OUTPUT(output, "Routing links (%u in total):\n", uip_sr_num_nodes()); + link = uip_sr_node_head(); while(link != NULL) { uip_ipaddr_t child_ipaddr; uip_ipaddr_t parent_ipaddr; - rpl_ns_get_node_global_addr(&child_ipaddr, link); - rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent); + NETSTACK_ROUTING.get_sr_node_ipaddr(&child_ipaddr, link); + NETSTACK_ROUTING.get_sr_node_ipaddr(&parent_ipaddr, link->parent); SHELL_OUTPUT(output, "-- "); shell_output_6addr(output, &child_ipaddr); if(link->parent == NULL) { @@ -594,20 +589,21 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) SHELL_OUTPUT(output, " to "); shell_output_6addr(output, &parent_ipaddr); } - if(link->lifetime != RPL_ROUTE_INFINITE_LIFETIME) { + if(link->lifetime != UIP_SR_INFINITE_LIFETIME) { SHELL_OUTPUT(output, " (lifetime: %lu seconds)\n", (unsigned long)link->lifetime); } else { SHELL_OUTPUT(output, " (lifetime: infinite)\n"); } - link = rpl_ns_node_next(link); + link = uip_sr_node_next(link); } } else { SHELL_OUTPUT(output, "No routing links\n"); } -#endif /* RPL_WITH_NON_STORING */ +#endif /* UIP_CONF_IPV6_RPL */ -#if RPL_WITH_STORING +#if (UIP_MAX_ROUTES != 0) if(uip_ds6_route_num_routes() > 0) { + uip_ds6_route_t *route; /* Our routing entries */ SHELL_OUTPUT(output, "Routing entries (%u in total):\n", uip_ds6_route_num_routes()); route = uip_ds6_route_head(); @@ -616,7 +612,7 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) shell_output_6addr(output, &route->ipaddr); SHELL_OUTPUT(output, " via "); shell_output_6addr(output, uip_ds6_route_nexthop(route)); - if((unsigned long)route->state.lifetime != RPL_ROUTE_INFINITE_LIFETIME) { + if((unsigned long)route->state.lifetime != 0xFFFFFFFF) { SHELL_OUTPUT(output, " (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); } else { SHELL_OUTPUT(output, " (lifetime: infinite)\n"); @@ -626,7 +622,7 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) } else { SHELL_OUTPUT(output, "No routing entries\n"); } -#endif /* RPL_WITH_STORING */ +#endif /* (UIP_MAX_ROUTES != 0) */ PT_END(pt); } @@ -712,11 +708,6 @@ shell_commands_init(void) /* Set up Ping Reply callback */ uip_icmp6_echo_reply_callback_add(&echo_reply_notification, echo_reply_handler); - /* Start with soft log level 0 so as to minimize interference with shell */ - log_set_level("all", LOG_LEVEL_NONE); -#if MAC_CONF_WITH_TSCH && TSCH_LOG_PER_SLOT - tsch_log_stop(); -#endif /* MAC_CONF_WITH_TSCH && TSCH_LOG_PER_SLOT */ } /*---------------------------------------------------------------------------*/ struct shell_command_t shell_commands[] = { @@ -726,12 +717,14 @@ struct shell_command_t shell_commands[] = { { "ip-nbr", cmd_ip_neighbors, "'> ip-nbr': Shows all IPv6 neighbors" }, { "log", cmd_log, "'> log module level': Sets log level (0--4) for a given module (or \"all\"). For module \"mac\", level 4 also enables per-slot logging." }, { "ping", cmd_ping, "'> ping addr': Pings the IPv6 address 'addr'" }, -#if UIP_CONF_IPV6_RPL_LITE +#if UIP_CONF_IPV6_RPL { "rpl-set-root", cmd_rpl_set_root, "'> rpl-set-root 0/1 [prefix]': Sets node as root (1) or not (0). A /64 prefix can be optionally specified." }, - { "rpl-status", cmd_rpl_status, "'> rpl-status': Shows a summary of the current RPL state" }, { "rpl-local-repair", cmd_rpl_local_repair, "'> rpl-local-repair': Triggers a RPL local repair" }, { "rpl-global-repair", cmd_rpl_global_repair, "'> rpl-global-repair': Triggers a RPL global repair" }, -#endif /* UIP_CONF_IPV6_RPL_LITE */ +#endif /* UIP_CONF_IPV6_RPL */ +#if ROUTING_CONF_RPL_LITE + { "rpl-status", cmd_rpl_status, "'> rpl-status': Shows a summary of the current RPL state" }, +#endif /* ROUTING_CONF_RPL_LITE */ { "routes", cmd_routes, "'> routes': Shows the route entries" }, #if MAC_CONF_WITH_TSCH { "tsch-set-coordinator", cmd_tsch_set_coordinator, "'> tsch-set-coordinator 0/1 [0/1]': Sets node as coordinator (1) or not (0). Second, optional parameter: enable (1) or disable (0) security." }, diff --git a/os/services/slip-cmd/cmd.c b/os/services/slip-cmd/cmd.c index a2853efd2..c821fe77c 100644 --- a/os/services/slip-cmd/cmd.c +++ b/os/services/slip-cmd/cmd.c @@ -48,19 +48,18 @@ void CMD_OUTPUT(const uint8_t *data, int data_len); extern const cmd_handler_t cmd_handlers[]; /*---------------------------------------------------------------------------*/ -void +int cmd_input(const uint8_t *data, int data_len) { int i; for(i = 0; cmd_handlers[i] != NULL; i++) { if(cmd_handlers[i](data, data_len)) { /* Command has been handled */ - return; + return 1; } } - /* Unknown command */ - cmd_send((uint8_t *)"EUnknown command", 16); + return 0; } /*---------------------------------------------------------------------------*/ void diff --git a/os/services/slip-cmd/cmd.h b/os/services/slip-cmd/cmd.h index d363ac933..c3282b536 100644 --- a/os/services/slip-cmd/cmd.h +++ b/os/services/slip-cmd/cmd.h @@ -47,7 +47,7 @@ typedef int (* cmd_handler_t)(const uint8_t *data, int len); #define CMD_HANDLERS(...) \ const cmd_handler_t cmd_handlers[] = {__VA_ARGS__, NULL} -void cmd_input(const uint8_t *data, int data_len); +int cmd_input(const uint8_t *data, int data_len); void cmd_send(const uint8_t *data, int data_len); #endif /* CMD_H_ */ diff --git a/os/storage/antelope/aql-lexer.c b/os/storage/antelope/aql-lexer.c index cad604efb..4bdefecf2 100644 --- a/os/storage/antelope/aql-lexer.c +++ b/os/storage/antelope/aql-lexer.c @@ -42,6 +42,7 @@ #include #include #include +#include struct keyword { char *string; diff --git a/os/storage/antelope/index.c b/os/storage/antelope/index.c index 5c96bf459..7e05d0738 100644 --- a/os/storage/antelope/index.c +++ b/os/storage/antelope/index.c @@ -29,7 +29,7 @@ /** * \file - * This component forwards index calls using the generic index + * This component forwards index calls using the generic index * API to specific implementations. * \author * Nicolas Tsiftes @@ -241,7 +241,7 @@ index_delete(index_t *index, attribute_value_t *value) } db_result_t -index_get_iterator(index_iterator_t *iterator, index_t *index, +index_get_iterator(index_iterator_t *iterator, index_t *index, attribute_value_t *min_value, attribute_value_t *max_value) { @@ -266,15 +266,15 @@ index_get_iterator(index_iterator_t *iterator, index_t *index, range = (unsigned long)max - min; if(range > 0) { /* - * Index structures that do not have a natural ability to handle + * Index structures that do not have a natural ability to handle * range queries (e.g., a hash index) can nevertheless emulate them. * - * The range query emulation attempts to look up the key for each - * value in the search range. If the search range is sparse, this + * The range query emulation attempts to look up the key for each + * value in the search range. If the search range is sparse, this * iteration will incur a considerable overhead per found key. * - * Hence, the emulation is preferable when an external module wants - * to iterate over a narrow range of keys, for which the total + * Hence, the emulation is preferable when an external module wants + * to iterate over a narrow range of keys, for which the total * search cost is smaller than that of an iteration over all tuples * in the relation. */ @@ -294,7 +294,7 @@ index_get_iterator(index_iterator_t *iterator, index_t *index, iterator->max_value = *max_value; iterator->next_item_no = 0; - PRINTF("DB: Acquired an index iterator for %s.%s over the range (%ld,%ld)\n", + PRINTF("DB: Acquired an index iterator for %s.%s over the range (%ld,%ld)\n", index->rel->name, index->attr->name, min_value->u.long_value, max_value->u.long_value); @@ -380,7 +380,7 @@ PROCESS_THREAD(db_indexer, ev, data) PRINTF("DB: Loading the index for %s.%s...\n", index->rel->name, index->attr->name); - /* Project the values of the indexed attribute from all tuples in + /* Project the values of the indexed attribute from all tuples in the relation, and insert them into the index again. */ if(DB_ERROR(db_query(&handle, "SELECT %s FROM %s;", index->attr->name, index->rel->name))) { index->flags |= INDEX_LOAD_ERROR; diff --git a/os/storage/antelope/index.h b/os/storage/antelope/index.h index de7b28b36..6c9863e8f 100644 --- a/os/storage/antelope/index.h +++ b/os/storage/antelope/index.h @@ -105,7 +105,7 @@ db_result_t index_load(relation_t *, attribute_t *); db_result_t index_release(index_t *); db_result_t index_insert(index_t *, attribute_value_t *, tuple_id_t); db_result_t index_delete(index_t *, attribute_value_t *); -db_result_t index_get_iterator(index_iterator_t *, index_t *, +db_result_t index_get_iterator(index_iterator_t *, index_t *, attribute_value_t *, attribute_value_t *); tuple_id_t index_get_next(index_iterator_t *); int index_exists(attribute_t *); diff --git a/os/storage/cfs/cfs-coffee.c b/os/storage/cfs/cfs-coffee.c index 75cbf730e..53c7eca53 100644 --- a/os/storage/cfs/cfs-coffee.c +++ b/os/storage/cfs/cfs-coffee.c @@ -1094,7 +1094,7 @@ cfs_read(int fd, void *buf, unsigned size) fdp = &coffee_fd_set[fd]; file = fdp->file; - + if(fdp->io_flags & CFS_COFFEE_IO_ENSURE_READ_LENGTH) { while(fdp->offset + size > file->end) { ((char *)buf)[--size] = '\0'; diff --git a/os/storage/cfs/cfs.h b/os/storage/cfs/cfs.h index 3e2452c61..4851f562a 100644 --- a/os/storage/cfs/cfs.h +++ b/os/storage/cfs/cfs.h @@ -166,7 +166,7 @@ struct cfs_dirent { * \sa cfs_close() */ #ifndef cfs_open -CCIF int cfs_open(const char *name, int flags); +int cfs_open(const char *name, int flags); #endif /** @@ -177,7 +177,7 @@ CCIF int cfs_open(const char *name, int flags); * opened with cfs_open(). */ #ifndef cfs_close -CCIF void cfs_close(int fd); +void cfs_close(int fd); #endif /** @@ -192,7 +192,7 @@ CCIF void cfs_close(int fd); * cfs_open() and the CFS_READ flag. */ #ifndef cfs_read -CCIF int cfs_read(int fd, void *buf, unsigned int len); +int cfs_read(int fd, void *buf, unsigned int len); #endif /** @@ -207,7 +207,7 @@ CCIF int cfs_read(int fd, void *buf, unsigned int len); * cfs_open() and the CFS_WRITE flag. */ #ifndef cfs_write -CCIF int cfs_write(int fd, const void *buf, unsigned int len); +int cfs_write(int fd, const void *buf, unsigned int len); #endif /** @@ -228,7 +228,7 @@ CCIF int cfs_write(int fd, const void *buf, unsigned int len); * \sa CFS_SEEK_SET */ #ifndef cfs_seek -CCIF cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence); +cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence); #endif /** @@ -238,7 +238,7 @@ CCIF cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence); * \return -1 If the file could not be removed or if it doesn't exist. */ #ifndef cfs_remove -CCIF int cfs_remove(const char *name); +int cfs_remove(const char *name); #endif /** @@ -251,7 +251,7 @@ CCIF int cfs_remove(const char *name); * \sa cfs_closedir() */ #ifndef cfs_opendir -CCIF int cfs_opendir(struct cfs_dir *dirp, const char *name); +int cfs_opendir(struct cfs_dir *dirp, const char *name); #endif /** @@ -265,7 +265,7 @@ CCIF int cfs_opendir(struct cfs_dir *dirp, const char *name); * \sa cfs_closedir() */ #ifndef cfs_readdir -CCIF int cfs_readdir(struct cfs_dir *dirp, struct cfs_dirent *dirent); +int cfs_readdir(struct cfs_dir *dirp, struct cfs_dirent *dirent); #endif /** @@ -276,7 +276,7 @@ CCIF int cfs_readdir(struct cfs_dir *dirp, struct cfs_dirent *dirent); * \sa cfs_readdir() */ #ifndef cfs_closedir -CCIF void cfs_closedir(struct cfs_dir *dirp); +void cfs_closedir(struct cfs_dir *dirp); #endif #endif /* CFS_H_ */ diff --git a/os/sys/autostart.h b/os/sys/autostart.h index 8a671b363..dcf91c4ef 100644 --- a/os/sys/autostart.h +++ b/os/sys/autostart.h @@ -50,7 +50,7 @@ struct process * const autostart_processes[] = {__VA_ARGS__, NULL} #error "C compiler must support __VA_ARGS__ macro" #endif -CLIF extern struct process * const autostart_processes[]; +extern struct process * const autostart_processes[]; void autostart_start(struct process * const processes[]); void autostart_exit(struct process * const processes[]); diff --git a/os/sys/clock.h b/os/sys/clock.h index 3aa25b22c..161527d47 100644 --- a/os/sys/clock.h +++ b/os/sys/clock.h @@ -98,7 +98,7 @@ void clock_init(void); * * \return The current clock time, measured in system ticks. */ -CCIF clock_time_t clock_time(void); +clock_time_t clock_time(void); /** * Get the current value of the platform seconds. @@ -108,7 +108,7 @@ CCIF clock_time_t clock_time(void); * * \return The value. */ -CCIF unsigned long clock_seconds(void); +unsigned long clock_seconds(void); /** * Set the value of the platform seconds. diff --git a/os/sys/ctimer.c b/os/sys/ctimer.c index 66698a8e6..1d628677b 100644 --- a/os/sys/ctimer.c +++ b/os/sys/ctimer.c @@ -106,7 +106,7 @@ void ctimer_set_with_process(struct ctimer *c, clock_time_t t, void (*f)(void *), void *ptr, struct process *p) { - PRINTF("ctimer_set %p %u\n", c, (unsigned)t); + PRINTF("ctimer_set %p %lu\n", c, (unsigned long)t); c->p = p; c->f = f; c->ptr = ptr; diff --git a/os/sys/etimer.h b/os/sys/etimer.h index 59f665d10..02ad5df11 100644 --- a/os/sys/etimer.h +++ b/os/sys/etimer.h @@ -94,7 +94,7 @@ struct etimer { * process that called the etimer_set() function. * */ -CCIF void etimer_set(struct etimer *et, clock_time_t interval); +void etimer_set(struct etimer *et, clock_time_t interval); /** * \brief Reset an event timer with the same interval as was @@ -111,7 +111,7 @@ CCIF void etimer_set(struct etimer *et, clock_time_t interval); * * \sa etimer_restart() */ -CCIF void etimer_reset(struct etimer *et); +void etimer_reset(struct etimer *et); /** * \brief Reset an event timer with a new interval. @@ -192,7 +192,7 @@ clock_time_t etimer_start_time(struct etimer *et); * This function tests if an event timer has expired and * returns true or false depending on its status. */ -CCIF int etimer_expired(struct etimer *et); +int etimer_expired(struct etimer *et); /** * \brief Stop a pending event timer. diff --git a/os/sys/log-conf.h b/os/sys/log-conf.h index d52765c31..24cf21f71 100644 --- a/os/sys/log-conf.h +++ b/os/sys/log-conf.h @@ -133,6 +133,14 @@ #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_NONE #endif /* LOG_CONF_LEVEL_6TOP */ +#ifndef LOG_CONF_LEVEL_COAP +#define LOG_CONF_LEVEL_COAP LOG_LEVEL_NONE +#endif /* LOG_CONF_LEVEL_COAP */ + +#ifndef LOG_CONF_LEVEL_LWM2M +#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_NONE +#endif /* LOG_CONF_LEVEL_LWM2M */ + #ifndef LOG_CONF_LEVEL_MAIN #define LOG_CONF_LEVEL_MAIN LOG_LEVEL_INFO #endif /* LOG_CONF_LEVEL_MAIN */ diff --git a/os/sys/log.c b/os/sys/log.c index d4b21639d..90709ec5f 100644 --- a/os/sys/log.c +++ b/os/sys/log.c @@ -59,6 +59,8 @@ int curr_log_level_nullnet = LOG_CONF_LEVEL_NULLNET; int curr_log_level_mac = LOG_CONF_LEVEL_MAC; int curr_log_level_framer = LOG_CONF_LEVEL_FRAMER; int curr_log_level_6top = LOG_CONF_LEVEL_6TOP; +int curr_log_level_coap = LOG_CONF_LEVEL_COAP; +int curr_log_level_lwm2m = LOG_CONF_LEVEL_LWM2M; int curr_log_level_main = LOG_CONF_LEVEL_MAIN; struct log_module all_modules[] = { @@ -70,6 +72,8 @@ struct log_module all_modules[] = { {"mac", &curr_log_level_mac, LOG_CONF_LEVEL_MAC}, {"framer", &curr_log_level_framer, LOG_CONF_LEVEL_FRAMER}, {"6top", &curr_log_level_6top, LOG_CONF_LEVEL_6TOP}, + {"coap", &curr_log_level_coap, LOG_CONF_LEVEL_COAP}, + {"lwm2m", &curr_log_level_lwm2m, LOG_CONF_LEVEL_LWM2M}, {"main", &curr_log_level_main, LOG_CONF_LEVEL_MAIN}, {NULL, NULL, 0}, }; diff --git a/os/sys/log.h b/os/sys/log.h index b0624bbc7..e27a3007e 100644 --- a/os/sys/log.h +++ b/os/sys/log.h @@ -81,6 +81,8 @@ extern int curr_log_level_nullnet; extern int curr_log_level_mac; extern int curr_log_level_framer; extern int curr_log_level_6top; +extern int curr_log_level_coap; +extern int curr_log_level_lwm2m; extern int curr_log_level_main; extern struct log_module all_modules[]; @@ -93,6 +95,8 @@ extern struct log_module all_modules[]; #define LOG_LEVEL_MAC MIN((LOG_CONF_LEVEL_MAC), curr_log_level_mac) #define LOG_LEVEL_FRAMER MIN((LOG_CONF_LEVEL_FRAMER), curr_log_level_framer) #define LOG_LEVEL_6TOP MIN((LOG_CONF_LEVEL_6TOP), curr_log_level_6top) +#define LOG_LEVEL_COAP MIN((LOG_CONF_LEVEL_COAP), curr_log_level_coap) +#define LOG_LEVEL_LWM2M MIN((LOG_CONF_LEVEL_LWM2M), curr_log_level_lwm2m) #define LOG_LEVEL_MAIN MIN((LOG_CONF_LEVEL_MAIN), curr_log_level_main) /* Main log function */ @@ -141,31 +145,40 @@ extern struct log_module all_modules[]; } while (0) /* More compact versions of LOG macros */ +#define LOG_PRINT(...) LOG(1, 0, "PRI", __VA_ARGS__) #define LOG_ERR(...) LOG(1, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) #define LOG_WARN(...) LOG(1, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) #define LOG_INFO(...) LOG(1, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) #define LOG_DBG(...) LOG(1, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) +#define LOG_PRINT_(...) LOG(0, 0, "PRI", __VA_ARGS__) #define LOG_ERR_(...) LOG(0, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) #define LOG_WARN_(...) LOG(0, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) #define LOG_INFO_(...) LOG(0, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) #define LOG_DBG_(...) LOG(0, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) +#define LOG_PRINT_LLADDR(...) LOG_LLADDR(0, __VA_ARGS__) #define LOG_ERR_LLADDR(...) LOG_LLADDR(LOG_LEVEL_ERR, __VA_ARGS__) #define LOG_WARN_LLADDR(...) LOG_LLADDR(LOG_LEVEL_WARN, __VA_ARGS__) #define LOG_INFO_LLADDR(...) LOG_LLADDR(LOG_LEVEL_INFO, __VA_ARGS__) #define LOG_DBG_LLADDR(...) LOG_LLADDR(LOG_LEVEL_DBG, __VA_ARGS__) +#define LOG_PRINT_6ADDR(...) LOG_6ADDR(0, __VA_ARGS__) #define LOG_ERR_6ADDR(...) LOG_6ADDR(LOG_LEVEL_ERR, __VA_ARGS__) #define LOG_WARN_6ADDR(...) LOG_6ADDR(LOG_LEVEL_WARN, __VA_ARGS__) #define LOG_INFO_6ADDR(...) LOG_6ADDR(LOG_LEVEL_INFO, __VA_ARGS__) #define LOG_DBG_6ADDR(...) LOG_6ADDR(LOG_LEVEL_DBG, __VA_ARGS__) -/* For testing log level */ -#define LOG_ERR_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_ERR) -#define LOG_WARN_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_WARN) -#define LOG_INFO_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_INFO) -#define LOG_DBG_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_DBG) +/* For checking log level. + As this builds on curr_log_level variables, this should not be used + in pre-processor macros. Use in a C 'if' statement instead, e.g.: + if(LOG_INFO_ENABLED) { ... } + Note that most compilers will still be able to strip the code out + for low enough log levels configurations. */ +#define LOG_ERR_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_ERR) +#define LOG_WARN_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_WARN) +#define LOG_INFO_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_INFO) +#define LOG_DBG_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_DBG) #if NETSTACK_CONF_WITH_IPV6 diff --git a/os/sys/process.h b/os/sys/process.h index bd206b6e7..5cffdb526 100644 --- a/os/sys/process.h +++ b/os/sys/process.h @@ -339,7 +339,7 @@ struct process { * process * */ -CCIF void process_start(struct process *p, process_data_t data); +void process_start(struct process *p, process_data_t data); /** * Post an asynchronous event. @@ -362,7 +362,7 @@ CCIF void process_start(struct process *p, process_data_t data); * \retval PROCESS_ERR_FULL The event queue was full and the event could * not be posted. */ -CCIF int process_post(struct process *p, process_event_t ev, process_data_t data); +int process_post(struct process *p, process_event_t ev, process_data_t data); /** * Post a synchronous event to a process. @@ -374,8 +374,8 @@ CCIF int process_post(struct process *p, process_event_t ev, process_data_t data * \param data A pointer to additional data that is posted together * with the event. */ -CCIF void process_post_synch(struct process *p, - process_event_t ev, process_data_t data); +void process_post_synch(struct process *p, + process_event_t ev, process_data_t data); /** * \brief Cause a process to exit @@ -387,7 +387,7 @@ CCIF void process_post_synch(struct process *p, * * \sa PROCESS_CURRENT() */ -CCIF void process_exit(struct process *p); +void process_exit(struct process *p); /** @@ -400,7 +400,7 @@ CCIF void process_exit(struct process *p); * \hideinitializer */ #define PROCESS_CURRENT() process_current -CCIF extern struct process *process_current; +extern struct process *process_current; /** * Switch context to another process @@ -450,7 +450,7 @@ process_current = p * \note There currently is no way to deallocate an allocated event * number. */ -CCIF process_event_t process_alloc_event(void); +process_event_t process_alloc_event(void); /** @} */ @@ -467,7 +467,7 @@ CCIF process_event_t process_alloc_event(void); * * \param p A pointer to the process' process structure. */ -CCIF void process_poll(struct process *p); +void process_poll(struct process *p); /** @} */ @@ -509,7 +509,7 @@ int process_run(void); * \retval Non-zero if the process is running. * \retval Zero if the process is not running. */ -CCIF int process_is_running(struct process *p); +int process_is_running(struct process *p); /** * Number of events waiting to be processed. @@ -521,7 +521,7 @@ int process_nevents(void); /** @} */ -CCIF extern struct process *process_list; +extern struct process *process_list; #define PROCESS_LIST() process_list diff --git a/os/sys/timer.h b/os/sys/timer.h index b05963e47..54abcb3c2 100644 --- a/os/sys/timer.h +++ b/os/sys/timer.h @@ -84,10 +84,10 @@ struct timer { clock_time_t interval; }; -CCIF void timer_set(struct timer *t, clock_time_t interval); +void timer_set(struct timer *t, clock_time_t interval); void timer_reset(struct timer *t); void timer_restart(struct timer *t); -CCIF int timer_expired(struct timer *t); +int timer_expired(struct timer *t); clock_time_t timer_remaining(struct timer *t); diff --git a/tests/01-compile-base/Makefile b/tests/01-compile-base/Makefile index 78efc6411..d043c9d6e 100644 --- a/tests/01-compile-base/Makefile +++ b/tests/01-compile-base/Makefile @@ -4,6 +4,7 @@ TOOLSDIR=../../tools EXAMPLES = \ hello-world/native \ hello-world/native:MAKE_NET=MAKE_NET_NULLNET \ +hello-world/native:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \ hello-world/sky \ storage/eeprom-test/native \ multicast/sky \ @@ -12,6 +13,8 @@ libs/energest/native \ libs/energest/sky \ libs/data-structures/native \ libs/data-structures/sky \ +ipso-objects/native \ +ipso-objects/native:MAKE_WITH_DTLS=1 \ rpl-udp/sky \ rpl-border-router/native \ rpl-border-router/sky \ diff --git a/tests/02-compile-arm-ports-01/Makefile b/tests/02-compile-arm-ports-01/Makefile index 1505fd831..3840e2b95 100644 --- a/tests/02-compile-arm-ports-01/Makefile +++ b/tests/02-compile-arm-ports-01/Makefile @@ -14,6 +14,20 @@ platform-specific/cc26xx/very-sleepy-demo/srf06-cc26xx \ rpl-border-router/srf06-cc26xx:BOARD=launchpad/cc2650 \ sensniff/srf06-cc26xx \ sensniff/srf06-cc26xx:BOARD=launchpad/cc1310 \ +dev/gpio-hal/srf06-cc26xx:BOARD=srf06/cc13xx \ +dev/gpio-hal/srf06-cc26xx:BOARD=srf06/cc26xx \ +dev/gpio-hal/srf06-cc26xx:BOARD=sensortag/cc1350 \ +dev/gpio-hal/srf06-cc26xx:BOARD=sensortag/cc2650 \ +dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc1310 \ +dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc1350 \ +dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc2650 \ +dev/leds/srf06-cc26xx:BOARD=srf06/cc13xx \ +dev/leds/srf06-cc26xx:BOARD=srf06/cc26xx \ +dev/leds/srf06-cc26xx:BOARD=sensortag/cc1350 \ +dev/leds/srf06-cc26xx:BOARD=sensortag/cc2650 \ +dev/leds/srf06-cc26xx:BOARD=launchpad/cc1310 \ +dev/leds/srf06-cc26xx:BOARD=launchpad/cc1350 \ +dev/leds/srf06-cc26xx:BOARD=launchpad/cc2650 \ 6tisch/etsi-plugtest-2017/srf06-cc26xx:BOARD=launchpad/cc2650 \ ble/ipv6-client/srf06-cc26xx:BOARD=launchpad/cc2650 \ storage/cfs-coffee/cc2538dk \ @@ -23,15 +37,18 @@ coap/cc2538dk \ slip-radio/cc2538dk \ ipso-objects/cc2538dk \ multicast/cc2538dk \ +dev/gpio-hal/cc2538dk \ +dev/leds/cc2538dk \ platform-specific/cc2538-common/cc2538dk \ platform-specific/cc2538-common/mqtt-demo/cc2538dk \ platform-specific/cc2538-common/crypto/cc2538dk \ platform-specific/cc2538-common/pka/cc2538dk \ hello-world/cc2538dk \ rpl-border-router/cc2538dk \ +rpl-border-router/cc2538dk:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \ hello-world/nrf52dk \ platform-specific/nrf52dk/coap-demo/nrf52dk:coap-server \ -platform-specific/nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_ADDR=ffff \ +platform-specific/nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_EP=ffff \ platform-specific/nrf52dk/mqtt-demo/nrf52dk \ platform-specific/nrf52dk/blink-hello/nrf52dk \ platform-specific/nrf52dk/timer-test/nrf52dk \ diff --git a/tests/03-compile-arm-ports-02/Makefile b/tests/03-compile-arm-ports-02/Makefile index 25345e14c..01aab98b6 100644 --- a/tests/03-compile-arm-ports-02/Makefile +++ b/tests/03-compile-arm-ports-02/Makefile @@ -8,8 +8,13 @@ platform-specific/cc2538-common/mqtt-demo/zoul \ platform-specific/cc2538-common/crypto/zoul \ platform-specific/cc2538-common/pka/zoul \ platform-specific/zoul/orion/ip64-router/zoul:BOARD=orion \ +platform-specific/zoul/rev-b/zoul:BOARD=remote-revb \ +platform-specific/zoul/at-test/zoul \ +platform-specific/zoul/rtcc/zoul \ +platform-specific/zoul/zoul \ coap/zoul \ ipso-objects/zoul \ +ipso-objects/zoul:MAKE_WITH_DTLS=1 \ hello-world/zoul \ sensniff/zoul \ sensniff/zoul:ZOUL_CONF_SUB_GHZ_SNIFFER=1 \ @@ -29,10 +34,27 @@ libs/trickle-library/zoul \ libs/data-structures/zoul \ nullnet/zoul \ slip-radio/zoul \ +dev/gpio-hal/zoul:BOARD=remote-reva \ +dev/gpio-hal/zoul:BOARD=remote-revb \ +dev/gpio-hal/zoul:BOARD=firefly-reva \ +dev/gpio-hal/zoul:BOARD=firefly \ +dev/gpio-hal/zoul:BOARD=orion \ +dev/leds/zoul:BOARD=remote-reva \ +dev/leds/zoul:BOARD=remote-revb \ +dev/leds/zoul:BOARD=firefly-reva \ +dev/leds/zoul:BOARD=firefly \ +dev/leds/zoul:BOARD=orion \ +dev/rgb-led/zoul:BOARD=remote-reva \ +dev/rgb-led/zoul:BOARD=remote-revb \ +dev/rgb-led/zoul:BOARD=firefly-reva \ +dev/rgb-led/zoul:BOARD=firefly \ +dev/rgb-led/zoul:BOARD=orion \ storage/cfs-coffee/openmote-cc2538 \ sensniff/openmote-cc2538 \ hello-world/openmote-cc2538 \ rpl-udp/openmote-cc2538 \ +dev/gpio-hal/openmote-cc2538 \ +dev/leds/openmote-cc2538 \ rpl-border-router/openmote-cc2538 TOOLS= diff --git a/tests/07-simulation-base/02-ringbufindex.csc b/tests/07-simulation-base/02-ringbufindex.csc index 2b3722197..5b236bc5a 100644 --- a/tests/07-simulation-base/02-ringbufindex.csc +++ b/tests/07-simulation-base/02-ringbufindex.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/tests/07-simulation-base/03-nullnet-broadcast.csc b/tests/07-simulation-base/03-nullnet-broadcast.csc index 911f998f4..302a04b9b 100644 --- a/tests/07-simulation-base/03-nullnet-broadcast.csc +++ b/tests/07-simulation-base/03-nullnet-broadcast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc b/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc index 29c4b6669..498c7fcbe 100644 --- a/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc +++ b/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/05-nullnet-unicast.csc b/tests/07-simulation-base/05-nullnet-unicast.csc index 628196ac6..12b600317 100644 --- a/tests/07-simulation-base/05-nullnet-unicast.csc +++ b/tests/07-simulation-base/05-nullnet-unicast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/06-nullnet-unicast-tsch.csc b/tests/07-simulation-base/06-nullnet-unicast-tsch.csc index 12639e273..e64247095 100644 --- a/tests/07-simulation-base/06-nullnet-unicast-tsch.csc +++ b/tests/07-simulation-base/06-nullnet-unicast-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/10-sky-slip-radio.csc b/tests/07-simulation-base/10-sky-slip-radio.csc deleted file mode 100644 index 85eb6e9d5..000000000 --- a/tests/07-simulation-base/10-sky-slip-radio.csc +++ /dev/null @@ -1,189 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - slip radio 1 - 123456 - 1000000 - - se.sics.cooja.radiomediums.UDGM - 15.0 - 15.0 - 1.0 - 1.0 - - - 40000 - - - se.sics.cooja.mspmote.SkyMoteType - sky1 - slip radio - [CONTIKI_DIR]/examples/slip-radio/slip-radio.c - make -j slip-radio.sky TARGET=sky - [CONTIKI_DIR]/examples/slip-radio/slip-radio.sky - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.interfaces.IPAddress - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.MoteAttributes - se.sics.cooja.mspmote.interfaces.MspClock - se.sics.cooja.mspmote.interfaces.MspMoteID - se.sics.cooja.mspmote.interfaces.SkyButton - se.sics.cooja.mspmote.interfaces.SkyFlash - se.sics.cooja.mspmote.interfaces.SkyCoffeeFilesystem - se.sics.cooja.mspmote.interfaces.Msp802154Radio - se.sics.cooja.mspmote.interfaces.MspSerial - se.sics.cooja.mspmote.interfaces.SkyLED - se.sics.cooja.mspmote.interfaces.MspDebugOutput - se.sics.cooja.mspmote.interfaces.SkyTemperature - - - se.sics.cooja.mspmote.SkyMoteType - sky2 - wait-dag - [CONFIG_DIR]/code-slip-radio/wait-dag.c - make -j wait-dag.sky TARGET=sky - [CONFIG_DIR]/code-slip-radio/wait-dag.sky - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.interfaces.IPAddress - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.MoteAttributes - se.sics.cooja.mspmote.interfaces.MspClock - se.sics.cooja.mspmote.interfaces.MspMoteID - se.sics.cooja.mspmote.interfaces.SkyButton - se.sics.cooja.mspmote.interfaces.SkyFlash - se.sics.cooja.mspmote.interfaces.SkyCoffeeFilesystem - se.sics.cooja.mspmote.interfaces.Msp802154Radio - se.sics.cooja.mspmote.interfaces.MspSerial - se.sics.cooja.mspmote.interfaces.SkyLED - se.sics.cooja.mspmote.interfaces.MspDebugOutput - se.sics.cooja.mspmote.interfaces.SkyTemperature - - - - - se.sics.cooja.interfaces.Position - 43.565500781711165 - 14.697933087406794 - 0.0 - - - se.sics.cooja.mspmote.interfaces.MspMoteID - 1 - - sky1 - - - - - se.sics.cooja.interfaces.Position - 53.849666651434326 - 14.629826028666905 - 0.0 - - - se.sics.cooja.mspmote.interfaces.MspMoteID - 2 - - sky2 - - - - se.sics.cooja.plugins.SimControl - 315 - 1 - 175 - 433 - 0 - - - se.sics.cooja.plugins.Visualizer - - se.sics.cooja.plugins.skins.IDVisualizerSkin - se.sics.cooja.plugins.skins.GridVisualizerSkin - se.sics.cooja.plugins.skins.TrafficVisualizerSkin - se.sics.cooja.plugins.skins.UDGMVisualizerSkin - 14.682765905648006 0.0 0.0 14.682765905648006 -512.6620495401903 -96.80631081927221 - - 432 - 4 - 291 - 1 - 1 - - - se.sics.cooja.plugins.LogListener - - - - 758 - 3 - 289 - 748 - 159 - - - se.sics.cooja.plugins.Notes - - Slip-radio Tests, 01-sky-slip-radio-dio - -Test that we can send a packet over a slip-radio. -In this basic test, we send a DIO from mote 1, and wait for "DAG Found" in mote 2. - true - - 928 - 5 - 159 - 749 - -1 - - - se.sics.cooja.plugins.ScriptRunner - - - true - - 758 - 2 - 502 - 749 - 449 - - - se.sics.cooja.plugins.RadioLogger - - 150 - - 746 - 0 - 657 - 3 - 294 - - diff --git a/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc b/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc index 3b6ad609b..473df16dd 100644 --- a/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc +++ b/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc index f390242ed..e20a30cb6 100644 --- a/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc +++ b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc index e3f4a3593..14b74b41e 100644 --- a/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc +++ b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/18-cooja-multicast-31-hops.csc b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc index c18de1fce..86ae6916f 100644 --- a/tests/07-simulation-base/18-cooja-multicast-31-hops.csc +++ b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/19-cooja-rpl-tsch.csc b/tests/07-simulation-base/19-cooja-rpl-tsch.csc index 462cf7f84..99e11d63d 100644 --- a/tests/07-simulation-base/19-cooja-rpl-tsch.csc +++ b/tests/07-simulation-base/19-cooja-rpl-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL+TSCH diff --git a/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc b/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc index fb284128d..5ce2c8121 100644 --- a/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc +++ b/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL+TSCH+Orchestrsa diff --git a/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc b/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc index 2607b8b03..c34e6c4cf 100644 --- a/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc +++ b/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL+TSCH+Security diff --git a/tests/07-simulation-base/31-data-structures-sky.csc b/tests/07-simulation-base/31-data-structures-sky.csc index cd0e35ee3..0e4e81069 100644 --- a/tests/07-simulation-base/31-data-structures-sky.csc +++ b/tests/07-simulation-base/31-data-structures-sky.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker data-structures-sky diff --git a/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c b/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c index 929e0d584..4e2e664b3 100644 --- a/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c +++ b/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c @@ -1,8 +1,7 @@ #include "contiki.h" #include "contiki-lib.h" #include "contiki-net.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include @@ -41,7 +40,7 @@ PROCESS_THREAD(udp_process, ev, data) PROCESS_BEGIN(); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); simple_udp_register(&broadcast_connection, UDP_PORT, NULL, UDP_PORT, diff --git a/tests/07-simulation-base/code-slip-radio/wait-dag.c b/tests/07-simulation-base/code-slip-radio/wait-dag.c index 83e3d28f7..a059661b4 100644 --- a/tests/07-simulation-base/code-slip-radio/wait-dag.c +++ b/tests/07-simulation-base/code-slip-radio/wait-dag.c @@ -33,7 +33,7 @@ #include "contiki.h" #include "contiki-lib.h" #include "contiki-net.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "net/ipv6/uip.h" #include @@ -49,8 +49,7 @@ AUTOSTART_PROCESSES(&wait_for_dag); static void timeout_handler(void) { - rpl_dag_t *dag = rpl_get_any_dag(); - if (dag != NULL) { + if(NETSTACK_ROUTING.node_has_joined()) { PRINTF("DAG Found\n"); } } @@ -67,7 +66,7 @@ PROCESS_THREAD(wait_for_dag, ev, data) if(etimer_expired(&et)) { timeout_handler(); etimer_restart(&et); - } + } } PROCESS_END(); } diff --git a/tests/13-ieee802154/01-panid-handling.csc b/tests/13-ieee802154/01-panid-handling.csc index 0d40497a1..71ec85818 100644 --- a/tests/13-ieee802154/01-panid-handling.csc +++ b/tests/13-ieee802154/01-panid-handling.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc b/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc index 50b58769f..879b31345 100644 --- a/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc +++ b/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/03-cooja-test-sixtop.csc b/tests/13-ieee802154/03-cooja-test-sixtop.csc index 0826967df..9d5be006c 100644 --- a/tests/13-ieee802154/03-cooja-test-sixtop.csc +++ b/tests/13-ieee802154/03-cooja-test-sixtop.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc b/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc index 994a9f8a2..5d5cf7016 100644 --- a/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc +++ b/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/05-cooja-test-sixp-trans.csc b/tests/13-ieee802154/05-cooja-test-sixp-trans.csc index e7dfc2373..837fcc321 100644 --- a/tests/13-ieee802154/05-cooja-test-sixp-trans.csc +++ b/tests/13-ieee802154/05-cooja-test-sixp-trans.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc b/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc index 00aca5da3..bbffc18a8 100644 --- a/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc +++ b/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/07-cooja-test-sixp.csc b/tests/13-ieee802154/07-cooja-test-sixp.csc index 6e6e89ba7..3e884e4b2 100644 --- a/tests/13-ieee802154/07-cooja-test-sixp.csc +++ b/tests/13-ieee802154/07-cooja-test-sixp.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/01-rpl-up-route.csc b/tests/14-rpl-lite/01-rpl-up-route.csc index e35c99f05..899b58bf7 100644 --- a/tests/14-rpl-lite/01-rpl-up-route.csc +++ b/tests/14-rpl-lite/01-rpl-up-route.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/03-rpl-28-hours.csc b/tests/14-rpl-lite/03-rpl-28-hours.csc index 56777ba3e..a4c25cc08 100644 --- a/tests/14-rpl-lite/03-rpl-28-hours.csc +++ b/tests/14-rpl-lite/03-rpl-28-hours.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc b/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc index 0bd3c4d63..49e793691 100644 --- a/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc +++ b/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc b/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc index 2ac006172..6d8283d3e 100644 --- a/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc +++ b/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/07-rpl-random-rearrangement.csc b/tests/14-rpl-lite/07-rpl-random-rearrangement.csc index dd1e73e9c..6119c6829 100644 --- a/tests/14-rpl-lite/07-rpl-random-rearrangement.csc +++ b/tests/14-rpl-lite/07-rpl-random-rearrangement.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc index 7e91d4551..bd1114c50 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc index 8d1540dab..cc1fd3970 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc index 860b3ab05..f659b4e04 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc index d18acd1c2..a3e38edac 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc index 049de48f5..11a0f3168 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc index c877ba8b9..0a0308e22 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/09-rpl-probing.csc b/tests/14-rpl-lite/09-rpl-probing.csc index cf5ab5afb..d79ec7be4 100644 --- a/tests/14-rpl-lite/09-rpl-probing.csc +++ b/tests/14-rpl-lite/09-rpl-probing.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/code/receiver-node.c b/tests/14-rpl-lite/code/receiver-node.c index 352f23cb5..b5265d3f7 100644 --- a/tests/14-rpl-lite/code/receiver-node.c +++ b/tests/14-rpl-lite/code/receiver-node.c @@ -38,7 +38,7 @@ #include "simple-udp.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "dev/leds.h" #include diff --git a/tests/14-rpl-lite/code/root-node.c b/tests/14-rpl-lite/code/root-node.c index ef3c982ee..7c9fc8c99 100644 --- a/tests/14-rpl-lite/code/root-node.c +++ b/tests/14-rpl-lite/code/root-node.c @@ -38,8 +38,7 @@ #include "simple-udp.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include #include @@ -75,7 +74,7 @@ PROCESS_THREAD(unicast_receiver_process, ev, data) { PROCESS_BEGIN(); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); simple_udp_register(&unicast_connection, UDP_PORT, NULL, UDP_PORT, receiver); diff --git a/tests/15-rpl-classic/01-rpl-up-route.csc b/tests/15-rpl-classic/01-rpl-up-route.csc index e35c99f05..899b58bf7 100644 --- a/tests/15-rpl-classic/01-rpl-up-route.csc +++ b/tests/15-rpl-classic/01-rpl-up-route.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/02-rpl-root-reboot.csc b/tests/15-rpl-classic/02-rpl-root-reboot.csc index d3bc14461..2c89a499e 100644 --- a/tests/15-rpl-classic/02-rpl-root-reboot.csc +++ b/tests/15-rpl-classic/02-rpl-root-reboot.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/03-rpl-28-hours.csc b/tests/15-rpl-classic/03-rpl-28-hours.csc index 56777ba3e..a4c25cc08 100644 --- a/tests/15-rpl-classic/03-rpl-28-hours.csc +++ b/tests/15-rpl-classic/03-rpl-28-hours.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/05-rpl-up-and-down-routes-non-storing.csc b/tests/15-rpl-classic/05-rpl-up-and-down-routes-non-storing.csc new file mode 100644 index 000000000..aa412586b --- /dev/null +++ b/tests/15-rpl-classic/05-rpl-up-and-down-routes-non-storing.csc @@ -0,0 +1,341 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype743 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make -j sender-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype452 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make -j root-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype782 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make -j receiver-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -22.5728586847096 + 123.9358664968653 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype743 + + + + org.contikios.cooja.interfaces.Position + -1.39303771455413 + 100.21446701029119 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 10.931583432822638 + 69.848248459216 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype452 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + 1184 + 3 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 0 + 596 + 603 + 43 + + diff --git a/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc b/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc index 0bd3c4d63..49e793691 100644 --- a/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc +++ b/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc b/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc index e68e5b307..9bbf552d5 100644 --- a/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc +++ b/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/07-rpl-random-rearrangement.csc b/tests/15-rpl-classic/07-rpl-random-rearrangement.csc index dd1e73e9c..6119c6829 100644 --- a/tests/15-rpl-classic/07-rpl-random-rearrangement.csc +++ b/tests/15-rpl-classic/07-rpl-random-rearrangement.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc index 7e91d4551..bd1114c50 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc index 8d1540dab..cc1fd3970 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc index 860b3ab05..f659b4e04 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc index d18acd1c2..a3e38edac 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc index 049de48f5..11a0f3168 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc index c877ba8b9..0a0308e22 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/09-rpl-probing.csc b/tests/15-rpl-classic/09-rpl-probing.csc index cf5ab5afb..d79ec7be4 100644 --- a/tests/15-rpl-classic/09-rpl-probing.csc +++ b/tests/15-rpl-classic/09-rpl-probing.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/10-rpl-multi-dodag.csc b/tests/15-rpl-classic/10-rpl-multi-dodag.csc index ccdaa4734..7d48ae7b4 100644 --- a/tests/15-rpl-classic/10-rpl-multi-dodag.csc +++ b/tests/15-rpl-classic/10-rpl-multi-dodag.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/serial2pty [APPS_DIR]/radiologger-headless diff --git a/tests/15-rpl-classic/code/receiver-node.c b/tests/15-rpl-classic/code/receiver-node.c index 770f50f77..20bf165f8 100644 --- a/tests/15-rpl-classic/code/receiver-node.c +++ b/tests/15-rpl-classic/code/receiver-node.c @@ -38,7 +38,7 @@ #include "simple-udp.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "dev/leds.h" #include @@ -91,6 +91,7 @@ set_global_address(void) return &ipaddr; } /*---------------------------------------------------------------------------*/ +#if RPL_WITH_STORING uint8_t should_blink = 1; static void route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, int num_routes) @@ -101,17 +102,22 @@ route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, int num_rou should_blink = 1; } } +#endif /* #if RPL_WITH_STORING */ /*---------------------------------------------------------------------------*/ PROCESS_THREAD(receiver_node_process, ev, data) { static struct etimer et; +#if RPL_WITH_STORING static struct uip_ds6_notification n; +#endif /* #if RPL_WITH_STORING */ PROCESS_BEGIN(); set_global_address(); +#if RPL_WITH_STORING uip_ds6_notification_add(&n, route_callback); +#endif /* #if RPL_WITH_STORING */ simple_udp_register(&unicast_connection, UDP_PORT, NULL, UDP_PORT, receiver); @@ -120,12 +126,14 @@ PROCESS_THREAD(receiver_node_process, ev, data) while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); +#if RPL_WITH_STORING if(should_blink) { leds_on(LEDS_ALL); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); leds_off(LEDS_ALL); } +#endif /* #if RPL_WITH_STORING */ } PROCESS_END(); } diff --git a/tests/15-rpl-classic/code/root-node.c b/tests/15-rpl-classic/code/root-node.c index ef3c982ee..e25b2872f 100644 --- a/tests/15-rpl-classic/code/root-node.c +++ b/tests/15-rpl-classic/code/root-node.c @@ -35,12 +35,9 @@ #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-debug.h" - +#include "net/routing/routing.h" #include "simple-udp.h" -#include "rpl.h" -#include "rpl-dag-root.h" - #include #include @@ -75,7 +72,7 @@ PROCESS_THREAD(unicast_receiver_process, ev, data) { PROCESS_BEGIN(); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); simple_udp_register(&unicast_connection, UDP_PORT, NULL, UDP_PORT, receiver); diff --git a/tests/17-tun-rpl-br/01-border-router-cooja.csc b/tests/17-tun-rpl-br/01-border-router-cooja.csc index f2fbdc67f..02808aeec 100644 --- a/tests/17-tun-rpl-br/01-border-router-cooja.csc +++ b/tests/17-tun-rpl-br/01-border-router-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc b/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc index 7c70d4cd8..5b86b690c 100644 --- a/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc +++ b/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/17-tun-rpl-br/03-border-router-sky.csc b/tests/17-tun-rpl-br/03-border-router-sky.csc index 62d0ccac0..cec948e0d 100644 --- a/tests/17-tun-rpl-br/03-border-router-sky.csc +++ b/tests/17-tun-rpl-br/03-border-router-sky.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/17-tun-rpl-br/04-border-router-traceroute.csc b/tests/17-tun-rpl-br/04-border-router-traceroute.csc index f2fbdc67f..02808aeec 100644 --- a/tests/17-tun-rpl-br/04-border-router-traceroute.csc +++ b/tests/17-tun-rpl-br/04-border-router-traceroute.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 0dba7f835..a150c530f 100755 --- a/tests/17-tun-rpl-br/04-border-router-traceroute.sh +++ b/tests/17-tun-rpl-br/04-border-router-traceroute.sh @@ -17,9 +17,6 @@ java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$BASENAME.csc -c JPID=$! sleep 20 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # Connect to the simlation echo "Starting tunslip6" make -C $CONTIKI/tools tunslip6 diff --git a/tests/17-tun-rpl-br/05-native-ping.sh b/tests/17-tun-rpl-br/05-native-ping.sh index e47536e3f..9e677c16e 100755 --- a/tests/17-tun-rpl-br/05-native-ping.sh +++ b/tests/17-tun-rpl-br/05-native-ping.sh @@ -7,9 +7,6 @@ BASENAME=01-native-ping IPADDR=fd00::302:304:506:708 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # Starting Contiki-NG native node echo "Starting native node" make -C $CONTIKI/examples/hello-world > make.log 2> make.err diff --git a/tests/17-tun-rpl-br/06-native-coap.sh b/tests/17-tun-rpl-br/06-native-coap.sh index 453d76e2e..16dd8aab7 100755 --- a/tests/17-tun-rpl-br/06-native-coap.sh +++ b/tests/17-tun-rpl-br/06-native-coap.sh @@ -10,9 +10,6 @@ IPADDR=fd00::302:304:506:708 declare -i OKCOUNT=0 declare -i TESTCOUNT=0 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # Starting Contiki-NG native node echo "Starting native CoAP server" make -C $CONTIKI/examples/coap > make.log 2> make.err @@ -41,7 +38,7 @@ done echo "Closing native node" sleep 2 -pgrep hello-world | sudo xargs kill -9 +pgrep coap-example | sudo xargs kill -9 if [ $TESTCOUNT -eq $OKCOUNT ] ; then printf "%-32s TEST OK %3d/%d\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" > $BASENAME.testlog; diff --git a/tests/17-tun-rpl-br/07-native-border-router-cooja.csc b/tests/17-tun-rpl-br/07-native-border-router-cooja.csc new file mode 100644 index 000000000..7140d183c --- /dev/null +++ b/tests/17-tun-rpl-br/07-native-border-router-cooja.csc @@ -0,0 +1,254 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/powertracker + + My simulation + 1.0 + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype295 + Cooja Mote Type #1 + [CONTIKI_DIR]/examples/slip-radio/slip-radio.c + make TARGET=cooja clean +make -j slip-radio.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype686 + Cooja Mote Type #2 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make TARGET=cooja clean +make -j hello-world.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 54.36775767371176 + 24.409055040864118 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype295 + + + + org.contikios.cooja.interfaces.Position + 83.54989222799365 + 52.63050856506214 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype686 + + + + org.contikios.cooja.interfaces.Position + 108.91767775240822 + 78.59778809170032 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype686 + + + + org.contikios.cooja.interfaces.Position + 139.91021061864723 + 98.34190023350419 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype686 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + true + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.IDVisualizerSkin + 1.9798610460263038 0.0 0.0 1.9798610460263038 -61.112037797038525 -1.2848438586294648 + + 400 + 4 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + ID:4 + + + + 1404 + 2 + 240 + 400 + 160 + + + org.contikios.cooja.plugins.TimeLine + + 0 + 1 + 2 + 3 + + + + 500.0 + + 1804 + 6 + 166 + 0 + 753 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 1124 + 5 + 160 + 680 + 0 + + + org.contikios.cooja.serialsocket.SerialSocketServer + 0 + + 60001 + true + + 362 + 3 + 116 + 13 + 414 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 0 + 700 + 1037 + 40 + + diff --git a/tests/17-tun-rpl-br/07-native-border-router-cooja.sh b/tests/17-tun-rpl-br/07-native-border-router-cooja.sh new file mode 100755 index 000000000..d5d2642fe --- /dev/null +++ b/tests/17-tun-rpl-br/07-native-border-router-cooja.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=07-native-border-router-cooja + +bash test-nbr.sh $CONTIKI $BASENAME fd00::204:4:4:4 diff --git a/tests/17-tun-rpl-br/test-border-router.sh b/tests/17-tun-rpl-br/test-border-router.sh index 1a1d22a46..b8c8f018e 100755 --- a/tests/17-tun-rpl-br/test-border-router.sh +++ b/tests/17-tun-rpl-br/test-border-router.sh @@ -9,15 +9,15 @@ BASENAME=$2 # Destination IPv6 IPADDR=$3 +# ICMP request-reply count +COUNT=5 + # Start simulation echo "Starting Cooja simulation $BASENAME.csc" java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$BASENAME.csc -contiki=$CONTIKI > $BASENAME.coojalog & JPID=$! sleep 20 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # Connect to the simlation echo "Starting tunslip6" make -C $CONTIKI/tools tunslip6 @@ -28,9 +28,10 @@ sleep 5 # Do ping echo "Pinging" -ping6 $IPADDR -c 5 | tee $BASENAME.scriptlog +ping6 $IPADDR -c $COUNT | tee $BASENAME.scriptlog # Fetch ping6 status code (not $? because this is piped) STATUS=${PIPESTATUS[0]} +REPLIES=`grep -c 'icmp_seq=' $BASENAME.scriptlog` echo "Closing simulation and tunslip6" sleep 1 @@ -40,7 +41,7 @@ sleep 1 rm COOJA.testlog rm COOJA.log -if [ $STATUS -eq 0 ] ; then +if [ $STATUS -eq 0 ] && [ $REPLIES -eq $COUNT ] ; then printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; else echo "==== $BASENAME.coojalog ====" ; cat $BASENAME.coojalog; diff --git a/tests/17-tun-rpl-br/test-nbr.sh b/tests/17-tun-rpl-br/test-nbr.sh new file mode 100644 index 000000000..9a1824f7c --- /dev/null +++ b/tests/17-tun-rpl-br/test-nbr.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=$2 + +# Destination IPv6 +IPADDR=$3 + +# ICMP request-reply count +COUNT=5 + +# Start simulation +echo "Starting Cooja simulation $BASENAME.csc" +java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$BASENAME.csc -contiki=$CONTIKI > $BASENAME.coojalog & +JPID=$! +sleep 20 + +# Connect to the simlation +echo "Starting native border-router" +nohup make -C $CONTIKI/examples/rpl-border-router/ connect-router-cooja TARGET=native >> $BASENAME.nbr.log 2>&1 & +MPID=$! +echo "Waiting for network formation" +sleep 60 # runs in real time so we need to wait a bit + +# Do ping +echo "Pinging" +ping6 $IPADDR -c $COUNT | tee $BASENAME.scriptlog +# Fetch ping6 status code (not $? because this is piped) +STATUS=${PIPESTATUS[0]} +REPLIES=`grep -c 'icmp_seq=' $BASENAME.scriptlog` + +echo "Closing simulation and nbr" +sleep 1 +kill -9 $JPID +kill -9 $MPID +sleep 1 +rm COOJA.testlog +rm COOJA.log + +if [ $STATUS -eq 0 ] && [ $REPLIES -eq $COUNT ] ; then + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== $BASENAME.coojalog ====" ; cat $BASENAME.coojalog; + echo "==== $BASENAME.nbr.log ====" ; cat $BASENAME.nbr.log; + echo "==== $BASENAME.scriptlog ====" ; cat $BASENAME.scriptlog; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +# 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/06-lwm2m-ipso-test.sh b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh new file mode 100755 index 000000000..15fd96243 --- /dev/null +++ b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=06-lwm2m-test + +IPADDR=fd00::302:304:506:708 + +# Starting Contiki-NG native node +echo "Starting native node - lwm2m/ipso objects" +make -C $CONTIKI/examples/ipso-objects > make.log 2> make.err +sudo $CONTIKI/examples/ipso-objects/example-ipso-objects.native > node.log 2> node.err & +CPID=$! +sleep 10 + +echo "Downloading leshan" +wget -nc https://joakimeriksson.github.io/resources/leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server" +java -jar leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar >leshan.log 2>leshan.err & +LESHID=$! +sleep 50 + +echo "Closing native node" +sleep 1 +pgrep ipso | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + + +if grep -q 'OK' leshan.err ; 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/07-lwm2m-standalone-test.sh b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh new file mode 100755 index 000000000..5516eeb46 --- /dev/null +++ b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=07-lwm2m-standalone-test + +git clone https://github.com/contiki-ng/example-lwm2m-standalone.git +# Building standalone posix example +make -C example-lwm2m-standalone/lwm2m > make.log 2> make.err + +echo "Downloading leshan" +wget -nc https://joakimeriksson.github.io/resources/leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server" +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=$! + +sleep 50 + +echo "Closing native node" +sleep 1 +pgrep ipso | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + + +if grep -q 'OK' leshan.err ; 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/Makefile b/tests/18-coap-lwm2m/Makefile new file mode 100644 index 000000000..c46e5271d --- /dev/null +++ b/tests/18-coap-lwm2m/Makefile @@ -0,0 +1 @@ +include ../Makefile.script-test diff --git a/tests/18-coap-lwm2m/example-lwm2m-standalone b/tests/18-coap-lwm2m/example-lwm2m-standalone new file mode 160000 index 000000000..7ab51eaaa --- /dev/null +++ b/tests/18-coap-lwm2m/example-lwm2m-standalone @@ -0,0 +1 @@ +Subproject commit 7ab51eaaa309c123fbd318c6ad3338cce1e48e48 diff --git a/tests/18-coap-lwm2m/pytests/test-device.py b/tests/18-coap-lwm2m/pytests/test-device.py new file mode 100644 index 000000000..9c441e4a0 --- /dev/null +++ b/tests/18-coap-lwm2m/pytests/test-device.py @@ -0,0 +1,69 @@ +import unittest, array, time + +class TestDevice(unittest.TestCase): + global client + + def test_available_power_sources(self): + r = client.readTLV("3/0/6") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_device_read_JSON(self): + r = client.readJSON("3/0/1") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_read(self): + r = client.read("3/0/0") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_readJSON(self): + r = client.readJSON("3/0/0") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_write(self): + r = client.write(3, 0, 0, "abc"); + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + + def test_manufacturer_execute(self): + r = client.execute("3/0/0") + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + + def test_reboot_read(self): + r = client.read("3/0/4") + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + +# def test_opaque_read(self): +# r = client.readTLV("4711/0/11000") +# v = r.getContent().getValue(); + #print "Result:", v + #print "Type: ", type(v) + #print "Type code: ", v.typecode + #print "Data size: ", len(v) +# self.assertEqual(len(v), 900) + +# def test_object_with_opaque_read(self): +# r = client.readTLV("4711/0/") +# self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_device_time_write(self): + r = client.write(3,0,13,1000) + self.assertEqual(r.getCode().getName(), "CHANGED") + time.sleep(4.9) + r = client.read("3/0/13") + v = r.getContent().getValue().getTime() + self.assertTrue(v > 1000) + print "Time: ", v + + + +print "----------------------------------------" +print "LWM2M Tester - name of client: ", client.endpoint +print "----------------------------------------" + +r = client.read("3/0/0"); +print "Code:", r.getCode(), r.getCode().getName() == "CONTENT" +print "Objects: ", client.links +print "Read Manufacturer => ", client.read("3/0/0") +print "Read Device => ", client.readTLV("3/0/") + +suite = unittest.TestLoader().loadTestsFromTestCase(TestDevice) +unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tools/collect-view/build.xml b/tools/collect-view/build.xml deleted file mode 100644 index 5e7458eb7..000000000 --- a/tools/collect-view/build.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/collect-view/collect-init.script b/tools/collect-view/collect-init.script deleted file mode 100644 index 493cd46c5..000000000 --- a/tools/collect-view/collect-init.script +++ /dev/null @@ -1,6 +0,0 @@ -echo ~K -echo killall -sleep 2 -echo mac 0 -sleep 2 -echo time %TIME% | null diff --git a/tools/collect-view/lib/jcommon-1.0.13.jar b/tools/collect-view/lib/jcommon-1.0.13.jar deleted file mode 100644 index 634447d2f..000000000 Binary files a/tools/collect-view/lib/jcommon-1.0.13.jar and /dev/null differ diff --git a/tools/collect-view/lib/jfreechart-1.0.10.jar b/tools/collect-view/lib/jfreechart-1.0.10.jar deleted file mode 100644 index f6f7bbf2d..000000000 Binary files a/tools/collect-view/lib/jfreechart-1.0.10.jar and /dev/null differ diff --git a/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java b/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java deleted file mode 100644 index 582a4dacd..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java +++ /dev/null @@ -1,1592 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * ----------------------------------------------------------------- - * - * CollectServer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - */ - -package org.contikios.contiki.collect; -import java.awt.BorderLayout; -import java.awt.GraphicsEnvironment; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; -import java.util.Properties; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.contikios.contiki.collect.gui.AggregatedTimeChartPanel; -import org.contikios.contiki.collect.gui.BarChartPanel; -import org.contikios.contiki.collect.gui.MapPanel; -import org.contikios.contiki.collect.gui.NodeControl; -import org.contikios.contiki.collect.gui.NodeInfoPanel; -import org.contikios.contiki.collect.gui.SerialConsole; -import org.contikios.contiki.collect.gui.TimeChartPanel; - -/** - * - */ -public class CollectServer implements SerialConnectionListener { - - public static final String WINDOW_TITLE = "Sensor Data Collect with Contiki"; - public static final String STDIN_COMMAND = ""; - - public static final String CONFIG_FILE = "collect.conf"; - public static final String SENSORDATA_FILE = "sensordata.log"; - public static final String CONFIG_DATA_FILE = "collect-data.conf"; - public static final String INIT_SCRIPT = "collect-init.script"; - public static final String FIRMWARE_FILE = "collect-view-shell.ihex"; - - /* Categories for the tab pane */ - private static final String MAIN = "main"; - private static final String NETWORK = "Network"; - private static final String SENSORS = "Sensors"; - private static final String POWER = "Power"; - - private Properties config = new Properties(); - - private String configFile; - private Properties configTable = new Properties(); - - private ArrayList sensorDataList = new ArrayList(); - private PrintWriter sensorDataOutput; - private boolean isSensorLogUsed; - - private Hashtable nodeTable = new Hashtable(); - private Node[] nodeCache; - - private JFrame window; - private JTabbedPane mainPanel; - private HashMap categoryTable = new HashMap(); - private JMenuItem runInitScriptItem; - - private final Visualizer[] visualizers; - private final MapPanel mapPanel; - private final SerialConsole serialConsole; - private final ConnectSerialAction connectSerialAction; - private final MoteProgramAction moteProgramAction; - private JFileChooser fileChooser; - - private JList nodeList; - private DefaultListModel nodeModel; - private Node[] selectedNodes; - - private SerialConnection serialConnection; - private boolean hasSerialOpened; - /* Do not auto send init script at startup */ - private boolean doSendInitAtStartup = false; - private String initScript; - - private boolean hasStarted = false; - private boolean doExitOnRequest = true; - private JMenuItem exitItem; - - private int defaultMaxItemCount = 250; - private long nodeTimeDelta; - - @SuppressWarnings("serial") - public CollectServer() { - loadConfig(config, CONFIG_FILE); - - this.configFile = config.getProperty("config.datafile", CONFIG_DATA_FILE); - if (this.configFile != null) { - loadConfig(configTable, this.configFile); - } - this.initScript = config.getProperty("init.script", INIT_SCRIPT); - - /* Make sure we have nice window decorations */ -// JFrame.setDefaultLookAndFeelDecorated(true); -// JDialog.setDefaultLookAndFeelDecorated(true); - Rectangle maxSize = GraphicsEnvironment.getLocalGraphicsEnvironment() - .getMaximumWindowBounds(); - - /* Create and set up the window */ - window = new JFrame(WINDOW_TITLE + " (not connected)"); - window.setLocationByPlatform(true); - if (maxSize != null) { - window.setMaximizedBounds(maxSize); - } - window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - - window.addWindowListener(new WindowAdapter() { - - public void windowClosing(WindowEvent e) { - exit(); - } - }); - - moteProgramAction = new MoteProgramAction("Program Nodes..."); - connectSerialAction = new ConnectSerialAction("Connect to serial"); - - nodeModel = new DefaultListModel(); - nodeModel.addElement(""); - nodeList = new JList(nodeModel); - nodeList.setPrototypeCellValue("888.888"); - nodeList.addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting() && e.getSource() == nodeList) { - Node[] selected; - int iMin = nodeList.getMinSelectionIndex(); - int iMax = nodeList.getMaxSelectionIndex(); - if ((iMin < 0) || (iMax < 0)) { - selected = null; - } else if (nodeList.getSelectedIndex() == 0) { - selected = getNodes(); - if (nodeModel.size() > 1) { - nodeList.setSelectionInterval(1, nodeModel.size() - 1); - } - } else { - Node[] tmp = new Node[1 + (iMax - iMin)]; - int n = 0; - if (iMin < 1) { - iMin = 1; - } - for(int i = iMin; i <= iMax; i++) { - if (nodeList.isSelectedIndex(i)) { - tmp[n++] = (Node) nodeModel.getElementAt(i); - } - } - if (n != tmp.length) { - Node[] t = new Node[n]; - System.arraycopy(tmp, 0, t, 0, n); - tmp = t; - } - selected = tmp; - } - selectNodes(selected, false); - } - - }}); - nodeList.setBorder(BorderFactory.createTitledBorder("Nodes")); - ListCellRenderer renderer = nodeList.getCellRenderer(); - if (renderer instanceof JLabel) { - ((JLabel)renderer).setHorizontalAlignment(JLabel.CENTER); - } - window.getContentPane().add(new JScrollPane(nodeList), BorderLayout.WEST); - - mainPanel = new JTabbedPane(); - mainPanel.setBackground(nodeList.getBackground()); - mainPanel.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - categoryTable.put(MAIN, mainPanel); - - serialConsole = new SerialConsole(this, MAIN); - mapPanel = new MapPanel(this, "Sensor Map", MAIN, true); - String image = getConfig("collect.mapimage"); - if (image != null) { - mapPanel.setMapBackground(image); - } - NodeControl nodeControl = new NodeControl(this, MAIN); - - visualizers = new Visualizer[] { - nodeControl, - mapPanel, - new MapPanel(this, "Network Graph", MAIN, false), - new BarChartPanel(this, SENSORS, "Average Temperature", "Temperature", "Nodes", "Celsius", - new String[] { "Celsius" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(aggregator.getAverageTemperature(), categories[0], nodeName); - } - }, - new TimeChartPanel(this, SENSORS, "Temperature", "Temperature", "Time", "Celsius") { - { - chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - setRangeTick(5); - setRangeMinimumSize(10.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getTemperature(); - } - }, - new TimeChartPanel(this, SENSORS, "Battery Voltage", "Battery Voltage", - "Time", "Volt") { - { - setRangeTick(1); - setRangeMinimumSize(4.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getBatteryVoltage(); - } - }, - new TimeChartPanel(this, SENSORS, "Battery Indicator", "Battery Indicator", - "Time", "Indicator") { - { - chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - setRangeTick(5); - setRangeMinimumSize(10.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getBatteryIndicator(); - } - }, - new TimeChartPanel(this, SENSORS, "Relative Humidity", "Humidity", "Time", "%") { - { - chart.getXYPlot().getRangeAxis().setRange(0.0, 100.0); - } - protected double getSensorDataValue(SensorData data) { - return data.getHumidity(); - } - }, - new TimeChartPanel(this, SENSORS, "Light 1", "Light 1", "Time", "-") { - protected double getSensorDataValue(SensorData data) { - return data.getLight1(); - } - }, - new TimeChartPanel(this, SENSORS, "Light 2", "Light 2", "Time", "-") { - protected double getSensorDataValue(SensorData data) { - return data.getLight2(); - } - }, - new TimeChartPanel(this, NETWORK, "Neighbors", "Neighbor Count", "Time", "Neighbors") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.NUM_NEIGHBORS); - } - }, - new TimeChartPanel(this, NETWORK, "Beacon Interval", "Beacon interval", "Time", "Interval (s)") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.BEACON_INTERVAL); - } - }, - new TimeChartPanel(this, NETWORK, "Network Hops (Over Time)", "Network Hops", "Time", "Hops") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.HOPS); - } - }, - new BarChartPanel(this, NETWORK, "Network Hops (Per Node)", "Network Hops", "Nodes", "Hops", - new String[] { "Last Hop", "Average Hops" }, false) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - dataset.addValue(data.getValue(SensorData.HOPS), categories[0], data.getNode().getName()); - dataset.addValue(data.getNode().getSensorDataAggregator().getAverageValue(SensorData.HOPS), categories[1], data.getNode().getName()); - } - }, - new TimeChartPanel(this, NETWORK, "Routing Metric (Over Time)", "Routing Metric", "Time", "Routing Metric") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.RTMETRIC); - } - }, - new AggregatedTimeChartPanel(this, NETWORK, "Avg Routing Metric (Over Time)", "Time", - "Average Routing Metric") { - private int nodeCount; - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected boolean[] createState(Node node) { - return new boolean[1]; - } - @Override - protected void clearState(Map map) { - nodeCount = 0; - for(boolean[] value : map.values()) { - value[0] = false; - } - } - @Override - protected String getTitle(int selectedCount, int dataCount, int duplicateCount) { - return "Average Routing Metric (" + dataCount + " packets from " + nodeCount + " node" - + (nodeCount > 1 ? "s" : "") + ')'; - } - @Override - protected int getTotalDataValue(int value) { - // Return average value - return nodeCount > 0 ? (value / nodeCount) : value; - } - @Override - protected int getSensorDataValue(SensorData data, boolean[] nodeState) { - if (!nodeState[0]) { - nodeCount++; - nodeState[0] = true; - } - return data.getValue(SensorData.RTMETRIC); - } - }, - new TimeChartPanel(this, NETWORK, "ETX (Over Time)", "ETX to Next Hop", "Time", "ETX") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getBestNeighborETX(); - } - }, - new AggregatedTimeChartPanel(this, NETWORK, - "Next Hop (Over Time)", "Time", "Next Hop Changes") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected int[] createState(Node node) { - return new int[1]; - } - @Override - protected void clearState(Map map) { - for(int[] value : map.values()) { - value[0] = 0; - } - } - @Override - protected int getSensorDataValue(SensorData sd, int[] nodeState) { - boolean hasBest = nodeState[0] != 0; - int bestNeighbor = sd.getValue(SensorData.BEST_NEIGHBOR); - if (bestNeighbor != 0 && bestNeighbor != nodeState[0]) { - nodeState[0] = bestNeighbor; - return hasBest ? 1 : 0; - } - return 0; - } - }, - new TimeChartPanel(this, NETWORK, "Latency", "Latency", "Time", "Seconds") { - protected double getSensorDataValue(SensorData data) { - return data.getLatency(); - } - }, - new AggregatedTimeChartPanel(this, NETWORK, - "Received (Over Time)", "Time", "Received Packets") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return "Received " + dataCount + " packets from " + nodeCount + " node" - + (nodeCount > 1 ? "s" : "") - + (duplicateCount > 0 ? (" (" + duplicateCount + " duplicates)") : ""); - } - @Override - protected Node createState(Node node) { - return node; - } - @Override - protected int getSensorDataValue(SensorData sd, Node node) { - return 1; - } - }, - new AggregatedTimeChartPanel(this, NETWORK, - "Lost (Over Time)", "Time", "Estimated Lost Packets") { - private int totalLost; - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return "Received " + dataCount + " packets from " + nodeCount - + " node" + (nodeCount > 1 ? "s" : "") + ". Estimated " - + totalLost + " lost packet" + (totalLost == 1 ? "" : "s") - + '.'; - } - @Override - protected int[] createState(Node node) { - return new int[1]; - } - @Override - protected void clearState(Map map) { - totalLost = 0; - for(int[] v : map.values()) { - v[0] = 0; - } - } - @Override - protected int getSensorDataValue(SensorData sd, int[] nodeState) { - int lastSeqno = nodeState[0]; - int seqno = sd.getSeqno(); - nodeState[0] = seqno; - if (seqno > lastSeqno + 1 && lastSeqno != 0) { - int estimatedLost = seqno - lastSeqno - 1; - totalLost += estimatedLost; - return estimatedLost; - } - return 0; - } - }, - new BarChartPanel(this, NETWORK, "Received (Per Node)", "Received Packets Per Node", "Nodes", "Packets", - new String[] { "Packets", "Duplicates" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - SensorDataAggregator sda = node.getSensorDataAggregator(); - dataset.addValue(sda.getDataCount(), categories[0], node.getName()); - dataset.addValue(sda.getDuplicateCount(), categories[1], node.getName()); - } - }, - new BarChartPanel(this, NETWORK, "Received (5 min)", "Received Packets (last 5 min)", "Nodes", "Packets", - new String[] { "Packets", "Duplicates" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - int packetCount = 0; - int duplicateCount = 0; - long earliestData = System.currentTimeMillis() - (5 * 60 * 1000); - for(int index = node.getSensorDataCount() - 1; index >= 0; index--) { - SensorData sd = node.getSensorData(index); - if (sd.getNodeTime() < earliestData) { - break; - } - if (sd.isDuplicate()) { - duplicateCount++; - } else { - packetCount++; - } - } - dataset.addValue(packetCount, categories[0], node.getName()); - dataset.addValue(duplicateCount, categories[1], node.getName()); - } - }, - new BarChartPanel(this, POWER, "Average Power", "Average Power Consumption", - "Nodes", "Power (mW)", - new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(aggregator.getLPMPower(), categories[0], nodeName); - dataset.addValue(aggregator.getCPUPower(), categories[1], nodeName); - dataset.addValue(aggregator.getListenPower(), categories[2], nodeName); - dataset.addValue(aggregator.getTransmitPower(), categories[3], nodeName); - } - }, - new BarChartPanel(this, POWER, "Radio Duty Cycle", "Average Radio Duty Cycle", - "Nodes", "Duty Cycle (%)", - new String[] { "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_LISTEN), - categories[0], nodeName); - dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_TRANSMIT), - categories[1], nodeName); - } - }, - new BarChartPanel(this, POWER, "Instantaneous Power", - "Instantaneous Power Consumption", "Nodes", "Power (mW)", - new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - dataset.addValue(data.getLPMPower(), categories[0], nodeName); - dataset.addValue(data.getCPUPower(), categories[1], nodeName); - dataset.addValue(data.getListenPower(), categories[2], nodeName); - dataset.addValue(data.getTransmitPower(), categories[3], nodeName); - } - }, - new TimeChartPanel(this, POWER, "Power History", "Historical Power Consumption", "Time", "mW") { - protected double getSensorDataValue(SensorData data) { - return data.getAveragePower(); - } - }, - new NodeInfoPanel(this, MAIN), - serialConsole - }; - for (int i = 0, n = visualizers.length; i < n; i++) { - String category = visualizers[i].getCategory(); - JTabbedPane pane = categoryTable.get(category); - if (pane == null) { - pane = new JTabbedPane(); - pane.setBackground(nodeList.getBackground()); - pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - categoryTable.put(category, pane); - mainPanel.add(category, pane); - } - pane.add(visualizers[i].getTitle(), visualizers[i].getPanel()); - } - JTabbedPane pane = categoryTable.get(nodeControl.getCategory()); - if (pane != null) { - pane.setSelectedComponent(nodeControl.getPanel()); - } - window.getContentPane().add(mainPanel, BorderLayout.CENTER); - - // Setup menu - JMenuBar menuBar = new JMenuBar(); - - JMenu fileMenu = new JMenu("File"); - fileMenu.setMnemonic(KeyEvent.VK_F); - menuBar.add(fileMenu); - fileMenu.add(new JMenuItem(connectSerialAction)); - fileMenu.add(new JMenuItem(moteProgramAction)); - - fileMenu.addSeparator(); - final JMenuItem clearMapItem = new JMenuItem("Remove Map Background"); - clearMapItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - mapPanel.setMapBackground(null); - clearMapItem.setEnabled(false); - configTable.remove("collect.mapimage"); - } - - }); - clearMapItem.setEnabled(mapPanel.getMapBackground() != null); - - JMenuItem item = new JMenuItem("Select Map Background..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - if (fileChooser == null) { - fileChooser = new JFileChooser(); - } - int reply = fileChooser.showOpenDialog(window); - if (reply == JFileChooser.APPROVE_OPTION) { - File file = fileChooser.getSelectedFile(); - String name = file.getAbsolutePath(); - if (!mapPanel.setMapBackground(file.getAbsolutePath())) { - JOptionPane.showMessageDialog(window, "Failed to set background image", "Error", JOptionPane.ERROR_MESSAGE); - } else { - configTable.put("collect.mapimage", name); - save(); - } - clearMapItem.setEnabled(mapPanel.getMapBackground() != null); - } - } - - }); - fileMenu.add(item); - fileMenu.add(clearMapItem); - - item = new JMenuItem("Save Settings"); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - save(); - JOptionPane.showMessageDialog(window, "Settings have been saved."); - } - - }); - fileMenu.add(item); - - fileMenu.addSeparator(); - item = new JMenuItem("Clear Sensor Data..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int reply = isSensorLogUsed - ? JOptionPane.showConfirmDialog(window, "Also clear the sensor data log file?") - : JOptionPane.NO_OPTION; - if (reply == JOptionPane.YES_OPTION) { - // Clear data from both memory and sensor log file - clearSensorDataLog(); - clearSensorData(); - } else if (reply == JOptionPane.NO_OPTION) { - // Only clear data from memory - clearSensorData(); - } - } - - }); - fileMenu.add(item); - - fileMenu.addSeparator(); - exitItem = new JMenuItem("Exit", KeyEvent.VK_X); - exitItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - exit(); - } - - }); - fileMenu.add(exitItem); - - JMenu toolsMenu = new JMenu("Tools"); - toolsMenu.setMnemonic(KeyEvent.VK_T); - menuBar.add(toolsMenu); - - runInitScriptItem = new JMenuItem("Run Init Script"); - runInitScriptItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - mainPanel.setSelectedComponent(serialConsole.getPanel()); - if (serialConnection != null && serialConnection.isOpen()) { - runInitScript(); - } else { - JOptionPane.showMessageDialog(mainPanel, "No serial port connection", "No connected node", JOptionPane.ERROR_MESSAGE); - } - } - - }); - runInitScriptItem.setEnabled(false); - toolsMenu.add(runInitScriptItem); - toolsMenu.addSeparator(); - - item = new JMenuItem("Set Max Item Count..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int value = getUserInputAsInteger("Specify Max Item Count", - "Please specify max item count for the time charts.\n" + - "Charts with more values will aggregate the values into fewer items.", - defaultMaxItemCount); - if (value > 0) { - defaultMaxItemCount = value; - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof TimeChartPanel) { - ((TimeChartPanel)v).setMaxItemCount(defaultMaxItemCount); - } - } - } - } - } - - }); - toolsMenu.add(item); - - final JCheckBoxMenuItem baseShapeItem = new JCheckBoxMenuItem("Base Shape Visible"); - baseShapeItem.setSelected(true); - baseShapeItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - boolean visible = baseShapeItem.getState(); - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof TimeChartPanel) { - ((TimeChartPanel)v).setBaseShapeVisible(visible); - } - } - } - } - - }); - toolsMenu.add(baseShapeItem); - - window.setJMenuBar(menuBar); - window.pack(); - - String bounds = configTable.getProperty("collect.bounds"); - if (bounds != null) { - String[] b = bounds.split(","); - if (b.length == 4) { - window.setBounds(Integer.parseInt(b[0]), Integer.parseInt(b[1]), - Integer.parseInt(b[2]), Integer.parseInt(b[3])); - } - } - - for(Object key: configTable.keySet()) { - String property = key.toString(); - if (!property.startsWith("collect")) { - getNode(property, true); - } - } - } - - private int getUserInputAsInteger(String title, String message, int defaultValue) { - String s = (String)JOptionPane.showInputDialog( - window, message, title, JOptionPane.PLAIN_MESSAGE, null, null, Integer.toString(defaultValue)); - if (s != null) { - try { - return Integer.parseInt(s); - } catch (Exception e) { - JOptionPane.showMessageDialog(window, "Illegal value", "Error", JOptionPane.ERROR_MESSAGE); - } - } - return -1; - } - - public void start(SerialConnection connection) { - if (hasStarted) { - throw new IllegalStateException("already started"); - } - hasStarted = true; - this.serialConnection = connection; - if (isSensorLogUsed) { - initSensorData(); - } - SwingUtilities.invokeLater(new Runnable() { - public void run() { - window.setVisible(true); - } - }); - connectToSerial(); - } - - protected void connectToSerial() { - if (serialConnection != null && !serialConnection.isOpen()) { - String comPort = serialConnection.getComPort(); - if (comPort == null && serialConnection.isMultiplePortsSupported()) { - comPort = MoteFinder.selectComPort(window); - } - if (comPort != null || !serialConnection.isMultiplePortsSupported()) { - serialConnection.open(comPort); - } - } - } - - public void stop() { - save(); - if (serialConnection != null) { - serialConnection.close(); - } - PrintWriter output = this.sensorDataOutput; - if (output != null) { - output.close(); - } - window.setVisible(false); - } - - public void setUseSensorDataLog(boolean useSensorLog) { - this.isSensorLogUsed = useSensorLog; - } - - public void setExitOnRequest(boolean doExit) { - this.doExitOnRequest = doExit; - if (exitItem != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - exitItem.setEnabled(doExitOnRequest); - } - }); - } - } - - private void exit() { - if (doExitOnRequest) { - stop(); - System.exit(0); - } else { - Toolkit.getDefaultToolkit().beep(); - } - } - - private void sleep(long delay) { - try { - Thread.sleep(delay); - } catch (InterruptedException e1) { - // Ignore - } - } - - protected boolean hasInitScript() { - return initScript != null && new File(initScript).canRead(); - } - - protected void runInitScript() { - if (initScript != null) { - runScript(initScript); - } - } - - protected void runScript(final String scriptFileName) { - new Thread("scripter") { - public void run() { - try { - BufferedReader in = new BufferedReader(new FileReader(scriptFileName)); - String line; - while ((line = in.readLine()) != null) { - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines and comments - } else if (line.startsWith("echo ")) { - line = line.substring(5).trim(); - if (line.indexOf('%') >= 0) { - line = line.replace("%TIME%", "" + (System.currentTimeMillis() / 1000)); - } - sendToNode(line); - } else if (line.startsWith("sleep ")) { - long delay = Integer.parseInt(line.substring(6).trim()); - Thread.sleep(delay * 1000); - } else { - System.err.println("Unknown script command: " + line); - break; - } - } - in.close(); - } catch (Exception e) { - System.err.println("Failed to run script: " + scriptFileName); - e.printStackTrace(); - } - } - }.start(); - } - - public String getConfig(String property) { - return getConfig(property, null); - } - - public String getConfig(String property, String defaultValue) { - return configTable.getProperty(property, config.getProperty(property, defaultValue)); - } - - public void setConfig(String property, String value) { - configTable.setProperty(property, value); - } - - public void removeConfig(String property) { - configTable.remove(property); - } - - public int getDefaultMaxItemCount() { - return defaultMaxItemCount; - } - - public Action getMoteProgramAction() { - return moteProgramAction; - } - - public Action getConnectSerialAction() { - return connectSerialAction; - } - - protected void setSystemMessage(final String message) { - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - boolean isOpen = serialConnection != null && serialConnection.isOpen(); - if (message == null) { - window.setTitle(WINDOW_TITLE); - } else { - window.setTitle(WINDOW_TITLE + " (" + message + ')'); - } - connectSerialAction.putValue(ConnectSerialAction.NAME, - isOpen ? "Disconnect from serial" : "Connect to serial"); - runInitScriptItem.setEnabled(isOpen - && serialConnection.isSerialOutputSupported() && hasInitScript()); - } - - }); - } - - // ------------------------------------------------------------------- - // Node Handling - // ------------------------------------------------------------------- - - public synchronized Node[] getNodes() { - if (nodeCache == null) { - Node[] tmp = nodeTable.values().toArray(new Node[nodeTable.size()]); - Arrays.sort(tmp); - nodeCache = tmp; - } - return nodeCache; - } - - public Node addNode(String nodeID) { - return getNode(nodeID, true); - } - - private Node getNode(final String nodeID, boolean notify) { - Node node = nodeTable.get(nodeID); - if (node == null) { - node = new Node(nodeID); - nodeTable.put(nodeID, node); - - synchronized (this) { - nodeCache = null; - } - - if (notify) { - final Node newNode = node; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - boolean added = false; - for (int i = 1, n = nodeModel.size(); i < n; i++) { - int cmp = newNode.compareTo((Node) nodeModel.get(i)); - if (cmp < 0) { - nodeModel.insertElementAt(newNode, i); - added = true; - break; - } else if (cmp == 0) { - // node already added - added = true; - break; - } - } - if (!added) { - nodeModel.addElement(newNode); - } - if (visualizers != null) { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodeAdded(newNode); - } - } - } - }); - } - } - return node; - } - - public void selectNodes(Node[] nodes) { - selectNodes(nodes, true); - } - - private void selectNodes(Node[] nodes, boolean updateList) { - if (nodes != selectedNodes) { - selectedNodes = nodes; - if (updateList) { - nodeList.clearSelection(); - if (selectedNodes != null) { - for (int i = 0, n = selectedNodes.length; i < n; i++) { - int index = nodeModel.indexOf(selectedNodes[i]); - if (index >= 0) { - nodeList.addSelectionInterval(index, index); - } - } - } - } - if (visualizers != null) { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodesSelected(nodes); - } - } - } - } - - public Node[] getSelectedNodes() { - return selectedNodes; - } - - - // ------------------------------------------------------------------- - // Node location handling - // ------------------------------------------------------------------- - - private boolean loadConfig(Properties properties, String configFile) { - try { - BufferedInputStream input = - new BufferedInputStream(new FileInputStream(configFile)); - try { - properties.load(input); - } finally { - input.close(); - } - return true; - } catch (FileNotFoundException e) { - // No configuration file exists. - } catch (IOException e) { - System.err.println("Failed to read configuration file: " + configFile); - e.printStackTrace(); - } - return false; - } - - private void save() { - if (configFile != null) { - configTable.setProperty("collect.bounds", "" + window.getX() + ',' + window.getY() + ',' + window.getWidth() + ',' + window.getHeight()); - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof Configurable) { - ((Configurable)v).updateConfig(configTable); - } - } - } - saveConfig(configTable, configFile); - } - } - - private void saveConfig(Properties properties, String configFile) { - try { - File fp = new File(configFile); - if (fp.exists()) { - File targetFp = new File(configFile + ".bak"); - if (targetFp.exists()) { - targetFp.delete(); - } - fp.renameTo(targetFp); - } - FileOutputStream output = new FileOutputStream(configFile); - try { - properties.store(output, "Configuration for Collect"); - } finally { - output.close(); - } - } catch (IOException e) { - System.err.println("failed to save configuration to " + configFile); - e.printStackTrace(); - } - } - - - // ------------------------------------------------------------------- - // Serial communication - // ------------------------------------------------------------------- - - public boolean sendToNode(String data) { - if (serialConnection != null && serialConnection.isOpen() && serialConnection.isSerialOutputSupported()) { - serialConsole.addSerialData("SEND: " + data); - serialConnection.writeSerialData(data); - return true; - } - return false; - } - - public void handleIncomingData(long systemTime, String line) { - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines, comments, and annotations. - return; - } - SensorData sensorData = SensorData.parseSensorData(this, line, systemTime); - if (sensorData != null) { - // Sensor data received - handleSensorData(sensorData); - return; - } - System.out.println("SERIAL: " + line); - serialConsole.addSerialData(line); - } - - // ------------------------------------------------------------------- - // Node time estimation - // ------------------------------------------------------------------- - - public long getNodeTime() { - return System.currentTimeMillis() + nodeTimeDelta; - } - - private void updateNodeTime(SensorData sensorData) { - this.nodeTimeDelta = sensorData.getNodeTime() - System.currentTimeMillis(); - } - - - // ------------------------------------------------------------------- - // SensorData handling - // ------------------------------------------------------------------- - - public int getSensorDataCount() { - return sensorDataList.size(); - } - - public SensorData getSensorData(int i) { - return sensorDataList.get(i); - } - - private void handleSensorData(final SensorData sensorData) { - System.out.println("SENSOR DATA: " + sensorData); - saveSensorData(sensorData); - if (sensorData.getNode().addSensorData(sensorData)) { - updateNodeTime(sensorData); - sensorDataList.add(sensorData); - handleLinks(sensorData); - if (visualizers != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodeDataReceived(sensorData); - } - } - }); - } - } - } - - private void handleLinks(SensorData sensorData) { - String nodeID = sensorData.getBestNeighborID(); - if (nodeID != null) { - Node neighbor = addNode(nodeID); - Node source = sensorData.getNode(); - Link link = source.getLink(neighbor); - link.setETX(sensorData.getBestNeighborETX()); - link.setLastActive(sensorData.getNodeTime()); - } - } - - private void initSensorData() { - loadSensorData(SENSORDATA_FILE, true); - } - - private boolean loadSensorData(String filename, boolean isStrict) { - File fp = new File(filename); - if (fp.exists() && fp.canRead()) { - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(fp)); - String line; - int no = 0; - while ((line = in.readLine()) != null) { - no++; - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines and comments - } else { - SensorData data = SensorData.parseSensorData(this, line); - if (data != null) { - if (data.getNode().addSensorData(data)) { - updateNodeTime(data); - sensorDataList.add(data); - handleLinks(data); - } - } else if (isStrict) { - // TODO exit here? - System.err.println("Failed to parse sensor data from log line " + no + ": " + line); - } - } - } - in.close(); - } catch (IOException e) { - System.err.println("Failed to read sensor data log from " + fp.getAbsolutePath()); - e.printStackTrace(); - return false; - } - } - return true; - } - - private void saveSensorData(SensorData data) { - PrintWriter output = this.sensorDataOutput; - if (output == null && isSensorLogUsed) { - try { - output = sensorDataOutput = new PrintWriter(new FileWriter(SENSORDATA_FILE, true)); - } catch (IOException e) { - System.err.println("Failed to add sensor data to log '" + SENSORDATA_FILE + '\''); - e.printStackTrace(); - } - } - if (output != null) { - output.println(data.toString()); - output.flush(); - } - } - - private void clearSensorData() { - sensorDataList.clear(); - Node[] nodes = getNodes(); - this.selectedNodes = null; - nodeList.clearSelection(); - if (nodeModel.size() > 1) { - nodeModel.removeRange(1, nodeModel.size() - 1); - } - this.nodeTable.clear(); - synchronized (this) { - this.nodeCache = null; - } - if (nodes != null) { - for(Node node : nodes) { - node.removeAllSensorData(); - } - } - if (visualizers != null) { - for(Visualizer v : visualizers) { - v.nodesSelected(null); - v.clearNodeData(); - } - } - // Remove any saved node positions - for(String key: configTable.keySet().toArray(new String[0])) { - String property = key.toString(); - if (!property.startsWith("collect")) { - configTable.remove(property); - } - } - } - - private void clearSensorDataLog() { - PrintWriter output = this.sensorDataOutput; - if (output != null) { - output.close(); - } - // Remove the sensor data log - new File(SENSORDATA_FILE).delete(); - this.sensorDataOutput = null; - } - - protected class ConnectSerialAction extends AbstractAction implements Runnable { - - private static final long serialVersionUID = 1L; - - private boolean isRunning; - - public ConnectSerialAction(String name) { - super(name); - } - - public void actionPerformed(ActionEvent e) { - if (!isRunning) { - isRunning = true; - new Thread(this, "serial").start(); - } - } - - public void run() { - try { - if (serialConnection != null) { - if (serialConnection.isOpen()) { - serialConnection.close(); - } else { - connectToSerial(); - } - } else { - JOptionPane.showMessageDialog(window, "No serial connection configured", "Error", JOptionPane.ERROR_MESSAGE); - } - } finally { - isRunning = false; - } - } - - } - - protected class MoteProgramAction extends AbstractAction implements Runnable { - - private static final long serialVersionUID = 1L; - - private boolean isRunning = false; - - public MoteProgramAction(String name) { - super(name); - } - - public void actionPerformed(ActionEvent e) { - if (!isRunning) { - isRunning = true; - new Thread(this, "program thread").start(); - } - } - - @Override - public void run() { - try { - MoteProgrammer mp = new MoteProgrammer(); - mp.setParentComponent(window); - mp.setFirmwareFile(FIRMWARE_FILE); - mp.searchForMotes(); - String[] motes = mp.getMotes(); - if (motes == null || motes.length == 0) { - JOptionPane.showMessageDialog(window, "Could not find any connected nodes", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - int reply = JOptionPane.showConfirmDialog(window, "Found " + motes.length + " connected nodes.\n" - + "Do you want to upload the firmware " + FIRMWARE_FILE + '?'); - if (reply == JFileChooser.APPROVE_OPTION) { - boolean wasOpen = serialConnection != null && serialConnection.isOpen(); - if (serialConnection != null) { - serialConnection.close(); - } - if (wasOpen) { - Thread.sleep(1000); - } - mp.programMotes(); - mp.waitForProcess(); - if (wasOpen) { - connectToSerial(); - } - } - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(window, "Programming failed: " + e, "Error", JOptionPane.ERROR_MESSAGE); - } finally { - isRunning = false; - } - } - - } - - - // ------------------------------------------------------------------- - // SerialConnection Listener - // ------------------------------------------------------------------- - - @Override - public void serialData(SerialConnection connection, String line) { - handleIncomingData(System.currentTimeMillis(), line); - } - - @Override - public void serialOpened(SerialConnection connection) { - String connectionName = connection.getConnectionName(); - serialConsole.addSerialData("*** Serial console listening on " + connectionName + " ***"); - hasSerialOpened = true; - if (connection.isMultiplePortsSupported()) { - String comPort = connection.getComPort(); - // Remember the last selected serial port - configTable.put("collect.serialport", comPort); - } - setSystemMessage("connected to " + connectionName); - - if (!connection.isSerialOutputSupported()) { - serialConsole.addSerialData("*** Serial output not supported ***"); - } else if (doSendInitAtStartup) { - // Send any initial commands - doSendInitAtStartup = false; - - if (hasInitScript()) { - // Wait a short time before running the init script - sleep(3000); - - runInitScript(); - } - } - } - - @Override - public void serialClosed(SerialConnection connection) { - String prefix; - if (hasSerialOpened) { - serialConsole.addSerialData("*** Serial connection terminated ***"); - prefix = "Serial connection terminated.\n"; - hasSerialOpened = false; - setSystemMessage("not connected"); - } else { - prefix = "Failed to connect to " + connection.getConnectionName() + '\n'; - } - if (!connection.isClosed()) { - if (connection.isMultiplePortsSupported()) { - String options[] = {"Retry", "Search for connected nodes", "Cancel"}; - int value = JOptionPane.showOptionDialog(window, - prefix + "Do you want to retry or search for connected nodes?", - "Reconnect to serial port?", - JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, - null, options, options[0]); - if (value == JOptionPane.CLOSED_OPTION || value == 2) { -// exit(); - } else { - String comPort = connection.getComPort(); - if (value == 1) { - // Select new serial port - comPort = MoteFinder.selectComPort(window); - if (comPort == null) { -// exit(); - } - } - // Try to open com port again - if (comPort != null) { - connection.open(comPort); - } - } - } else { -// JOptionPane.showMessageDialog(window, -// prefix, "Serial Connection Closed", JOptionPane.ERROR_MESSAGE); - } - } - } - - - // ------------------------------------------------------------------- - // Main - // ------------------------------------------------------------------- - - public static void main(String[] args) { - boolean resetSensorLog = false; - boolean useSensorLog = true; - boolean useSerialOutput = true; - String host = null; - String command = null; - String logFileToLoad = null; - String comPort = null; - int port = -1; - for(int i = 0, n = args.length; i < n; i++) { - String arg = args[i]; - if (arg.length() == 2 && arg.charAt(0) == '-') { - switch (arg.charAt(1)) { - case 'a': - if (i + 1 < n) { - host = args[++i]; - int pIndex = host.indexOf(':'); - if (pIndex > 0) { - port = Integer.parseInt(host.substring(pIndex + 1)); - host = host.substring(0, pIndex); - } - } else { - usage(arg); - } - break; - case 'c': - if (i + 1 < n) { - command = args[++i]; - } else { - usage(arg); - } - break; - case 'p': - if (i + 1 < n) { - port = Integer.parseInt(args[++i]); - } else { - usage(arg); - } - break; - case 'r': - resetSensorLog = true; - break; - case 'n': - useSensorLog = false; - break; - case 'i': - useSerialOutput = false; - break; - case 'f': - command = STDIN_COMMAND; - if (i + 1 < n && !args[i + 1].startsWith("-")) { - logFileToLoad = args[++i]; - } - break; - case 'h': - usage(null); - break; - default: - usage(arg); - break; - } - } else if (comPort == null) { - comPort = arg; - } else { - usage(arg); - } - } - - CollectServer server = new CollectServer(); - SerialConnection serialConnection; - if (host != null) { - if (port <= 0) { - port = 60001; - } - serialConnection = new TCPClientConnection(server, host, port); - } else if (port > 0) { - serialConnection = new UDPConnection(server, port); - } else if (command == null) { - serialConnection = new SerialDumpConnection(server); - } else if (command == STDIN_COMMAND) { - serialConnection = new StdinConnection(server); - } else { - serialConnection = new CommandConnection(server, command); - } - if (comPort == null) { - comPort = server.getConfig("collect.serialport"); - } - if (comPort != null) { - serialConnection.setComPort(comPort); - } - if (!useSerialOutput) { - serialConnection.setSerialOutputSupported(false); - } - - server.isSensorLogUsed = useSensorLog; - if (useSensorLog && resetSensorLog) { - server.clearSensorDataLog(); - } - if (logFileToLoad != null) { - server.loadSensorData(logFileToLoad, false); - } - server.start(serialConnection); - } - - private static void usage(String arg) { - if (arg != null) { - System.err.println("Unknown argument '" + arg + '\''); - } - System.err.println("Usage: java CollectServer [-n] [-i] [-r] [-f [file]] [-a host:port] [-p port] [-c command] [COMPORT]"); - System.err.println(" -n : Do not read or save sensor data log"); - System.err.println(" -r : Clear any existing sensor data log at startup"); - System.err.println(" -i : Do not allow serial output"); - System.err.println(" -f : Read serial data from standard in"); - System.err.println(" -a : Connect to specified host:port"); - System.err.println(" -p : Read data from specified UDP port"); - System.err.println(" -c : Use specified command for serial data input/output"); - System.err.println(" COMPORT: The serial port to connect to"); - System.exit(arg != null ? 1 : 0); - } -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java deleted file mode 100644 index dd19761b7..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * CommandConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -/** - * - */ -public class CommandConnection extends SerialConnection { - - protected Process commandProcess; - protected String command; - - public CommandConnection(SerialConnectionListener listener) { - super(listener); - } - - public CommandConnection(SerialConnectionListener listener, String command) { - super(listener); - this.command = command; - } - - @Override - public String getConnectionName() { - return command; - } - - public String getCommand() { - return command; - } - - public void setCommand(String command) { - this.command = command; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - String fullCommand = getCommand(); - - isClosed = false; - try { - String[] cmd = fullCommand.split(" "); - System.err.println("Running '" + fullCommand + '\''); - - commandProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(commandProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(commandProcess.getErrorStream())); - setSerialOutput(new PrintWriter(new OutputStreamWriter(commandProcess.getOutputStream()))); - - /* Start thread listening on standard out */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - standardData(line); - } - input.close(); - System.err.println("SerialConnection command terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection command: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "read input stream thread"); - - /* Start thread listening on standard err */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - errorData(line); - } - err.close(); - } catch (IOException e) { - if (!isClosed) { - System.err.println("Error when reading from SerialConnection command: " + e); - e.printStackTrace(); - } - } - } - }, "read error stream thread"); - - if (!isOpen) { - isOpen = true; - serialOpened(); - } - readInput.start(); - readError.start(); - } catch (Exception e) { - lastError = "Failed to execute '" + fullCommand + "': " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - protected void standardData(String line) { - serialData(line); - } - - protected void errorData(String line) { - System.err.println("SerialConnection error stream> " + line); - } - - @Override - protected void doClose() { - if (commandProcess != null) { - commandProcess.destroy(); - commandProcess = null; - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java b/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java deleted file mode 100644 index 285bcca91..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * Configurable - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 24 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.util.Properties; - -/** - * - */ -public interface Configurable { - - public void updateConfig(Properties config); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java deleted file mode 100644 index 2c3c86d5b..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * Motelist - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 4 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.awt.Component; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.JOptionPane; - -/** - * - */ -public class MoteFinder { - - public static final String MOTELIST_WINDOWS = "./tools/motelist-windows.exe"; - public static final String MOTELIST_LINUX = "./tools/motelist-linux"; - public static final String MOTELIST_MACOS = "./tools/motelist-macos"; - - private final Pattern motePattern; - private final boolean isWindows; - private final boolean isMacos; - private Process moteListProcess; -// private boolean hasVerifiedProcess; - private ArrayList comList = new ArrayList(); - private ArrayList moteList = new ArrayList(); - - public MoteFinder() { - String osName = System.getProperty("os.name", "").toLowerCase(); - isWindows = osName.startsWith("win"); - isMacos = osName.startsWith("mac"); - motePattern = Pattern.compile("\\s(COM|/dev/[a-zA-Z]+|/dev/tty.usbserial-)(\\d+|[A-Z0-9]+)\\s"); - } - - public String[] getMotes() throws IOException { - searchForMotes(); - return getMoteList(); - } - - public String[] getComPorts() throws IOException { - searchForMotes(); - return getComList(); - } - - private void searchForMotes() throws IOException { - comList.clear(); - moteList.clear(); -// hasVerifiedProcess = false; - - /* Connect to COM using external serialdump application */ - String fullCommand; - if (isWindows) { - fullCommand = MOTELIST_WINDOWS; - } else if (isMacos) { - fullCommand = MOTELIST_MACOS; - } else { - fullCommand = MOTELIST_LINUX; - } - - try { - String[] cmd = new String[] { fullCommand }; - moteListProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(moteListProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(moteListProcess.getErrorStream())); - - /* Start thread listening on stdout */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - parseIncomingLine(line); - } - input.close(); - } catch (IOException e) { - System.err.println("Exception when reading from motelist"); - e.printStackTrace(); - } - } - }, "read motelist thread"); - - /* Start thread listening on stderr */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - System.err.println("Motelist error stream> " + line); - } - err.close(); - } catch (IOException e) { - System.err.println("Exception when reading from motelist error stream: " + e); - } - } - }, "read motelist error stream thread"); - - readInput.start(); - readError.start(); - - // Wait for the motelist program to finish executing - readInput.join(); - } catch (Exception e) { - throw (IOException) new IOException("Failed to execute '" + fullCommand + "'").initCause(e); - } - } - - private String[] getComList() { - return comList.toArray(new String[comList.size()]); - } - - private String[] getMoteList() { - return moteList.toArray(new String[moteList.size()]); - } - - public void close() { - if (moteListProcess != null) { - moteListProcess.destroy(); - moteListProcess = null; - } - } - - protected void parseIncomingLine(String line) { - if (line.contains("No devices found") || line.startsWith("Reference")) { - // No Sky connected or title before connected motes -// hasVerifiedProcess = true; - } else if (line.startsWith("-------")) { - // Separator - } else { - Matcher matcher = motePattern.matcher(line); - if (matcher.find()) { - String dev = matcher.group(1); - String no = matcher.group(2); - String comPort = dev + no; - String moteID = comPort; - if (isWindows) { - // Special handling of mote id under Windows - int moteNumber = Integer.parseInt(no); - moteID = Integer.toString(moteNumber - 1); - } - comList.add(comPort); - moteList.add(moteID); - } else { - System.err.println("Motelist> " + line); - } - } - } - - public static String selectComPort(Component parent) { - MoteFinder finder = new MoteFinder(); - try { - String[] motes = finder.getComPorts(); - if (motes == null || motes.length == 0) { - JOptionPane.showMessageDialog(parent, "Could not find any connected motes.", "No mote found", JOptionPane.ERROR_MESSAGE); - return null; - } else if (motes.length == 1) { - // Only one node found - return motes[0]; - } else { - // Several motes found - return (String) JOptionPane.showInputDialog( - parent, "Found multiple connected motes. Please select serial port:", - "Select serial port", JOptionPane.QUESTION_MESSAGE, null, motes, motes[0]); - } - } catch (IOException e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(parent, "Failed to search for connected motes:\n" + e, "Error", JOptionPane.ERROR_MESSAGE); - return null; - } finally { - finder.close(); - } - } - - public static void main(String[] args) throws IOException { - MoteFinder finder = new MoteFinder(); - String[] comPorts = args.length > 0 && "-v".equals(args[0]) ? - finder.getMotes() : finder.getComPorts(); - finder.close(); - if (comPorts == null || comPorts.length == 0) { - System.out.println("No motes connected"); - } else { - for(String port: comPorts) { - System.out.println("Found Sky at " + port); - } - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java deleted file mode 100644 index 11809bf46..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * MoteProgrammer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 10 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.awt.BorderLayout; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.IOException; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; - -/** - * - */ -public class MoteProgrammer { - - private MoteProgrammerProcess[] processes; - private String[] motes; - private String firmwareFile; - - private Window parent; - private JProgressBar progressBar; - protected JTextArea logTextArea; - protected JDialog dialog; - protected JButton closeButton; - private boolean isDone; - - public MoteProgrammer() { - } - - public Window getParentComponent() { - return parent; - } - - public void setParentComponent(Window parent) { - this.parent = parent; - } - - public boolean hasMotes() { - return motes != null && motes.length > 0; - } - - public String[] getMotes() { - return motes; - } - - public void setMotes(String[] motes) { - this.motes = motes; - } - - public void searchForMotes() throws IOException { - MoteFinder finder = new MoteFinder(); - motes = finder.getMotes(); - finder.close(); - } - - public String getFirmwareFile() { - return firmwareFile; - } - - public void setFirmwareFile(String firmwareFile) { - this.firmwareFile = firmwareFile; - } - - public void programMotes() throws IOException { - if (firmwareFile == null) { - throw new IllegalStateException("no firmware"); - } - if (!hasMotes()) { - throw new IllegalStateException("no motes"); - } - File fp = new File(firmwareFile); - if (!fp.canRead()) { - throw new IllegalStateException("can not read firmware file '" + fp.getAbsolutePath() + '\''); - } - if (parent != null) { - // Use GUI - dialog = new JDialog(parent, "Mote Programmer"); - progressBar = new JProgressBar(0, 100); - progressBar.setValue(0); - progressBar.setString("Programming..."); - progressBar.setStringPainted(true); - progressBar.setIndeterminate(true); - dialog.getContentPane().add(progressBar, BorderLayout.NORTH); - - logTextArea = new JTextArea(28, 80); - logTextArea.setEditable(false); - logTextArea.setLineWrap(true); - dialog.getContentPane().add(new JScrollPane(logTextArea), BorderLayout.CENTER); - JPanel panel = new JPanel(); - closeButton = new JButton("Cancel"); - closeButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - MoteProgrammer.this.close(); - } - - }); - panel.add(closeButton); - dialog.getContentPane().add(panel, BorderLayout.SOUTH); - dialog.pack(); - dialog.setLocationRelativeTo(parent); - dialog.setVisible(true); - } - processes = new MoteProgrammerProcess[motes.length]; - isDone = false; - try { - log("Programming " + motes.length + " motes with '" + firmwareFile + '\'', null); - for (int i = 0, n = processes.length; i < n; i++) { - processes[i] = new MoteProgrammerProcess(motes[i], firmwareFile) { - protected void logLine(String line, boolean stderr, Throwable e) { - if (!handleLogLine(this, line, stderr, e)) { - super.logLine(line, stderr, e); - } - } - protected void processEnded() { - handleProcessEnded(this); - } - }; - processes[i].start(); - } - } catch (Exception e) { - throw (IOException) new IOException("Failed to program motes").initCause(e); - } - } - - public synchronized void waitForProcess() throws InterruptedException { - while (!isDone) { - wait(); - } - } - - public void close() { - MoteProgrammerProcess[] processes = this.processes; - if (processes != null) { - this.processes = null; - for (int i = 0, n = processes.length; i < n; i++) { - if (processes[i] != null) { - processes[i].stop(); - } - } - } - if (dialog != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - dialog.setVisible(false); - } - }); - } - isDone = true; - synchronized (this) { - notifyAll(); - } - } - - protected void handleProcessEnded(MoteProgrammerProcess process) { - // Another process has finished - log("Mote@" + process.getMoteID() + "> finished" + (process.hasError() ? " with errors": ""), null); - MoteProgrammerProcess[] processes = this.processes; - if (processes != null) { - int running = 0; - int errors = 0; - for(MoteProgrammerProcess p: processes) { - if (p.isRunning()) { - running++; - } else if (p.hasError()) { - errors++; - } - } - if (running == 0) { - // All processes has finished - isDone = true; - final String doneMessage = "Programming finished with " + errors + " errors."; - log(doneMessage, null); - if (closeButton != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - progressBar.setValue(100); - progressBar.setIndeterminate(false); - progressBar.setString(doneMessage); - closeButton.setText("Close"); - }}); - } - synchronized (this) { - notifyAll(); - } - } - } - } - - protected boolean handleLogLine(MoteProgrammerProcess moteProgrammerProcess, - String line, boolean stderr, final Throwable e) { - log("Mote@" + moteProgrammerProcess.getMoteID() + "> " + line, e); - return true; - } - - private void log(String line, final Throwable e) { - System.err.println(line); - if (e != null) { - e.printStackTrace(); - line += "\n " + e; - } - final String text = line; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - int len = logTextArea.getDocument().getLength(); - if (len == 0) { - logTextArea.append(text); - } else { - logTextArea.append('\n' + text); - len++; - } - logTextArea.setCaretPosition(len + text.length()); - } - }); - } - - public static void main(String[] args) throws IOException { - MoteProgrammer mp = new MoteProgrammer(); - if (args.length < 1 || args.length > 2) { - System.err.println("Usage: MoteProgrammer [mote]"); - System.exit(1); - } - mp.setFirmwareFile(args[0]); - if (args.length == 2) { - mp.setMotes(new String[] { args[1] }); - } else { - mp.searchForMotes(); - } - if (!mp.hasMotes()) { - System.err.println("No motes connected"); - System.exit(1); - } - mp.programMotes(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java deleted file mode 100644 index 1878abc41..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * MoteProgrammerProcess - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 10 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * - */ -public class MoteProgrammerProcess { - - public static final String BSL_WINDOWS = "./tools/msp430-bsl-windows.exe"; - public static final String BSL_LINUX = "./tools/msp430-bsl-linux"; - - private final String moteID; - private final String firmwareFile; - private final String[][] commandSet; - private int retry = 3; - - private Process currentProcess; - private Thread commandThread; - private boolean isRunning; - private boolean hasError; - - public MoteProgrammerProcess(String moteID, String firmwareFile) { - this.moteID = moteID; - this.firmwareFile = firmwareFile; - String osName = System.getProperty("os.name").toLowerCase(); - String bslCommand; - if (osName.startsWith("win")) { - bslCommand = BSL_WINDOWS; - } else { - bslCommand = BSL_LINUX; - } - commandSet = new String[][] { - { bslCommand, "--telosb", "-c", moteID, "-e" }, - { bslCommand, "--telosb", "-c", moteID, "-I", "-p", firmwareFile }, - { bslCommand, "--telosb", "-c", moteID, "-r" } - }; - } - - public String getMoteID() { - return moteID; - } - - public String getFirmwareFile() { - return firmwareFile; - } - - public int getRetry() { - return retry; - } - - public void setRetry(int retry) { - this.retry = retry; - } - - public boolean isRunning() { - return isRunning; - } - - public boolean hasError() { - return hasError; - } - - public void start() { - if (isRunning) { - // Already running - return; - } - isRunning = true; - commandThread = new Thread(new Runnable() { - public void run() { - try { - int count = 0; - do { - if (count > 0) { - logLine("An error occurred. Retrying.", true, null); - } - count++; - hasError = false; - for (int j = 0, m = commandSet.length; j < m && isRunning && !hasError; j++) { - runCommand(commandSet[j]); - Thread.sleep(2000); - } - } while (isRunning && hasError && count < retry); - } catch (Exception e) { - e.printStackTrace(); - } finally { - isRunning = false; - processEnded(); - } - } - }); - commandThread.start(); - } - - public void stop() { - isRunning = false; - Process process = currentProcess; - if (process != null) { - process.destroy(); - } - } - - public void waitForProcess() throws InterruptedException { - if (isRunning && commandThread != null) { - commandThread.join(); - } - } - - protected void processEnded() { - } - - private void runCommand(String[] cmd) throws IOException, InterruptedException { - if (currentProcess != null) { - currentProcess.destroy(); - } - currentProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(currentProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(currentProcess.getErrorStream())); - - /* Start thread listening on stdout */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - handleLine(line, false); - } - input.close(); - } catch (IOException e) { - logLine("Error reading from command", false, e); - } - } - }, "read stdout thread"); - - /* Start thread listening on stderr */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - handleLine(line, true); - } - err.close(); - } catch (IOException e) { - logLine("Error reading from command", true, e); - } - } - }, "read stderr thread"); - - readInput.start(); - readError.start(); - - // Wait for the bsl program to finish executing - readInput.join(); - currentProcess = null; - } - - private void handleLine(String line, boolean stderr) { - if (line.toLowerCase().contains("error")) { - hasError = true; - } - logLine(line, stderr, null); - } - - protected void logLine(String line, boolean stderr, Throwable e) { - if (stderr) { - System.err.println("Programmer@" + moteID + "> " + line); - } else { - System.out.println("Programmer@" + moteID + "> " + line); - } - if (e != null) { - e.printStackTrace(); - } - } - - protected String toString(String[] cmd) { - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = cmd.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(cmd[i]); - } - return sb.toString(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Node.java b/tools/collect-view/src/org/contikios/contiki/collect/Node.java deleted file mode 100644 index 8dc934bbd..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Node.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * Node - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.util.ArrayList; -import java.util.Hashtable; - -/** - * - */ -public class Node implements Comparable { - - private static final boolean SINGLE_LINK = true; - - private SensorDataAggregator sensorDataAggregator; - private ArrayList sensorDataList = new ArrayList(); - private ArrayList links = new ArrayList(); - - private final String id; - private final String name; - - private Hashtable objectTable; - - private long lastActive; - - public Node(String nodeID) { - this(nodeID, nodeID); - } - - public Node(String nodeID, String nodeName) { - this.id = nodeID; - this.name = nodeName; - sensorDataAggregator = new SensorDataAggregator(this); - } - - public final String getID() { - return id; - } - - public final String getName() { - return name; - } - - public long getLastActive() { - return lastActive; - } - - public void setLastActive(long lastActive) { - this.lastActive = lastActive; - } - - @Override - public int compareTo(Node o) { - String i1 = id; - String i2 = o.getID(); - // Shorter id first (4.0 before 10.0) - if (i1.length() == i2.length()) { - return i1.compareTo(i2); - } - return i1.length() - i2.length(); - } - - public String toString() { - return name; - } - - - // ------------------------------------------------------------------- - // Attributes - // ------------------------------------------------------------------- - - public Object getAttribute(String key) { - return getAttribute(key, null); - } - - public Object getAttribute(String key, Object defaultValue) { - if (objectTable == null) { - return null; - } - Object val = objectTable.get(key); - return val == null ? defaultValue : val; - } - - public void setAttribute(String key, Object value) { - if (objectTable == null) { - objectTable = new Hashtable(); - } - objectTable.put(key, value); - } - - public void clearAttributes() { - if (objectTable != null) { - objectTable.clear(); - } - } - - - // ------------------------------------------------------------------- - // SensorData - // ------------------------------------------------------------------- - - public SensorDataAggregator getSensorDataAggregator() { - return sensorDataAggregator; - } - - public SensorData[] getAllSensorData() { - return sensorDataList.toArray(new SensorData[sensorDataList.size()]); - } - - public void removeAllSensorData() { - sensorDataList.clear(); - sensorDataAggregator.clear(); - } - - public SensorData getSensorData(int index) { - return sensorDataList.get(index); - } - - public int getSensorDataCount() { - return sensorDataList.size(); - } - - public boolean addSensorData(SensorData data) { - if (sensorDataList.size() > 0) { - SensorData last = sensorDataList.get(sensorDataList.size() - 1); - if (data.getNodeTime() < last.getNodeTime()) { - // Sensor data already added - System.out.println("SensorData: ignoring (time " + (data.getNodeTime() - last.getNodeTime()) - + "msec): " + data); - return false; - } - } - sensorDataList.add(data); - sensorDataAggregator.addSensorData(data); - return true; - } - - - // ------------------------------------------------------------------- - // Links - // ------------------------------------------------------------------- - - public Link getLink(Node node) { - for(Link l: links) { - if (l.node == node) { - return l; - } - } - - // Add new link - Link l = new Link(node); - if (SINGLE_LINK) { - links.clear(); - } - links.add(l); - return l; - } - - public Link getLink(int index) { - return links.get(index); - } - - public int getLinkCount() { - return links.size(); - } - - public void removeLink(Node node) { - for (int i = 0, n = links.size(); i < n; i++) { - Link l = links.get(i); - if (l.node == node) { - links.remove(i); - break; - } - } - } - - public void clearLinks() { - links.clear(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java deleted file mode 100644 index 8e3445d58..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * SensorData - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2011/01/09 21:06:10 $ - * $Revision: 1.2 $ - */ - -package org.contikios.contiki.collect; -import java.util.Arrays; - -/** - * - */ -public class SensorData implements SensorInfo { - - private final Node node; - private final int[] values; - private final long nodeTime; - private final long systemTime; - private int seqno; - private boolean isDuplicate; - - public SensorData(Node node, int[] values, long systemTime) { - this.node = node; - this.values = values; - this.nodeTime = ((values[TIMESTAMP1] << 16) + values[TIMESTAMP2]) * 1000L; - this.systemTime = systemTime; - this.seqno = values[SEQNO]; - } - - public Node getNode() { - return node; - } - - public String getNodeID() { - return node.getID(); - } - - public boolean isDuplicate() { - return isDuplicate; - } - - public void setDuplicate(boolean isDuplicate) { - this.isDuplicate = isDuplicate; - } - - public int getSeqno() { - return seqno; - } - - public void setSeqno(int seqno) { - this.seqno = seqno; - } - - public int getValue(int index) { - return values[index]; - } - - public int getValueCount() { - return values.length; - } - - public long getNodeTime() { - return nodeTime; - } - - public long getSystemTime() { - return systemTime; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - if (systemTime > 0L) { - sb.append(systemTime).append(' '); - } - for (int i = 0, n = values.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(values[i]); - } - return sb.toString(); - } - - public static SensorData parseSensorData(CollectServer server, String line) { - return parseSensorData(server, line, 0); - } - - public static SensorData parseSensorData(CollectServer server, String line, long systemTime) { - String[] components = line.trim().split("[ \t]+"); - // Check if COOJA log - if (components.length == VALUES_COUNT + 2 && components[1].startsWith("ID:")) { - if (!components[2].equals("" + VALUES_COUNT)) { - // Ignore non sensor data - return null; - } - try { - systemTime = Long.parseLong(components[0]); - components = Arrays.copyOfRange(components, 2, components.length); - } catch (NumberFormatException e) { - // First column does not seem to be system time - } - - } else if (components[0].length() > 8) { - // Sensor data prefixed with system time - try { - systemTime = Long.parseLong(components[0]); - components = Arrays.copyOfRange(components, 1, components.length); - } catch (NumberFormatException e) { - // First column does not seem to be system time - } - } - if (components.length != SensorData.VALUES_COUNT) { - return null; - } - // Sensor data line (probably) - int[] data = parseToInt(components); - if (data == null || data[0] != VALUES_COUNT) { - System.err.println("Failed to parse data line: '" + line + "'"); - return null; - } - String nodeID = mapNodeID(data[NODE_ID]); - Node node = server.addNode(nodeID); - return new SensorData(node, data, systemTime); - } - - public static String mapNodeID(int nodeID) { - return "" + (nodeID & 0xff) + '.' + ((nodeID >> 8) & 0xff); - } - - private static int[] parseToInt(String[] text) { - try { - int[] data = new int[text.length]; - for (int i = 0, n = data.length; i < n; i++) { - data[i] = Integer.parseInt(text[i]); - } - return data; - } catch (NumberFormatException e) { - return null; - } - } - - public double getCPUPower() { - return (values[TIME_CPU] * POWER_CPU) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getLPMPower() { - return (values[TIME_LPM] * POWER_LPM) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getListenPower() { - return (values[TIME_LISTEN] * POWER_LISTEN) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getTransmitPower() { - return (values[TIME_TRANSMIT] * POWER_TRANSMIT) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAveragePower() { - return (values[TIME_CPU] * POWER_CPU + values[TIME_LPM] * POWER_LPM - + values[TIME_LISTEN] * POWER_LISTEN + values[TIME_TRANSMIT] * POWER_TRANSMIT) - / (values[TIME_CPU] + values[TIME_LPM]); - } - - public long getPowerMeasureTime() { - return (1000L * (values[TIME_CPU] + values[TIME_LPM])) / TICKS_PER_SECOND; - } - - public double getTemperature() { - return -39.6 + 0.01 * values[TEMPERATURE]; - } - - public double getBatteryVoltage() { - return values[BATTERY_VOLTAGE] * 2 * 2.5 / 4096.0; - } - - public double getBatteryIndicator() { - return values[BATTERY_INDICATOR]; - } - - public double getRadioIntensity() { - return values[RSSI]; - } - - public double getLatency() { - return values[LATENCY] / 32678.0; - } - - public double getHumidity() { - double v = -4.0 + 405.0 * values[HUMIDITY] / 10000.0; - if(v > 100) { - return 100; - } - return v; - } - - public double getLight1() { - return 10.0 * values[LIGHT1] / 7.0; - } - - public double getLight2() { - return 46.0 * values[LIGHT2] / 10.0; - } - - public String getBestNeighborID() { - return values[BEST_NEIGHBOR] > 0 ? mapNodeID(values[BEST_NEIGHBOR]): null; - } - - public double getBestNeighborETX() { - return values[BEST_NEIGHBOR_ETX] / 8.0; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java deleted file mode 100644 index a8bfc2a95..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * SensorDataAggregator - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 20 aug 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class SensorDataAggregator implements SensorInfo { - - private final Node node; - private long[] values; - private int minSeqno = Integer.MAX_VALUE; - private int maxSeqno = Integer.MIN_VALUE; - private int seqnoDelta = 0; - private int dataCount; - private int duplicates = 0; - private int lost = 0; - private int nodeRestartCount = 0; - private int nextHopChangeCount = 0; - private int lastNextHop = -1; - private long shortestPeriod = Long.MAX_VALUE; - private long longestPeriod = 0; - - public SensorDataAggregator(Node node) { - this.node = node; - this.values = new long[VALUES_COUNT]; - } - - public Node getNode() { - return node; - } - - public String getNodeID() { - return node.getID(); - } - - public long getValue(int index) { - return values[index]; - } - - public double getAverageValue(int index) { - return dataCount > 0 ? (double)values[index] / (double)dataCount : 0; - } - - public int getValueCount() { - return values.length; - } - - public int getDataCount() { - return dataCount; - } - - public void addSensorData(SensorData data) { - int seqn = data.getValue(SEQNO); - int s = seqn + seqnoDelta; - - int bestNeighbor = data.getValue(BEST_NEIGHBOR); - if (lastNextHop != bestNeighbor && lastNextHop >= 0) { - nextHopChangeCount++; - } - lastNextHop = bestNeighbor; - - if (s <= maxSeqno) { - // Check for duplicates among the last 5 packets - for(int n = node.getSensorDataCount() - 1, i = n > 5 ? n - 5 : 0; i < n; i++) { - SensorData sd = node.getSensorData(i); - if (sd.getValue(SEQNO) != seqn || sd == data || sd.getValueCount() != data.getValueCount()) { - // Not a duplicate - } else if (Math.abs(data.getNodeTime() - sd.getNodeTime()) > 180000) { - // Too long time between packets. Not a duplicate. -// System.err.println("Too long time between packets with same seqno from " -// + data.getNode() + ": " -// + (Math.abs(data.getNodeTime() - sd.getNodeTime()) / 1000) -// + " sec, " + (n - i) + " packets ago"); - } else { - data.setDuplicate(true); - - // Verify that the packet is a duplicate - for(int j = DATA_LEN2, m = data.getValueCount(); j < m; j++) { - if (sd.getValue(j) != data.getValue(j)) { - data.setDuplicate(false); -// System.out.println("NOT Duplicate: " + data.getNode() + " (" -// + (n - i) + ": " -// + ((data.getNodeTime() - sd.getNodeTime()) / 1000) + "sek): " -// + seqn + " value[" + j + "]: " + sd.getValue(j) + " != " -// + data.getValue(j)); - break; - } - } - if (data.isDuplicate()) { -// System.out.println("Duplicate: " + data.getNode() + ": " + seqn -// + ": " -// + (Math.abs(data.getNodeTime() - sd.getNodeTime()) / 1000) -// + " sec, " + (n - i) + " packets ago"); - duplicates++; - break; - } - } - } - } - - if (!data.isDuplicate()) { - for (int i = 0, n = Math.min(VALUES_COUNT, data.getValueCount()); i < n; i++) { - values[i] += data.getValue(i); - } - - if (node.getSensorDataCount() > 1) { - long timeDiff = data.getNodeTime() - node.getSensorData(node.getSensorDataCount() - 2).getNodeTime(); - if (timeDiff > longestPeriod) { - longestPeriod = timeDiff; - } - if (timeDiff < shortestPeriod) { - shortestPeriod = timeDiff; - } - } - if (dataCount == 0) { - // First packet from node. - } else if (maxSeqno - s > 2) { - // Handle sequence number overflow. - seqnoDelta = maxSeqno + 1; - s = seqnoDelta + seqn; - if (seqn > 127) { - // Sequence number restarted at 128 (to separate node restarts - // from sequence number overflow). - seqn -= 128; - seqnoDelta -= 128; - s -= 128; - } else { - // Sequence number restarted at 0. This is usually an indication that - // the node restarted. - nodeRestartCount++; - } - if (seqn > 0) { - lost += seqn; - } - } else if (s > maxSeqno + 1){ - lost += s - (maxSeqno + 1); - } - if (s < minSeqno) minSeqno = s; - if (s > maxSeqno) maxSeqno = s; - dataCount++; - } - data.setSeqno(s); - } - - public void clear() { - for (int i = 0, n = values.length; i < n; i++) { - values[i] = 0L; - } - dataCount = 0; - duplicates = 0; - lost = 0; - nodeRestartCount = 0; - nextHopChangeCount = 0; - lastNextHop = 0; - minSeqno = Integer.MAX_VALUE; - maxSeqno = Integer.MIN_VALUE; - seqnoDelta = 0; - shortestPeriod = Long.MAX_VALUE; - longestPeriod = 0; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = values.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(values[i]); - } - return sb.toString(); - } - - public double getCPUPower() { - return (values[TIME_CPU] * POWER_CPU) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getLPMPower() { - return (values[TIME_LPM] * POWER_LPM) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getListenPower() { - return (values[TIME_LISTEN] * POWER_LISTEN) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getTransmitPower() { - return (values[TIME_TRANSMIT] * POWER_TRANSMIT) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAveragePower() { - return (values[TIME_CPU] * POWER_CPU + values[TIME_LPM] * POWER_LPM - + values[TIME_LISTEN] * POWER_LISTEN + values[TIME_TRANSMIT] * POWER_TRANSMIT) - / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAverageDutyCycle(int index) { - return (double)(values[index]) / (double)(values[TIME_CPU] + values[TIME_LPM]); - } - - public long getPowerMeasureTime() { - return (1000L * (values[TIME_CPU] + values[TIME_LPM])) / TICKS_PER_SECOND; - } - - public double getAverageTemperature() { - return dataCount > 0 ? (-39.6 + 0.01 * (values[TEMPERATURE] / dataCount)) : 0.0; - } - - public double getAverageRtmetric() { - return getAverageValue(RTMETRIC); - } - - public double getAverageRadioIntensity() { - return getAverageValue(RSSI); - } - - public double getAverageLatency() { - return getAverageValue(LATENCY) / 4096.0; - } - - public double getAverageHumidity() { - double v = 0.0; - if (dataCount > 0) { - v = -4.0 + 405.0 * (values[HUMIDITY] / dataCount) / 10000.0; - } - return v > 100 ? 100 : v; - } - - public double getAverageLight1() { - return 10.0 * getAverageValue(LIGHT1) / 7.0; - } - - public double getAverageLight2() { - return 46.0 * getAverageValue(LIGHT2) / 10.0; - } - - public double getAverageBestNeighborETX() { - return getAverageValue(BEST_NEIGHBOR_ETX) / 8.0; - } - - public int getPacketCount() { - return node.getSensorDataCount(); - } - - public int getNextHopChangeCount() { - return nextHopChangeCount; - } - - public int getEstimatedRestarts() { - return nodeRestartCount; - } - - public int getEstimatedLostCount() { - return lost; - } - - public int getDuplicateCount() { - return duplicates; - } - - public int getMinSeqno() { - return minSeqno; - } - - public int getMaxSeqno() { - return maxSeqno; - } - - public long getAveragePeriod() { - if (dataCount > 1) { - long first = node.getSensorData(0).getNodeTime(); - long last = node.getSensorData(node.getSensorDataCount() - 1).getNodeTime(); - return (last - first) / dataCount; - } - return 0; - } - - public long getShortestPeriod() { - return shortestPeriod < Long.MAX_VALUE ? shortestPeriod : 0; - } - - public long getLongestPeriod() { - return longestPeriod; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java deleted file mode 100644 index 51043d1c3..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * SensorInfo - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 20 aug 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - - -/** - * - */ -public interface SensorInfo { - - public static final long TICKS_PER_SECOND = 4096L; - public static final double VOLTAGE = 3; - public static final double POWER_CPU = 1.800 * VOLTAGE; /* mW */ - public static final double POWER_LPM = 0.0545 * VOLTAGE; /* mW */ - public static final double POWER_TRANSMIT = 17.7 * VOLTAGE; /* mW */ - public static final double POWER_LISTEN = 20.0 * VOLTAGE; /* mW */ - - public static final int DATA_LEN = 0; - public static final int TIMESTAMP1 = 1; - public static final int TIMESTAMP2 = 2; - public static final int TIMESYNCTIMESTAMP = 3; - public static final int NODE_ID = 4; - public static final int SEQNO = 5; - public static final int HOPS = 6; - public static final int LATENCY = 7; - public static final int DATA_LEN2 = 8; - public static final int CLOCK = 9; - public static final int TIMESYNCHTIME = 10; - public static final int TIME_CPU = 11; - public static final int TIME_LPM = 12; - public static final int TIME_TRANSMIT = 13; - public static final int TIME_LISTEN = 14; - public static final int BEST_NEIGHBOR = 15; - public static final int BEST_NEIGHBOR_ETX = 16; - public static final int RTMETRIC = 17; - public static final int NUM_NEIGHBORS = 18; - public static final int BEACON_INTERVAL = 19; - public static final int BATTERY_VOLTAGE = 20; - public static final int BATTERY_INDICATOR = 21; - public static final int LIGHT1 = 22; - public static final int LIGHT2 = 23; - public static final int TEMPERATURE = 24; - public static final int HUMIDITY = 25; - public static final int RSSI = 26; - - public static final int VALUES_COUNT = 30; - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java deleted file mode 100644 index c2d140a03..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * SerialConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.PrintWriter; - -/** - * - */ -public abstract class SerialConnection { - - protected final SerialConnectionListener listener; - - protected boolean isSerialOutputSupported = true; - - protected String comPort; - protected boolean isOpen; - protected boolean isClosed = true; - protected String lastError; - - protected PrintWriter serialOutput; - - protected SerialConnection(SerialConnectionListener listener) { - this.listener = listener; - } - - public boolean isMultiplePortsSupported() { - return false; - } - - public void setSerialOutputSupported(boolean isSerialOutputSupported) { - this.isSerialOutputSupported = isSerialOutputSupported; - } - - public boolean isSerialOutputSupported() { - return isSerialOutputSupported; - } - - public boolean isOpen() { - return isOpen; - } - - public boolean isClosed() { - return isClosed; - } - - public abstract String getConnectionName(); - - public String getComPort() { - return comPort; - } - - public void setComPort(String comPort) { - this.comPort = comPort; - } - - public String getLastError() { - return lastError; - } - - protected PrintWriter getSerialOutput() { - return serialOutput; - } - - protected void setSerialOutput(PrintWriter serialOutput) { - this.serialOutput = serialOutput; - } - - public void writeSerialData(String data) { - PrintWriter serialOutput = this.serialOutput; - if (serialOutput != null) { - serialOutput.println(data); - serialOutput.flush(); - } - } - - public abstract void open(String comPort); - - public final void close() { - isClosed = true; - lastError = null; - closeConnection(); - } - - protected final void closeConnection() { - isOpen = false; - if (serialOutput != null) { - serialOutput.close(); - serialOutput = null; - } - doClose(); - serialClosed(); - } - - protected abstract void doClose(); - - protected final void serialData(String line) { - listener.serialData(this, line); - } - - protected final void serialOpened() { - listener.serialOpened(this); - } - - protected final void serialClosed() { - listener.serialClosed(this); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java deleted file mode 100644 index 5e266c6e1..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * SerialConnectionListener - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ -package org.contikios.contiki.collect; - -public interface SerialConnectionListener { - - public void serialData(SerialConnection connection, String line); - - public void serialOpened(SerialConnection connection); - - public void serialClosed(SerialConnection connection); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java deleted file mode 100644 index c624ea64a..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * SerialDumpConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class SerialDumpConnection extends CommandConnection { - - public static final String SERIALDUMP_WINDOWS = "./tools/serialdump-windows.exe"; - public static final String SERIALDUMP_LINUX = "./tools/serialdump-linux"; - public static final String SERIALDUMP_MACOS = "./tools/serialdump-macos"; - - public SerialDumpConnection(SerialConnectionListener listener) { - super(listener); - } - - @Override - public boolean isMultiplePortsSupported() { - return true; - } - - @Override - public String getConnectionName() { - return comPort; - } - - @Override - public void open(String comPort) { - if (comPort == null) { - throw new IllegalStateException("no com port"); - } - - /* Connect to COM using external serialdump application */ - String osName = System.getProperty("os.name").toLowerCase(); - String fullCommand; - if (osName.startsWith("win")) { - fullCommand = SERIALDUMP_WINDOWS + " " + "-b115200" + " " + getMappedComPortForWindows(comPort); - } else if (osName.startsWith("mac")) { - fullCommand = SERIALDUMP_MACOS + " " + "-b115200" + " " + comPort; - } else { - fullCommand = SERIALDUMP_LINUX + " " + "-b115200" + " " + comPort; - } - setCommand(fullCommand); - super.open(comPort); - } - - @Override - protected void standardData(String line) { - serialData(line); - } - - @Override - protected void errorData(String line) { - if (!isOpen && line.startsWith("connecting") && line.endsWith("[OK]")) { - isOpen = true; - serialOpened(); - } else { - super.errorData(line); - } - } - - private String getMappedComPortForWindows(String comPort) { - if (comPort.startsWith("COM")) { - comPort = "/dev/com" + comPort.substring(3); - } - return comPort; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java deleted file mode 100644 index 337a01a29..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * StdinConnection - * - * Authors : Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -/** - * - */ -public class StdinConnection extends SerialConnection { - - private PrintWriter stdout; - - public StdinConnection(SerialConnectionListener listener) { - super(listener); - // Redirect standard out as standard err to use standard out for serial output - stdout = new PrintWriter(new OutputStreamWriter(System.out)); - System.setOut(System.err); - } - - @Override - public String getConnectionName() { - return ""; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - final BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); - setSerialOutput(stdout); - - /* Start thread listening on standard in */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - serialData(line); - // Do not send data too fast - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - input.close(); - System.out.println("SerialConnection stdin terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection stdin: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "read input stream thread"); - - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open stdin for reading: " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java deleted file mode 100644 index 6a04f8b65..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, Swedish Institute of Computer Science. - * 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. - * - * ----------------------------------------------------------------- - * - * TCPClientConnection - * - * Authors : Niclas Finne - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.net.Socket; - -/** - * - */ -public class TCPClientConnection extends SerialConnection { - - private final String host; - private final int port; - - private Socket client; - private BufferedReader in; - private PrintStream out; - - public TCPClientConnection(SerialConnectionListener listener, String host, int port) { - super(listener); - this.host = host; - this.port = port; - } - - @Override - public String getConnectionName() { - return "'; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - client = new Socket(host, port); - in = new BufferedReader(new InputStreamReader(client.getInputStream())); - out = new PrintStream(client.getOutputStream()); - System.out.println("Opened TCP connection to " + host + ':' + port); - /* Start thread listening on UDP */ - Thread readInput = new Thread(new Runnable() { - public void run() { - try { - String line; - while (isOpen && (line = in.readLine()) != null) { - serialData(line); - } - } catch (IOException e) { - lastError = "Error when reading from SerialConnection TCP: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } finally { - System.out.println("SerialConnection TCP terminated."); - closeConnection(); - } - } - }, "TCP thread"); - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open TCP connection to " + host + ':' + port + ": " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - try { - if (in != null) { - in.close(); - in = null; - } - if (out != null) { - out.close(); - out = null; - } - if (client != null) { - client.close(); - client = null; - } - } catch (IOException e) { - e.printStackTrace(); - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java deleted file mode 100644 index ae1ed52a9..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2011, Swedish Institute of Computer Science. - * 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. - * - * ----------------------------------------------------------------- - * - * UDPConnection - * - * Authors : Niclas Finne - * Created : 1 June 2011 - */ - -package org.contikios.contiki.collect; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.io.*; -/** - * - */ -public class UDPConnection extends SerialConnection { - - private final int port; -private DatagramSocket serverSocket; - - public UDPConnection(SerialConnectionListener listener, int port) { - super(listener); - this.port = port; - } - - @Override - public String getConnectionName() { - return ""; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - serverSocket = new DatagramSocket(port); - System.out.println("Opened UDP port: " + port); - /* Start thread listening on UDP */ - Thread readInput = new Thread(new Runnable() { - public void run() { - byte[] data = new byte[1024]; - try { - while (isOpen) { - DatagramPacket packet = new DatagramPacket(data, data.length); - serverSocket.receive(packet); - - InetAddress addr = packet.getAddress(); - System.out.println("UDP: received " + packet.getLength() + " bytes from " + addr.getHostAddress() + ":" + packet.getPort()); - - StringWriter strOut = new StringWriter(); - PrintWriter out = new PrintWriter(strOut); - int payloadLen = packet.getLength() - 2; - out.printf("%d", 8 + payloadLen / 2); - /* Timestamp. Ignore time synch for now. */ - long time = System.currentTimeMillis() / 1000; - out.printf(" %d %d 0", - ((time >> 16) & 0xffff), time & 0xffff); - byte[] payload = packet.getData(); - int seqno = payload[0] & 0xff; - int hops = 0; /* how to get TTL / hot limit in Java??? */ - byte[] address = addr.getAddress(); - /* Ignore latency for now */ - out.printf(" %d %d %d %d", - ((address[14] & 0xff) + - ((address[15] & 0xff) << 8))&0xffff, seqno, hops, 0); - int d = 0; - for(int i = 0; i < payloadLen ; i += 2) { - d = (payload[i + 2] & 0xff) + ((payload[i + 3] & 0xff) << 8); - out.printf(" %d", d & 0xffff); - } - - String line = strOut.toString(); - serialData(line); - } - System.out.println("SerialConnection UDP terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection UDP: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "UDP thread"); - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open UDP server at port " + port + ": " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - if (serverSocket != null) { - serverSocket.close(); - serverSocket = null; - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java deleted file mode 100644 index f898e0e6a..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * ----------------------------------------------------------------- - * - * PacketChartPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 6 sep 2010 - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JPanel; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.time.Minute; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class AggregatedTimeChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = 2100788758213434540L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final TimeSeries series; - - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - - private Node[] selectedNodes; - private HashMap selectedMap = new HashMap(); - - public AggregatedTimeChartPanel(CollectServer server, String category, String title, - String timeAxisLabel, String valueAxisLabel) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.series = new TimeSeries(title, Minute.class); - TimeSeriesCollection timeSeries = new TimeSeriesCollection(series); - this.chart = ChartFactory.createTimeSeriesChart( - title, timeAxisLabel, valueAxisLabel, timeSeries, - false, true, false - ); - this.chartPanel = new ChartPanel(chart); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - setBaseShapeVisible(false); - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodesSelected(Node[] nodes) { - if (isVisible()) { - updateSelected(nodes); - } - } - - private void updateSelected(Node[] nodes) { - if (this.selectedNodes != nodes) { - this.selectedNodes = nodes; - this.selectedMap.clear(); - if (nodes != null) { - for(Node node : nodes) { - this.selectedMap.put(node, createState(node)); - } - } - updateCharts(); - } - } - - @Override - public void nodeDataReceived(SensorData data) { - if (isVisible() && selectedMap.get(data.getNode()) != null) { - updateCharts(); - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - int duplicates = 0; - int total = 0; - series.clear(); - if (this.selectedNodes != null && server.getSensorDataCount() > 0) { - long minute = server.getSensorData(0).getNodeTime() / 60000; - long lastMinute = minute; - int count = 0; - clearState(selectedMap); - for(int i = 0; i < server.getSensorDataCount(); i++) { - SensorData sd = server.getSensorData(i); - T nodeState = selectedMap.get(sd.getNode()); - if (nodeState != null) { - if (sd.isDuplicate()) { - duplicates++; - } else { - long min = sd.getNodeTime() / 60000; - if (min != minute) { - if (lastMinute < minute) { - series.add(new Minute(new Date(lastMinute * 60000L)), 0); - if (lastMinute < minute - 1) { - series.add(new Minute(new Date((minute - 1) * 60000L)), 0); - } - } - series.add(new Minute(new Date(minute * 60000L)), getTotalDataValue(count)); - count = 0; - lastMinute = minute + 1; - minute = min; - } - count += getSensorDataValue(sd, nodeState); - } - total++; - } - } - } - chart.setTitle(getTitle(selectedMap.size(), total, duplicates)); - } - - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return title; - } - - protected abstract T createState(Node node); - - protected void clearState(Map map) { - } - - protected int getTotalDataValue(int value) { - return value; - } - - protected abstract int getSensorDataValue(SensorData sd, T nodeState); - - public boolean getBaseShapeVisible() { - return ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).getBaseShapesVisible(); - } - - public void setBaseShapeVisible(boolean visible) { - ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).setBaseShapesVisible(visible); - } - - public double getRangeMinimumSize() { - return chart.getXYPlot().getRangeAxis().getAutoRangeMinimumSize(); - } - - public void setRangeMinimumSize(double size) { - chart.getXYPlot().getRangeAxis().setAutoRangeMinimumSize(size); - } - - public void setVisible(boolean visible) { - updateSelected(visible ? server.getSelectedNodes() : null); - super.setVisible(visible); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java deleted file mode 100644 index cb6969331..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * PowerPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GradientPaint; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import javax.swing.JPanel; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.BarRenderer; -import org.jfree.data.category.DefaultCategoryDataset; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class BarChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = 7664283678708048061L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final String[] categories; - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - protected final DefaultCategoryDataset dataset; - - private boolean isShowingAllNodes = false; - private int categoryOrder = 0; - - protected BarChartPanel(CollectServer server, String category, String title, - String chartTitle, String domainAxisLabel, String valueAxisLabel, - String[] categories) { - this(server, category, title, chartTitle, domainAxisLabel, valueAxisLabel, categories, true); - } - - protected BarChartPanel(CollectServer server, String category, String title, - String chartTitle, String domainAxisLabel, String valueAxisLabel, - String[] categories, boolean stackedChart) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.categories = categories; - - /* Create chart with power of all nodes */ - dataset = new DefaultCategoryDataset(); - if (stackedChart) { - this.chart = ChartFactory.createStackedBarChart(chartTitle, - domainAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, - categories.length > 1, true, false); - } else { - this.chart = ChartFactory.createBarChart(chartTitle, - domainAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, - categories.length > 1, true, false); - if (categories.length > 1) { - CategoryPlot plot = chart.getCategoryPlot(); - BarRenderer renderer = (BarRenderer) plot.getRenderer(); - renderer.setItemMargin(0); - } - } - this.chartPanel = new ChartPanel(chart, false); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - if (categories.length > 1) { - this.chartPanel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - categoryOrder++; - updateCharts(); - } - }); - } - - CategoryPlot plot = (CategoryPlot) chart.getPlot(); - BarRenderer renderer = (BarRenderer) plot.getRenderer(); - if (categories.length < 3) { - renderer.setDrawBarOutline(false); - - GradientPaint gp = new GradientPaint(0.0f, 0.0f, Color.RED, - 0.0f, 0.0f, new Color(128, 0, 0)); - renderer.setSeriesPaint(0, gp); - if (categories.length > 1) { - gp = new GradientPaint(0.0f, 0.0f, Color.BLUE, - 0.0f, 0.0f, new Color(0, 0, 128)); - renderer.setSeriesPaint(1, gp); - } - } else { - renderer.setDrawBarOutline(true); - } - - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - public boolean isShowingAllNodes() { - return isShowingAllNodes; - } - - public void setShowingAllNodes(boolean isShowingAllNodes) { - if (this.isShowingAllNodes != isShowingAllNodes) { - this.isShowingAllNodes = isShowingAllNodes; - if (isVisible()) { - updateCharts(); - } - } - } - - @Override - public void nodeAdded(Node node) { - if (isVisible()) { - int count = node.getSensorDataCount(); - if (count > 0 || isShowingAllNodes) { - addNode(node); - } - if (count > 0) { - addSensorData(node.getSensorData(count - 1)); - } - } - } - - @Override - public void nodesSelected(Node[] nodes) { - } - - @Override - public void nodeDataReceived(SensorData data) { - if (isVisible()) { - addSensorData(data); - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - dataset.clear(); - Node[] nodes = server.getNodes(); - if (nodes != null) { - for (int i = 0, n = nodes.length; i < n; i++) { - int count = nodes[i].getSensorDataCount(); - if (count > 0 || isShowingAllNodes) { - addNode(nodes[i]); - } - if (count > 0) { - addSensorData(nodes[i].getSensorData(count - 1)); - } - } - } - } - - private void addNode(Node node) { - String name = node.getName(); - for (int j = 0, m = categories.length; j < m; j++) { - dataset.addValue(0, categories[(j + categoryOrder) % categories.length], name); - } - } - - public void setVisible(boolean visible) { - if (visible) { - updateCharts(); - } else { - dataset.clear(); - } - super.setVisible(visible); - } - - protected abstract void addSensorData(SensorData data); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java deleted file mode 100644 index 5a6652b94..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * MapPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/23 16:21:48 $ - * $Revision: 1.4 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridLayout; -import java.awt.Polygon; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.Properties; -import java.util.logging.Logger; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFormattedTextField; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JSlider; -import javax.swing.Timer; -import javax.swing.border.LineBorder; -import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Configurable; -import org.contikios.contiki.collect.Link; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class MapPanel extends JPanel implements Configurable, Visualizer, ActionListener, MouseListener, MouseMotionListener { - - private static final long serialVersionUID = -8256619482599309425L; - - private static final Logger log = - Logger.getLogger(MapPanel.class.getName()); - - private static final boolean VISUAL_DRAG = true; - - private static final Color LINK_COLOR = new Color(0x40, 0x40, 0xf0, 0xff); - - private static final int delta = 7; - - private final CollectServer server; - private final String category; - private final boolean isMap; - private String title; - - private Timer timer; - - private JPopupMenu popupMenu; - private JCheckBoxMenuItem layoutItem; - private JCheckBoxMenuItem lockedItem; - private JMenuItem shakeItem; -// private JCheckBoxMenuItem dragItem; - private JCheckBoxMenuItem backgroundItem; - private JCheckBoxMenuItem showNetworkItem; - private JCheckBoxMenuItem configItem; - private JMenuItem resetNetworkItem; - private MapNode popupNode; - - private Hashtable nodeTable = new Hashtable(); - private MapNode[] nodeList = new MapNode[0]; - private boolean updateNodeList; - - private MapNode selectedNode; - private ArrayList selectedMapNodes = new ArrayList(); - private Node[] selectedNodes; - private MapNode draggedNode; - private long draggedTime; - - private ImageIcon mapImage; - private String mapName; - private boolean showBackground; - - private int layoutRepel = 100; - private int layoutAttract = 50; - private int layoutGravity = 1; - - private double etxFactor = 1.0; - - private boolean isLayoutActive = true; - private boolean hideNetwork = false; - - protected JPanel configPanel; - - public MapPanel(CollectServer server, String title, String category, boolean isMap) { - super(null); - this.server = server; - this.title = title; - this.category = category; - this.isMap = isMap; - setPreferredSize(new Dimension(300, 200)); - - popupMenu = new JPopupMenu(getTitle()); - if (!isMap) { - layoutItem = createCheckBoxMenuItem(popupMenu, "Update Layout", isLayoutActive); - popupMenu.add(layoutItem); - - lockedItem = createCheckBoxMenuItem(popupMenu, "Fixed Node Position", false); - shakeItem = createMenuItem(popupMenu, "Shake Nodes"); - popupMenu.addSeparator(); - } - - showNetworkItem = createCheckBoxMenuItem(popupMenu, "Show Network Info", true); - resetNetworkItem = createMenuItem(popupMenu, "Reset Network"); - popupMenu.addSeparator(); - if (isMap) { - backgroundItem = createCheckBoxMenuItem(popupMenu, "Show Background", false); - backgroundItem.setEnabled(false); - } else { - configItem = createCheckBoxMenuItem(popupMenu, "Show Layout Settings", false); - } - -// popupMenu.addSeparator(); -// dragItem = new JCheckBoxMenuItem("Visible Drag", true); -// popupMenu.add(dragItem); - - setBackground(Color.white); - addMouseListener(this); - addMouseMotionListener(this); - - if (!isMap) { - timer = new Timer(100, this); - - configPanel = new JPanel(new GridLayout(0, 1)); - configPanel.setBorder(LineBorder.createBlackLineBorder()); - - JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, 1000 - layoutAttract); - slider.setBorder(new TitledBorder("Attract Factor: " + (1000 - layoutAttract))); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutAttract = 1000 - slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Attract Factor: " + slider.getValue()); - } - }); - configPanel.add(slider); - - slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, layoutRepel); - slider.setBorder(new TitledBorder("Repel Range: " + layoutRepel)); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutRepel = slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Repel Range: " + layoutRepel); - } - }); - configPanel.add(slider); - - slider = new JSlider(JSlider.HORIZONTAL, 0, 100, layoutGravity); - slider.setBorder(new TitledBorder("Gravity: " + layoutGravity)); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutGravity = slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Gravity: " + layoutGravity); - } - }); - configPanel.add(slider); - - final JFormattedTextField etxField = new JFormattedTextField(new Double(etxFactor)); - etxField.setBorder(BorderFactory.createTitledBorder("ETX factor")); - etxField.setColumns(5); - etxField.addPropertyChangeListener("value", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - etxFactor = ((Number)etxField.getValue()).doubleValue(); - repaint(); - } - }); - configPanel.add(etxField); - - configPanel.setVisible(false); - add(configPanel); - - addComponentListener(new ComponentAdapter() { - public void componentResized(ComponentEvent ev) { - if (configPanel.isVisible()) { - updateConfigLayout(); - } - } - }); - } - } - - public String getMapBackground() { - return isMap ? mapName : null; - } - - public boolean setMapBackground(String image) { - if (!isMap) { - return false; - } - if (image == null) { - mapImage = null; - mapName = null; - backgroundItem.setEnabled(false); - backgroundItem.setSelected(false); - showBackground = false; - repaint(); - return true; - } - - ImageIcon ii = new ImageIcon(image); - if (ii.getIconWidth() <= 0 || ii.getIconHeight() <= 0) { - log.warning("could not find image '" + image + '\''); - return false; - } - mapImage = ii; - mapName = image; - setPreferredSize(new Dimension(ii.getIconWidth(), ii.getIconHeight())); - showBackground = true; - backgroundItem.setEnabled(true); - backgroundItem.setSelected(true); - repaint(); - return true; - } - - private JCheckBoxMenuItem createCheckBoxMenuItem(JPopupMenu menu, String title, boolean isSelected) { - JCheckBoxMenuItem item = new JCheckBoxMenuItem(title, isSelected); - item.addActionListener(this); - menu.add(item); - return item; - } - - private JMenuItem createMenuItem(JPopupMenu menu, String title) { - JMenuItem item = new JMenuItem(title); - item.addActionListener(this); - menu.add(item); - return item; - } - - public void setVisible(boolean visible) { - if (visible) { - clear(); - if (timer != null) { - timer.start(); - } - } else { - if (timer != null) { - timer.stop(); - } - } - super.setVisible(visible); - } - - public void clear() { - setCursor(Cursor.getDefaultCursor()); - draggedNode = null; - updateSelected(); - } - - - // ------------------------------------------------------------------- - // Node handling - // ------------------------------------------------------------------- - - public Node getNode(String id) { - MapNode node = nodeTable.get(id); - return node != null ? node.node : null; - } - - public MapNode getMapNode(String id) { - return nodeTable.get(id); - } - - private MapNode addMapNode(Node nd) { - String id = nd.getID(); - MapNode node = nodeTable.get(id); - if (node == null) { - node = new MapNode(this, nd); - node.y = 10 + (int) (Math.random() * (Math.max(100, getHeight()) - 20)); - node.x = 10 + (int) (Math.random() * (Math.max(100, getWidth()) - 30)); - - String location = server.getConfig(isMap ? id : ("collect.map." + id)); - if (location != null) { - try { - String[] pos = location.split(","); - node.x = Integer.parseInt(pos[0].trim()); - node.y = Integer.parseInt(pos[1].trim()); - node.hasFixedLocation = !isMap; - } catch (Exception e) { - System.err.println("could not parse node location: " + location); - e.printStackTrace(); - } - } - - nodeTable.put(id, node); - updateNodeList = true; - } - return node; - } - - private MapNode[] getNodeList() { - if (updateNodeList) { - synchronized (nodeTable) { - updateNodeList = false; - nodeList = nodeTable.values().toArray(new MapNode[nodeTable.size()]); - } - } - return nodeList; - } - - - // ------------------------------------------------------------------- - // Visualizer - // ------------------------------------------------------------------- - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodesSelected(Node[] nodes) { - if (selectedNodes != nodes) { - selectedNodes = nodes; - if (isVisible()) { - updateSelected(); - } - } - } - - private void updateSelected() { - if (selectedMapNodes.size() > 0) { - for(MapNode node : selectedMapNodes) { - node.isSelected = false; - } - selectedMapNodes.clear(); - } - - if (selectedNodes == null || selectedNodes.length == 0) { - selectedNode = null; - } else { - for (Node node : selectedNodes) { - MapNode mapNode = addMapNode(node); - selectedMapNodes.add(mapNode); - mapNode.isSelected = true; - } - selectedNode = selectedMapNodes.get(0); - } - - repaint(); - } - - @Override - public void nodeAdded(Node nd) { - addMapNode(nd); - if (isVisible()) { - repaint(); - } - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - if (isVisible()) { - repaint(); - } - } - - @Override - public void clearNodeData() { - nodeTable.clear(); - updateNodeList = true; - nodesSelected(null); - if (isVisible()) { - repaint(); - } - } - - - // ------------------------------------------------------------------- - // Graphics - // ------------------------------------------------------------------- - - @Override - protected void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - FontMetrics fm = g.getFontMetrics(); - int fnHeight = fm.getHeight(); - int fnDescent = fm.getDescent(); - int width = getWidth(); - int height = getHeight(); - - g.setColor(getBackground()); - g.fillRect(0, 0, width, height); - if (showBackground && isMap) { - mapImage.paintIcon(this, g, 0, 0); - } - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - - // Display legend - if (!hideNetwork) { - int legendWidth = fm.stringWidth("ETX"); - g.setColor(Color.black); - g.drawString("ETX", width - legendWidth - 10, 10 + fnHeight - fnDescent); - g.drawRect(width - legendWidth - 30, 8, legendWidth + 24, fnHeight + 4); - g.setColor(LINK_COLOR); - g2d.drawLine(width - legendWidth - 25, 10 + fnHeight / 2, - width - legendWidth - 15, 10 + fnHeight / 2); - } - - MapNode[] nodes = getNodeList(); - if (!isMap || !hideNetwork) { - g.setColor(LINK_COLOR); - for (MapNode n : nodes) { - for (int j = 0, mu = n.node.getLinkCount(); j < mu; j++) { - Link link = n.node.getLink(j); - MapNode linkNode = addMapNode(link.node); - int x2 = linkNode.x; - int y2 = linkNode.y; - g2d.drawLine(n.x, n.y, x2, y2); - drawArrow(g, n.x, n.y, x2, y2, 3); - if (!hideNetwork) { - int xn1, xn2, yn1, yn2; - if (n.x <= x2) { - xn1 = n.x; xn2 = x2; - yn1 = n.y; yn2 = y2; - } else { - xn1 = x2; xn2 = n.x; - yn1 = y2; yn2 = n.y; - } - int dx = xn1 + (xn2 - xn1) / 2 + 4; - int dy = yn1 + (yn2 - yn1) / 2 - fnDescent; - if (yn2 < yn1) { - dy += fnHeight - fnDescent; - } - g.drawString( - Double.toString(((int) (link.getETX() * etxFactor * 100 + 0.5)) / 100.0), - dx, dy); - } - } - } - } - - for (MapNode n : nodes) { - n.paint(g, n.x, n.y); - - g.setColor(Color.black); - if (n.isSelected) { - BasicGraphicsUtils.drawDashedRect(g, n.x - delta, n.y - delta, - 2 * delta, 2 * delta); - } - if (selectedNode != null && selectedNode.message != null) { - g.drawString(selectedNode.message, 10, 10); - } - } - } - - private Polygon arrowPoly = new Polygon(); - private void drawArrow(Graphics g, int xSource, int ySource, int xDest, int yDest, int delta) { - double dx = xSource - xDest; - double dy = ySource - yDest; - double dir = Math.atan2(dx, dy); - double len = Math.sqrt(dx * dx + dy * dy); - dx /= len; - dy /= len; - len -= delta; - xDest = xSource - (int) (dx * len); - yDest = ySource - (int) (dy * len); - g.drawLine(xDest, yDest, xSource, ySource); - - final int size = 8; - arrowPoly.reset(); - arrowPoly.addPoint(xDest, yDest); - arrowPoly.addPoint(xDest + xCor(size, dir + 0.5), yDest + yCor(size, dir + 0.5)); - arrowPoly.addPoint(xDest + xCor(size, dir - 0.5), yDest + yCor(size, dir - 0.5)); - arrowPoly.addPoint(xDest, yDest); - g.fillPolygon(arrowPoly); - } - - private int yCor(int len, double dir) { - return (int)(0.5 + len * Math.cos(dir)); - } - - private int xCor(int len, double dir) { - return (int)(0.5 + len * Math.sin(dir)); - } - - - // ------------------------------------------------------------------- - // ActionListener - // ------------------------------------------------------------------- - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (!isMap && source == timer) { - if (isLayoutActive) { - updateNodeLayout(); - repaint(); - } - - } else if (!isMap && source == lockedItem) { - if (popupNode != null) { - boolean wasFixed = popupNode.hasFixedLocation; - popupNode.hasFixedLocation = lockedItem.isSelected(); - if (wasFixed && !popupNode.hasFixedLocation) { - server.removeConfig("collect.map." + popupNode.node.getID()); - } else if (!wasFixed && popupNode.hasFixedLocation) { - server.setConfig("collect.map." + popupNode.node.getID(), - "" + popupNode.x + ',' + popupNode.y); - } - repaint(); - } - - } else if (!isMap && source == layoutItem) { - isLayoutActive = layoutItem.isSelected(); - - } else if (!isMap && source == shakeItem) { - for(MapNode n : getNodeList()) { - if (!n.hasFixedLocation) { - n.x += Math.random() * 100 - 50; - n.y += Math.random() * 100 - 50; - } - } - - } else if (!isMap && source == configItem) { - if (configItem.isSelected()) { - configPanel.setSize(getPreferredSize()); - configPanel.validate(); - updateConfigLayout(); - configPanel.setVisible(true); - } else { - configPanel.setVisible(false); - } - repaint(); - - } else if (source == showNetworkItem) { - hideNetwork = !showNetworkItem.isSelected(); - repaint(); - - } else if (source == resetNetworkItem) { - for(MapNode n : getNodeList()) { - n.node.clearLinks(); - } - repaint(); - } else if (isMap && source == backgroundItem) { - showBackground = mapImage != null && backgroundItem.isSelected(); - repaint(); - } - } - - private void updateNodeLayout() { - MapNode[] nodes = getNodeList(); - for (MapNode n : nodes) { - - // Attract connected nodes - for(int i = 0, jn = n.node.getLinkCount(); i < jn; i++) { - Link link = n.node.getLink(i); - MapNode n2 = addMapNode(link.node); - double vx = n2.x - n.x; - double vy = n2.y - n.y; - double dist = Math.sqrt(vx * vx + vy * vy); - dist = dist == 0 ? 0.00001 : dist; - double etx = link.getETX() * etxFactor; - if (etx > 5) etx = 5; - double factor = (etx * layoutAttract - dist) / (dist * 3); - double dx = factor * vx; - double dy = factor * vy; - - n2.dx += dx; - n2.dy += dy; - n.dx -= dx; - n.dy -= dy; - } - - // Repel nodes that are too close - double dx = 0, dy = 0; - for (MapNode n2 : nodes) { - if (n == n2) { - continue; - } - double vx = n.x - n2.x; - double vy = n.y - n2.y; - double dist = vx * vx + vy * vy; - if (dist == 0) { - dx += Math.random() * 5; - dy += Math.random() * 5; - } else if (dist < layoutRepel * layoutRepel) { - dx += vx / dist; - dy += vy / dist; - } - } - double dist = dx * dx + dy * dy; - if (dist > 0) { - dist = Math.sqrt(dist) / 2; - n.dx += dx / dist; - n.dy += dy / dist; - } - - n.dy += layoutGravity; - } - - // Update the node positions - int width = getWidth(); - int height = getHeight(); - for(MapNode n : nodes) { - if (!n.hasFixedLocation && n != draggedNode) { - n.x += Math.max(-5, Math.min(5, n.dx)); - n.y += Math.max(-5, Math.min(5, n.dy)); - if (n.x < 0) { - n.x = 0; - } else if (n.x > width) { - n.x = width; - } - if (n.y < 0) { - n.y = 0; - } else if (n.y > height) { - n.y = height; - } - } - n.dx /= 2; - n.dy /= 2; - } - } - - private void updateConfigLayout() { - configPanel.setLocation(getWidth() - configPanel.getWidth() - 10, - getHeight() - configPanel.getHeight() - 10); - } - - - // ------------------------------------------------------------------- - // Mouselistener - // ------------------------------------------------------------------- - - private MapNode getNodeAt(int mx, int my) { - for(MapNode n : getNodeList()) { - if (mx >= (n.x - delta) - && mx <= (n.x + delta) - && my >= (n.y - delta) - && my <= (n.y + delta)) { - return n; - } - } - return null; - } - - public void mouseClicked(MouseEvent e) { - int mx = e.getX(); - int my = e.getY(); - if (e.getButton() == MouseEvent.BUTTON1) { - MapNode node = getNodeAt(mx, my); - if (node != selectedNode) { - server.selectNodes(node == null ? null : new Node[] { node.node }); - } - } - showPopup(e); - } - - public void mousePressed(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON1) { - MapNode aNode = getNodeAt(e.getX(), e.getY()); - if (aNode != selectedNode) { - server.selectNodes(aNode != null ? new Node[] { aNode.node } : null); - } - draggedNode = aNode; - draggedTime = System.currentTimeMillis(); - - } else if (selectedNode != null) { - if (draggedTime < 0) { - setCursor(Cursor.getDefaultCursor()); - draggedTime = 0; - } - selectedNode = draggedNode = null; - server.selectNodes(null); - } - showPopup(e); - } - - public void mouseReleased(MouseEvent e) { - if (draggedNode != null && e.getButton() == MouseEvent.BUTTON1) { - if ((draggedTime > 0) && - (System.currentTimeMillis() - draggedTime) < 300) { - // Do not drag if mouse is only moved during click - - } else { - draggedNode.x = e.getX(); - draggedNode.y = e.getY(); - setCursor(Cursor.getDefaultCursor()); - if (!isMap && draggedNode.hasFixedLocation) { - /* Update fixed location */ - server.setConfig("collect.map." + draggedNode.node.getID(), - "" + draggedNode.x + ',' + draggedNode.y); - } - draggedTime = 0; - draggedNode = null; - repaint(); - } - } - - showPopup(e); - } - - private void showPopup(MouseEvent e) { - if (e.isPopupTrigger() - && (e.getModifiers() & (MouseEvent.SHIFT_MASK|MouseEvent.CTRL_MASK)) == 0) { - popupNode = getNodeAt(e.getX(), e.getY()); - if (!isMap) { - lockedItem.setEnabled(popupNode != null); - lockedItem.setSelected(popupNode != null ? popupNode.hasFixedLocation : false); - } - popupMenu.show(this, e.getX(), e.getY()); - } - } - - public void mouseEntered(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - - // ------------------------------------------------------------------- - // MouseMotion - // ------------------------------------------------------------------- - - public void mouseDragged(MouseEvent e) { - if (draggedNode == null) { - // Do nothing - - } else if (draggedTime > 0) { - if ((System.currentTimeMillis() - draggedTime) > 300) { - // No mouse click, time to drag the node - draggedTime = -1; - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - } - - } else if (VISUAL_DRAG /* && dragItem.isSelected() */) { - draggedNode.x = e.getX(); - draggedNode.y = e.getY(); - repaint(); - } - } - - public void mouseMoved(MouseEvent e) { - } - - - // ------------------------------------------------------------------- - // MapNode - // ------------------------------------------------------------------- - - private static class MapNode { - - public final Node node; - public int x; - public int y; - public double dx; - public double dy; - public boolean hasFixedLocation; - public boolean isSelected; - public String message; - - MapNode(MapPanel panel, Node node) { - this.node = node; - } - - public void paint(Graphics g, int x, int y) { - final int od = 3; - g.setColor(Color.black); - g.drawString(node.getID(), x + od * 2 + 3, y + 4); - if (hasFixedLocation) { - g.setColor(Color.red); - } - g.fillOval(x - od, y - od, od * 2 + 1, od * 2 + 1); - } - - } // end of inner class MapNode - - - @Override - public void updateConfig(Properties config) { - if (isMap) { - for (MapNode n : getNodeList()) { - config.put(n.node.getID(), "" + n.x + ',' + n.y); - } - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java deleted file mode 100644 index 6b0cffbc8..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * NodeControl - * - * Authors : Niclas Finne - * Created : 27 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JFormattedTextField; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JTextPane; -import javax.swing.border.LineBorder; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class NodeControl implements Visualizer { - - private final static String SET_TIME_COMMAND = "time %TIME% | null"; - - private final CollectServer server; - private final String category; - private final JPanel panel; - private final JLabel statusLabel; - private final JSeparator statusSeparator; - - public NodeControl(CollectServer server, String category) { - this.server = server; - this.category = category; - this.panel = new JPanel(new BorderLayout()); - - final JFormattedTextField intervalField = new JFormattedTextField(new Integer(60)); - final JFormattedTextField randomField = new JFormattedTextField(new Integer(60)); - final JFormattedTextField reportsField = new JFormattedTextField(new Integer(0)); - final JFormattedTextField rexmitsField = new JFormattedTextField(new Integer(31)); - statusLabel = new JLabel("", JLabel.CENTER); - statusLabel.setOpaque(true); - statusLabel.setBackground(Color.white); - statusLabel.setBorder(LineBorder.createBlackLineBorder()); - statusLabel.setVisible(false); - statusSeparator = new JSeparator(); - statusSeparator.setVisible(false); - - JButton stopButton = createCommandButton("Send stop to nodes", "netcmd killall"); - - JButton sendButton = new JButton("Send command to nodes"); - sendButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int interval = (Integer)intervalField.getValue(); - int random = (Integer)randomField.getValue(); - int reports = (Integer)reportsField.getValue(); - int rexmits = (Integer)rexmitsField.getValue(); - - sendCommand("netcmd { repeat " + reports + " " + interval - + " { randwait " + random + " collect-view-data | send " + rexmits + " } }"); - } - - }); - - JButton collectButton = createCommandButton("Start Collect", - "~K", "killall", - "mac 0", SET_TIME_COMMAND, - "collect | timestamp | binprint &"); - JButton stopCollectButton = createCommandButton("Stop Collect", "~K", "killall"); - - JPanel controlPanel = new JPanel(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 0.5; - c.insets.left = c.insets.right = c.insets.bottom = 3; - c.anchor = GridBagConstraints.WEST; - c.gridy = 0; - - c.gridwidth = 3; - controlPanel.add(statusLabel, c); - c.gridy++; - controlPanel.add(statusSeparator, c); - c.insets.top = 10; - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Program Connected Nodes", JLabel.RIGHT), c); - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - controlPanel.add(new JButton(server.getMoteProgramAction()), c); - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Serial Connection", JLabel.RIGHT), c); - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - controlPanel.add(new JButton(server.getConnectSerialAction()), c); - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridy++; - controlPanel.add(new JSeparator(), c); - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Base Station Control", JLabel.RIGHT), c); - c.gridwidth = 2; - JPanel basePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5)); - basePanel.add(collectButton); - basePanel.add(stopCollectButton); - c.insets.left -= 5; - controlPanel.add(basePanel, c); - c.insets.left += 5; - - c.gridy++; - c.gridwidth = 3; - controlPanel.add(new JSeparator(), c); - - c.gridy++; - JLabel label = new JLabel("Collect Settings", JLabel.CENTER); - controlPanel.add(label, c); - c.gridwidth = 1; - - c.gridy++; - controlPanel.add(label = new JLabel("Report interval", JLabel.RIGHT), c); - label.setLabelFor(intervalField); - controlPanel.add(intervalField, c); - controlPanel.add(new JLabel("seconds"), c); - - c.insets.top = 3; - c.gridy++; - controlPanel.add(label = new JLabel("Report randomness", JLabel.RIGHT), c); - label.setLabelFor(randomField); - controlPanel.add(randomField, c); - controlPanel.add(new JLabel("seconds"), c); - - c.gridy++; - controlPanel.add(label = new JLabel("Hop-by-hop retransmissions", JLabel.RIGHT), c); - label.setLabelFor(rexmitsField); - controlPanel.add(rexmitsField, c); - controlPanel.add(new JLabel("retransmissions (0 - 31)"), c); - - c.gridy++; - controlPanel.add(new JLabel("Number of reports", JLabel.RIGHT), c); - label.setLabelFor(reportsField); - controlPanel.add(reportsField, c); - controlPanel.add(new JLabel("(0 = report forever)"), c); - - c.gridy++; - c.gridwidth = 3; - c.insets.bottom = 10; - JPanel nodePanel = new JPanel(); - nodePanel.add(sendButton); - nodePanel.add(stopButton); - controlPanel.add(nodePanel, c); - - c.gridy++; - controlPanel.add(new JSeparator(), c); - panel.add(controlPanel, BorderLayout.NORTH); - - JTextPane helpPane = new JTextPane(); - helpPane.setContentType("text/html"); - helpPane.setEditable(false); - helpPane.setText("" + - "

Quick Startup Instructions

" + - "" + - "
  • Connect nodes to USB. Press the Program Nodes... button." + - "
  • Disconnect all except one node. " + - "Press the Connect to Serial button." + - "
  • Press the Start Collect button." + - "
  • Press the Send command to nodes button." + - "" + - ""); - helpPane.setBackground(panel.getBackground()); - JScrollPane helpScroll = new JScrollPane(helpPane, - JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - helpScroll.setBorder(BorderFactory.createEmptyBorder(3, 10, 10, 10)); - panel.add(helpScroll, BorderLayout.CENTER); - } - - private JButton createCommandButton(String name, final String... command) { - JButton button = new JButton(name); - button.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - try { - // TODO Should use separate thread to send commands - panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - for(int i = 0, n = command.length; i < n; i++) { - if (i > 0) { - try { - // Do not send multiple commands too fast - Thread.sleep(1000); - } catch (InterruptedException e1) { - } - } - String cmd = command[i]; - if (cmd == SET_TIME_COMMAND) { - cmd = "time " + (System.currentTimeMillis() / 1000) + " | null"; - } - if (!sendCommand(cmd)) { - break; - } - } - } finally { - panel.setCursor(Cursor.getDefaultCursor()); - } - } - - }); - return button; - } - - protected boolean sendCommand(String command) { - if (server.sendToNode(command)) { - setStatus("Sent command '" + command + "'", false); - return true; - } - setStatus("Failed to send command. No serial connection.", true); - return false; - } - - private void setStatus(String text, boolean isWarning) { - statusLabel.setForeground(isWarning ? Color.red : Color.black); - statusLabel.setText(text); - statusLabel.setVisible(true); - statusSeparator.setVisible(true); - } - - public String getCategory() { - return category; - } - - public String getTitle() { - return "Node Control"; - } - - public Component getPanel() { - return panel; - } - - public void nodesSelected(Node[] node) { - } - - public void nodeAdded(Node node) { - } - - public void nodeDataReceived(SensorData sensorData) { - } - - public void clearNodeData() { - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java deleted file mode 100644 index dfda52993..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * NodeInfoPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 6 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Comparator; -import java.util.Properties; - -import javax.swing.AbstractAction; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableRowSorter; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Configurable; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.SensorInfo; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class NodeInfoPanel extends JPanel implements Visualizer, Configurable { - - private static final long serialVersionUID = -1060893468047793431L; - - private static Comparator NUMBER_COMPARATOR = new Comparator() { - - public int compare(Number o1, Number o2) { - double v1 = o1.doubleValue(); - double v2 = o2.doubleValue(); - return (v1 < v2 ? -1 : (v1 == v2 ? 0 : 1)); - } - - }; - - private final CollectServer server; - private final String category; - private final JTable table; - private final NodeModel nodeModel; - - @SuppressWarnings("serial") - public NodeInfoPanel(CollectServer server, String category) { - super(new BorderLayout()); - this.server = server; - this.category = category; - - TableData[] columns = new TableData[] { - new TableData("Node", Node.class) { - public Object getValue(Node node) { - return node; - } - }, - new TableData("Received", "Packets Received", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getPacketCount(); - } - }, - new TableData("Dups", "Duplicate Packets Received", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getDuplicateCount(); - } - }, - new TableData("Lost", "Estimated Lost Packets", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getEstimatedLostCount(); - } - }, - new TableData("Hops", "Average Hops to Sink", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageValue(SensorData.HOPS); - } - }, - new TableData("Rtmetric", "Average Routing Metric", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageRtmetric(); - } - }, - new TableData("ETX", "Average ETX to Next Hop", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageBestNeighborETX(); - } - }, - new TableData("Churn", "Next Hop Change Count", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getNextHopChangeCount(); - } - }, - new TableData("Beacon Interval", "Average Beacon Interval", Long.class) { - public Object getValue(Node node) { - return (long)(node.getSensorDataAggregator().getAverageValue(SensorData.BEACON_INTERVAL) * 1000); - } - }, - - new TableData("Reboots", "Estimated Node Restart Count", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getEstimatedRestarts(); - } - }, - - // Power - new TableData("CPU Power", "Average CPU Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getCPUPower(); - } - }, - new TableData("LPM Power", "Average LPM Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getLPMPower(); - } - }, - new TableData("Listen Power", "Average Radio Listen Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getListenPower(); - } - }, - new TableData("Transmit Power", "Average Radio Transmit Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getTransmitPower(); - } - }, - new TableData("Power", "Average Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAveragePower(); - } - }, - new TableData("On-time", "Power Measure Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getPowerMeasureTime(); - } - }, - - new TableData("Listen Duty Cycle", "Average Radio Listen Duty Cycle (%)", Double.class) { - public Object getValue(Node node) { - return 100 * node.getSensorDataAggregator().getAverageDutyCycle(SensorInfo.TIME_LISTEN); - } - }, - new TableData("Transmit Duty Cycle", "Average Radio Transmit Duty Cycle (%)", Double.class) { - public Object getValue(Node node) { - return 100 * node.getSensorDataAggregator().getAverageDutyCycle(SensorInfo.TIME_TRANSMIT); - } - }, - - // Inter-packet times - new TableData("Avg Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAveragePeriod(); - } - }, - new TableData("Min Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getShortestPeriod(); - } - }, - new TableData("Max Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getLongestPeriod(); - } - } - }; - nodeModel = new NodeModel(columns); - table = new JTable(nodeModel) { - private static final long serialVersionUID = 1L; - private Font fontForAverage; - - protected JTableHeader createDefaultTableHeader() { - return new JTableHeader(columnModel) { - private static final long serialVersionUID = 1L; - - public String getToolTipText(MouseEvent e) { - int index = columnModel.getColumnIndexAtX(e.getX()); - int modelIndex = index < 0 ? index : columnModel.getColumn(index).getModelIndex(); - return modelIndex < 0 ? null : nodeModel.getColumnToolTip(modelIndex); - } - }; - } - - public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) { - Component c = super.prepareRenderer(renderer, rowIndex, vColIndex); - int row = convertRowIndexToModel(rowIndex); - if (row == nodeModel.getRowCount() - 1) { - if (fontForAverage == null) { - fontForAverage = c.getFont().deriveFont(Font.BOLD); - } - // Last line is average - c.setFont(fontForAverage); - } - return c; - } - - }; - - // Do not sort column when clicking between the columns (resizing) - TableRowSorter sorter = new TableRowSorter(nodeModel) { - public void toggleSortOrder(int column) { - if(table.getTableHeader().getCursor().getType() != Cursor.E_RESIZE_CURSOR) { - super.toggleSortOrder(column); - } - } - }; - for(int c = 0; c < columns.length; c++) { - if (columns[c].dataClass == Number.class) { - sorter.setComparator(c, NUMBER_COMPARATOR); - } - } - table.setRowSorter(sorter); - // Pack the column when double clicking between columns (resizing) - table.getTableHeader().addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if(e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e) && - table.getTableHeader().getCursor().getType() == Cursor.E_RESIZE_CURSOR) { - int index = table.getColumnModel().getColumnIndexAtX(e.getX() - 3); - if (index >= 0) { - packColumn(table, index); - } - } - } - }); - - // Add right aligned renderer for node name - DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Node.class, renderer); - - // Add renderer for time - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - long time = (Long) value; - setText(time > 0 ? getTimeAsString(time) : null); - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Long.class, renderer); - - // Add renderer for double - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - if (value == null) { - setText(null); - } else { - double v = ((Number) value).doubleValue() + 0.0005; - int dec = ((int)(v * 1000)) % 1000; - setText((long)v + "." + (dec > 99 ? "" : "0") + (dec > 9 ? "" : "0") + dec); - } - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Double.class, renderer); - - // Add renderer for mixed integers and doubles - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - if (value == null) { - setText(null); - } else if (value instanceof Integer) { - setText(value.toString()); - } else { - double v = ((Number) value).doubleValue() + 0.0005; - int dec = ((int)(v * 1000)) % 1000; - setText((long)v + "." + (dec > 99 ? "" : "0") + (dec > 9 ? "" : "0") + dec); - } - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Number.class, renderer); - - table.setFillsViewportHeight(true); - table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - for (int i = 0, n = table.getColumnCount(); i < n; i++) { - packColumn(table, i); - } - - String savedColumnData = server.getConfig("collect.nodeinfo.table"); - if (savedColumnData != null) { - String[] columnList = savedColumnData.split("[ ,]"); - for(int i = 1; i < columns.length; i++) { - columns[i].setVisible(false); - } - for(int i = 0; i < columnList.length; i++) { - int c = Integer.parseInt(columnList[i]); - int index = table.convertColumnIndexToView(c); - if (index >= 0) { - table.getColumnModel().moveColumn(index, i); - } - columns[c].setVisible(true); - } - } - JPopupMenu popupMenu = new JPopupMenu(); - // The first column (the node name) should always be visible. - for(int i = 1; i < columns.length; i++) { - popupMenu.add(new JCheckBoxMenuItem(columns[i].init(table, i))); - } - table.setComponentPopupMenu(popupMenu); - add(new JScrollPane(table), BorderLayout.CENTER); - } - - public void updateConfig(Properties config) { - StringBuilder sb = new StringBuilder(); - for(int i = 0, n = table.getColumnCount(); i < n; i++) { - int index = table.convertColumnIndexToModel(i); - if (index >= 0) { - if (sb.length() > 0) { - sb.append(','); - } - sb.append(index); - } - } - config.setProperty("collect.nodeinfo.table", sb.toString()); - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return "Node Info"; - } - - @Override - public void nodeAdded(Node node) { - nodeModel.setNodes(server.getNodes()); - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - nodeModel.updateNode(sensorData.getNode()); - } - - @Override - public void clearNodeData() { - nodeModel.setNodes(null); - } - - @Override - public void nodesSelected(Node[] nodes) { - // Ignore - } - - @Override - public void setVisible(boolean visible) { - nodeModel.setNodes(visible ? server.getNodes() : null); - super.setVisible(visible); - } - - private String getTimeAsString(long time) { - StringBuilder sb = new StringBuilder(); - time /= 1000; - if (time > 24 * 60 * 60) { - long days = time / (24 * 60 * 60); - sb.append(days).append(days > 1 ? " days, " : " day, "); - time -= days * 24 * 60 * 60; - } - if (time > 60 * 60) { - long hours = time / (60 * 60); - sb.append(hours).append(hours > 1 ? " hours, " : " hour, "); - time -= hours * 60 * 60; - } - long sec = time % 60; - sb.append(time / 60).append(" min, "); - if (sec < 10) { - sb.append('0'); - } - sb.append(sec).append(" sec"); - return sb.toString(); - } - - private static void packColumn(JTable table, int columnIndex) { - TableColumn tableColumn = table.getColumnModel().getColumn(columnIndex); - Object value = tableColumn.getHeaderValue(); - TableCellRenderer columnRenderer = tableColumn.getHeaderRenderer(); - if (columnRenderer == null) { - columnRenderer = table.getTableHeader().getDefaultRenderer(); - } - Component c = columnRenderer.getTableCellRendererComponent(table, value, false, false, -1, columnIndex); - int width = c.getPreferredSize().width + 6; - int intercellSpacing = table.getIntercellSpacing().width; - for(int i = 0, n = table.getRowCount(); i < n; i++) { - TableCellRenderer cellRenderer = table.getCellRenderer(i, columnIndex); - value = table.getValueAt(i, columnIndex); - c = cellRenderer.getTableCellRendererComponent(table, value, false, false, i, columnIndex); - int w = c.getPreferredSize().width + intercellSpacing + 2; - if (w > width) { - width = w; - } - } - table.getTableHeader().setResizingColumn(tableColumn); - tableColumn.setWidth(width); - tableColumn.setPreferredWidth(width); - } - - private static class NodeModel extends AbstractTableModel { - - private static final long serialVersionUID = 1692207305977527004L; - - private final TableData[] columns; - private Node[] nodes; - - public NodeModel(TableData[] columns) { - this.columns = columns; - } - - public void recalculateAverage() { - for(TableData td : columns) { - td.clearAverageCache(); - } - int row = getRowCount() - 1; - fireTableRowsUpdated(row, row); - } - - public Object getValueAt(int row, int col) { - int count = nodes == null ? 0 : nodes.length; - if (row == count) { - return columns[col].getAverageValue(nodes); - } - return columns[col].getValue(nodes[row]); - } - - public Class getColumnClass(int col) { - return columns[col].dataClass; - } - - public String getColumnName(int col) { - return columns[col].name; - } - - public String getColumnToolTip(int col) { - Object v = columns[col].getValue(TableData.SHORT_DESCRIPTION); - return v == null ? null : v.toString(); - } - - public int getColumnCount() { - return columns.length; - } - - public int getRowCount() { - return (nodes == null ? 0 : nodes.length) + 1; - } - - public void setNodes(Node[] nodes) { - if (this.nodes != null && this.nodes.length > 0) { - fireTableRowsDeleted(0, this.nodes.length - 1); - } - this.nodes = nodes; - if (this.nodes != null && this.nodes.length > 0) { - fireTableRowsInserted(0, this.nodes.length - 1); - } - recalculateAverage(); - } - - public void updateNode(Node node) { - if (this.nodes != null) { - for(int row = 0; row < this.nodes.length; row++) { - if (this.nodes[row] == node) { - fireTableRowsUpdated(row, row); - recalculateAverage(); - break; - } - } - } - } - - } - - public static abstract class TableData extends AbstractAction { - private static final long serialVersionUID = -3045755073722516926L; - - private final static Node AVERAGE_NODE = new Node("99999999.9", "Avg"); - - public final String name; - public final Class dataClass; - - private JTable table; - private TableColumn tableColumn; - private int modelIndex = -1; - - private Object averageCache; - - protected TableData(String name, Class dataClass) { - this(name, name, dataClass); - } - - protected TableData(String name, String description, Class dataClass) { - super(name); - this.name = name; - this.dataClass = dataClass; - putValue(SHORT_DESCRIPTION, description); - setVisible(true); - } - - TableData init(JTable table, int modelIndex) { - this.table = table; - this.modelIndex = modelIndex; - if (!isVisible()) { - // The column should initially be hidden - setColumnVisible(false); - } - return this; - } - - public boolean isVisible() { - return Boolean.TRUE.equals(getValue(SELECTED_KEY)); - } - - public TableData setVisible(boolean isVisible) { - putValue(SELECTED_KEY, isVisible); - return this; - } - - public void actionPerformed(ActionEvent event) { - if (modelIndex >= 0) { - setColumnVisible(isVisible()); - } - } - - private void setColumnVisible(boolean isVisible) { - if (isVisible) { - if (tableColumn != null) { - int count = table.getColumnCount(); - table.addColumn(tableColumn); - tableColumn = null; - packColumn(table, count); - - int newIndex = 0; - for(int i = 0; i < modelIndex; i++) { - if (table.convertColumnIndexToView(i) >= 0) { - // The new column should be after this visible column - newIndex++; - } - } - if (newIndex < count) { - table.getColumnModel().moveColumn(count, newIndex); - } - } - } else { - int columnIndex = table.convertColumnIndexToView(modelIndex); - if (columnIndex >= 0 ) { - tableColumn = table.getColumnModel().getColumn(columnIndex); - table.removeColumn(tableColumn); - } - } - } - - public final Object getAverageValue(Node[] nodes) { - Object tmp = averageCache; - if (tmp != null) { - return tmp; - } - - if (dataClass == Long.class || dataClass == Double.class - || dataClass == Number.class) { - double average = 0.0; - if (nodes != null && nodes.length > 0) { - int count = 0; - for(Node node : nodes) { - if (node.getSensorDataAggregator().getDataCount() > 0) { - average += ((Number) getValue(node)).doubleValue(); - count++; - } - } - if (count > 0) { - average = average / count; - } - } - if (dataClass == Long.class) { - tmp = (long) (average + 0.5); - } else { - tmp = average; - } - } else if (dataClass == Node.class) { - tmp = AVERAGE_NODE; - } - averageCache = tmp; - return tmp; - } - - public final void clearAverageCache() { - averageCache = null; - } - - public abstract Object getValue(Node node); - - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java deleted file mode 100644 index ef7b0c7e5..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * SerialConsole - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 4 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class SerialConsole implements Visualizer { - - private final CollectServer server; - private final String category; - private JPanel panel; - private JTextArea logArea; - private JTextField commandField; - private String[] history = new String[50]; - private int historyPos = 0; - private int historyCount = 0; - - public SerialConsole(CollectServer server, String category) { - this.server = server; - this.category = category; - panel = new JPanel(new BorderLayout()); - logArea = new JTextArea(4, 30); - logArea.setEditable(false); - panel.add(new JScrollPane(logArea), BorderLayout.CENTER); - - JPopupMenu popupMenu = new JPopupMenu(); - JMenuItem clearItem = new JMenuItem("Clear"); - clearItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - logArea.setText(""); - } - - }); - popupMenu.add(clearItem); - logArea.setComponentPopupMenu(popupMenu); - - commandField = new JTextField(); - commandField.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - String command = trim(commandField.getText()); - if (command != null) { - try { - int previous = historyCount - 1; - if (previous < 0) previous += history.length; - if (!command.equals(history[previous])) { - history[historyCount] = command; - historyCount = (historyCount + 1) % history.length; - } - historyPos = historyCount; - if (SerialConsole.this.server.sendToNode(command)) { - commandField.setText(""); - } else { - addSerialData("*** failed to send command ***"); - } - } catch (Exception ex) { - System.err.println("could not send '" + command + "':"); - ex.printStackTrace(); - JOptionPane.showMessageDialog(panel, - "could not send '" + command + "':\n" - + ex, "ERROR", - JOptionPane.ERROR_MESSAGE); - } - } else { - commandField.getToolkit().beep(); - } - } - - }); - commandField.addKeyListener(new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - switch (e.getKeyCode()) { - case KeyEvent.VK_UP: { - int nextPos = (historyPos + history.length - 1) % history.length; - if (nextPos == historyCount || history[nextPos] == null) { - commandField.getToolkit().beep(); - } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); - } - break; - } - case KeyEvent.VK_DOWN: { - int nextPos = (historyPos + 1) % history.length; - if (nextPos == historyCount) { - historyPos = nextPos; - commandField.setText(""); - } else if (historyPos == historyCount || history[nextPos] == null) { - commandField.getToolkit().beep(); - } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); - } - break; - } - } - } - - }); - panel.add(commandField, BorderLayout.SOUTH); - } - - @Override - public Component getPanel() { - return panel; - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return "Serial Console"; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - // Ignore - } - - @Override - public void clearNodeData() { - // Ignore - } - - @Override - public void nodesSelected(Node[] node) { - // Ignore - } - - public void addSerialData(final String text) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - String current = logArea.getText(); - int len = current.length(); - if (len > 4096) { - current = current.substring(len - 4096); - } - current = len > 0 ? (current + '\n' + text) : text; - logArea.setText(current); - logArea.setCaretPosition(current.length()); - } - }); - } - - private String trim(String text) { - return (text != null) && ((text = text.trim()).length() > 0) ? text : null; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java deleted file mode 100644 index 206e25b5c..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * 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. - * - * - * ----------------------------------------------------------------- - * - * TimeChartPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Date; -import javax.swing.JPanel; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.time.Second; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class TimeChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = -607864439709540641L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final TimeSeriesCollection timeSeries; - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - - private Node[] selectedNodes; - - private double minValue; - private double maxValue; - private int rangeTick = 0; - private boolean hasGlobalRange; - private int maxItemCount; - - public TimeChartPanel(CollectServer server, String category, String title, - String chartTitle, String timeAxisLabel, String valueAxisLabel) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.timeSeries = new TimeSeriesCollection(); - this.chart = ChartFactory.createTimeSeriesChart( - chartTitle, timeAxisLabel, valueAxisLabel, timeSeries, - true, true, false - ); - this.chartPanel = new ChartPanel(chart); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - setBaseShapeVisible(true); - setMaxItemCount(server.getDefaultMaxItemCount()); - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodesSelected(Node[] nodes) { - if (this.selectedNodes != nodes) { - this.selectedNodes = nodes; - if (isVisible()) { - updateCharts(); - } - } - } - - @Override - public void nodeDataReceived(SensorData data) { - if (hasGlobalRange) { - boolean update = false; - if (minValue > maxValue) { - update = true; - } else { - double value = getSensorDataValue(data); - if (value < minValue) { - minValue = value; - update = true; - } - if (value > maxValue) { - maxValue = value; - update = true; - } - } - if (update && isVisible()) { - updateGlobalRange(); - } - } - if (isVisible() && selectedNodes != null && selectedNodes.length == timeSeries.getSeriesCount()) { - Node node = data.getNode(); - for (int i = 0, n = selectedNodes.length; i < n; i++) { - if (node == selectedNodes[i]) { - TimeSeries series = timeSeries.getSeries(i); - int groupSize = getGroupSize(node); - if (groupSize > 1) { - series.clear(); - updateSeries(series, node, groupSize); - } else { - series.addOrUpdate(new Second(new Date(data.getNodeTime())), getSensorDataValue(data)); - } - chartPanel.repaint(); - break; - } - } - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - timeSeries.removeAllSeries(); - if (this.selectedNodes != null) { - for(Node node: this.selectedNodes) { - TimeSeries series = new TimeSeries(node.getName(), Second.class); - // Reduce the number of items by grouping them and use the average for each group - int groupSize = getGroupSize(node); - if (groupSize > 1) { - updateSeries(series, node, groupSize); - } else { - for (int i = 0, n = node.getSensorDataCount(); i < n; i++) { - SensorData data = node.getSensorData(i); - series.addOrUpdate(new Second(new Date(data.getNodeTime())), getSensorDataValue(data)); - } - } - timeSeries.addSeries(series); - } - } - } - - protected int getGroupSize(Node node) { - if (maxItemCount > 0) { - int sensorDataCount = node.getSensorDataCount(); - if (sensorDataCount > maxItemCount) { - int groupSize = sensorDataCount / maxItemCount; - if (sensorDataCount / groupSize >= maxItemCount) { - groupSize++; - } - return groupSize; - } - } - return 1; - } - - protected void updateSeries(TimeSeries series, Node node, int groupSize) { - for (int i = 0, n = node.getSensorDataCount(); i < n; i += groupSize) { - double value = 0.0; - long time = 0L; - for (int j = 0; j < groupSize; j++) { - SensorData data = node.getSensorData(i); - value += getSensorDataValue(data); - time += data.getNodeTime() / 1000L; - } - series.addOrUpdate(new Second(new Date((time / groupSize) * 1000L)), value / groupSize); - } - } - - public boolean getBaseShapeVisible() { - return ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).getBaseShapesVisible(); - } - - public void setBaseShapeVisible(boolean visible) { - ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).setBaseShapesVisible(visible); - } - - public int getRangeTick() { - return rangeTick; - } - - public void setRangeTick(int rangeTick) { - this.rangeTick = rangeTick; - } - - public double getRangeMinimumSize() { - return chart.getXYPlot().getRangeAxis().getAutoRangeMinimumSize(); - } - - public void setRangeMinimumSize(double size) { - chart.getXYPlot().getRangeAxis().setAutoRangeMinimumSize(size); - } - - public boolean hasGlobalRange() { - return hasGlobalRange; - } - - public void setGlobalRange(boolean hasGlobalRange) { - if (this.hasGlobalRange != hasGlobalRange) { - this.hasGlobalRange = hasGlobalRange; - if (hasGlobalRange) { - minValue = Double.MAX_VALUE; - maxValue = Double.MIN_NORMAL; - if (isVisible()) { - updateGlobalRange(); - } - } else { - chart.getXYPlot().getRangeAxis().setAutoRange(true); - } - } - } - - private void updateGlobalRange() { - if (hasGlobalRange) { - if (minValue > maxValue) { - for (int i = 0, n = server.getSensorDataCount(); i < n; i++) { - double value = getSensorDataValue(server.getSensorData(i)); - if (value < minValue) minValue = value; - if (value > maxValue) maxValue = value; - } - } - if (minValue < maxValue) { - double minSize = getRangeMinimumSize(); - double min = minValue; - double max = maxValue; - if (max - min < minSize) { - double d = (minSize - (max - min)) / 2; - min -= d; - max += d; - } - if (rangeTick > 0) { - min = ((int) (min - rangeTick / 2) / rangeTick) * rangeTick; -// max = ((int) (max + rangeTick / 2) / rangeTick) * rangeTick; - } - chart.getXYPlot().getRangeAxis().setRange(min, max); - } - } - } - - /** - * Returns the maximal number of chart items to display for each node. - * - * @return the maximal number of chart items to display for each node or 0 - * for unlimited number of chart items. - */ - public int getMaxItemCount() { - return maxItemCount; - } - - /** - * Sets the maximal number of chart items to display for each node. Items will be - * grouped and replaced by the average value when needed. - * - * @param maxItemCount - the maximal number of chart items to display for each node or - * 0 for unlimited number (default) - */ - public void setMaxItemCount(int maxItemCount) { - this.maxItemCount = maxItemCount; - if (isVisible()) { - updateCharts(); - } - } - - public void setVisible(boolean visible) { - if (visible) { - updateGlobalRange(); - updateCharts(); - } else { - timeSeries.removeAllSeries(); - } - super.setVisible(visible); - } - - protected abstract double getSensorDataValue(SensorData data); - -} diff --git a/tools/cooja b/tools/cooja index c1a1b4fdc..22b1262d9 160000 --- a/tools/cooja +++ b/tools/cooja @@ -1 +1 @@ -Subproject commit c1a1b4fdc9329b6cf22a7740145f448841ac2254 +Subproject commit 22b1262d9e668d9cf6c8eaf70715f1bcd5728642 diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 14c1636ae..d8e9c0a79 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -67,24 +67,24 @@ WORKDIR ${HOME} RUN echo "#!/bin/bash\nant -Dbasedir=${COOJA} -f ${COOJA}/build.xml run" > ${HOME}/cooja && \ chmod +x ${HOME}/cooja -# Optional: download Contiki-NG and pre-compile Cooja. -# Else, use a Docker bind mount to share the repo with the host. -# Docker run option: -# -v :/home/user/contiki-ng -#RUN git clone --recursive https://github.com/contiki-ng/contiki-ng.git ${CONTIKI_NG} -#RUN ant -q -f ${CONTIKI_NG}/tools/cooja/build.xml jar - -# Enable IPv6 -- must be done at runtime, not in Dockerfile -#RUN sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # Install coap-cli RUN sudo apt-get install -y npm \ && sudo apt-get clean \ && sudo npm install coap-cli -g \ && sudo ln -s /usr/bin/nodejs /usr/bin/node +# Optional: download Contiki-NG and pre-compile Cooja. +# Else, use a Docker bind mount to share the repo with the host. +# Docker run option: +# -v :/home/user/contiki-ng +RUN git clone --recursive https://github.com/contiki-ng/contiki-ng.git ${CONTIKI_NG} +RUN ant -q -f ${CONTIKI_NG}/tools/cooja/build.xml jar + # Working directory WORKDIR ${CONTIKI_NG} +# Enable IPv6 -- must be done at runtime, not in Dockerfile +RUN echo "sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 > /dev/null" >> /home/user/.profile + # Start a bash -CMD bash +CMD bash --login diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile index 8073a8239..a7dc79fab 100644 --- a/tools/doxygen/Doxyfile +++ b/tools/doxygen/Doxyfile @@ -809,7 +809,8 @@ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */cpu/cc26xx-cc13xx/lib/* \ */cpu/cc26xx-cc13xx/rf-core/api/* \ - */platform/stm32nucleo-spirit1/stm32cube-lib/* + */platform/stm32nucleo-spirit1/stm32cube-lib/* \ + */os/net/security/tinydtls/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -1952,10 +1953,7 @@ INCLUDE_FILE_PATTERNS = # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = CC_FUNCTION_POINTER_ARGS:=1 \ - NETSTACK_CONF_WITH_RIME:=1 \ - NETSTACK_CONF_WITH_IPV4:=1 \ NETSTACK_CONF_WITH_IPV6:=1 \ - UIP_CONF_IPV6_RPL:=1 \ UIP_TCP:=1 \ UIP_UDP:=1 \ UIP_CONF_ICMP6:=1 \ diff --git a/tools/viewconf.c b/tools/viewconf.c index f742b66a0..8be720d56 100644 --- a/tools/viewconf.c +++ b/tools/viewconf.c @@ -62,10 +62,10 @@ ##### "TSCH_CONF_DEFAULT_TIMESLOT_LENGTH": _____ -> TSCH_DEFAULT_TIMESLOT_LENGTH #endif -#ifdef TSCH_CONF_SCHEDULE_DEFAULT_LENGTH -##### "TSCH_CONF_SCHEDULE_DEFAULT_LENGTH": _____ == TSCH_CONF_SCHEDULE_DEFAULT_LENGTH +#ifdef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH +##### "TSCH_SCHEDULE_CONF_DEFAULT_LENGTH": _____ == TSCH_SCHEDULE_CONF_DEFAULT_LENGTH #else -##### "TSCH_CONF_SCHEDULE_DEFAULT_LENGTH": _____ -> TSCH_CHEDULE_DEFAULT_LENGTH +##### "TSCH_SCHEDULE_CONF_DEFAULT_LENGTH": _____ -> TSCH_SCHEDULE_DEFAULT_LENGTH #endif #else /* MAC_CONF_WITH_TSCH */ @@ -150,4 +150,6 @@ ##### "LOG_CONF_LEVEL_MAC": ____________________ == LOG_CONF_LEVEL_MAC ##### "LOG_CONF_LEVEL_FRAMER": _________________ == LOG_CONF_LEVEL_FRAMER ##### "LOG_CONF_LEVEL_6TOP": ___________________ == LOG_CONF_LEVEL_6TOP +##### "LOG_CONF_LEVEL_COAP": ___________________ == LOG_CONF_LEVEL_COAP +##### "LOG_CONF_LEVEL_LWM2M": __________________ == LOG_CONF_LEVEL_LWM2M ##### "LOG_CONF_LEVEL_MAIN": ___________________ == LOG_CONF_LEVEL_MAIN diff --git a/tools/wpcapslip/contiki-conf.h b/tools/wpcapslip/contiki-conf.h index 020cbdfec..7221f4033 100644 --- a/tools/wpcapslip/contiki-conf.h +++ b/tools/wpcapslip/contiki-conf.h @@ -1,8 +1,6 @@ #ifndef CONTIKI_CONF_H_ #define CONTIKI_CONF_H_ #include -#define CCIF -#define CLIF /* These names are deprecated, use C99 names. */ typedef uint8_t u8_t;