diff --git a/examples/osd/merkurboard/Makefile b/examples/osd/merkurboard/Makefile new file mode 100644 index 000000000..2c12837cc --- /dev/null +++ b/examples/osd/merkurboard/Makefile @@ -0,0 +1,69 @@ +all: er-example-server er-example-client +# use target "er-plugtest-server" explicitly when requried + +CONTIKI=../../.. + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +ifndef TARGET +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c')) +else +ifeq ($(TARGET), native) +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c')) +else +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c' ! -name 'res-plugtest*')) +endif +endif + +PROJECTDIRS += $(REST_RESOURCES_DIR) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +# linker optimizations +SMALL=1 + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine + +# optional rules to get assembly +#CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 +#CUSTOM_RULE_S_TO_OBJECTDIR_O = 1 + +CONTIKI_WITH_IPV6 = 1 +include $(CONTIKI)/Makefile.include + +# minimal-net target is currently broken in Contiki +ifeq ($(TARGET), minimal-net) +CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" +${info INFO: er-example compiling with large buffers} +CFLAGS += -DUIP_CONF_BUFFER_SIZE=1300 +CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 +CFLAGS += -DCOAP_MAX_HEADER_SIZE=176 +CONTIKI_WITH_RPL=0 +endif + +# 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) + +connect-router: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + +connect-router-cooja: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 aaaa::1/64 + +connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-router.native + sudo $(CONTIKI)/exmples/ipv6/native-border-router/border-router.native -a 127.0.0.1 -p 60001 aaaa::1/64 + +connect-minimal: + sudo ip address add fdfd::1/64 dev tap0 diff --git a/examples/osd/merkurboard/er-example-client.c b/examples/osd/merkurboard/er-example-client.c new file mode 100644 index 000000000..40c6f353b --- /dev/null +++ b/examples/osd/merkurboard/er-example-client.c @@ -0,0 +1,135 @@ +/* + * 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 + * Erbium (Er) CoAP client example. + * \author + * Matthias Kovatsch + */ + +#include +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "er-coap-engine.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 + +/* 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, 0x0221, 0x2eff, 0xff00, 0x3305) /* 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 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. */ +#define NUMBER_OF_URLS 4 +/* leading and ending slashes only for demo purposes, get cropped automatically when setting the Uri-Path */ +char *service_urls[NUMBER_OF_URLS] = +{ ".well-known/core", "/a/toggle", "/s/battery/", "error/in//path" }; +#if PLATFORM_HAS_BUTTON +static int uri_switch = 1; +#endif + +/* This function is will be passed to COAP_BLOCKING_REQUEST() to handle responses. */ +void +client_chunk_handler(void *response) +{ + const uint8_t *chunk; + + int len = coap_get_payload(response, &chunk); + + printf("|%.*s", len, (char *)chunk); +} +PROCESS_THREAD(er_example_client, ev, data) +{ + PROCESS_BEGIN(); + + static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ + + SERVER_NODE(&server_ipaddr); + + /* receives all CoAP messages */ + coap_init_engine(); + + etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND); + +#if PLATFORM_HAS_BUTTON + SENSORS_ACTIVATE(button_sensor); + printf("Press a button to request %s\n", service_urls[uri_switch]); +#endif + + while(1) { + PROCESS_YIELD(); + + if(ev == sensors_event && data == &button_sensor) { + + /* send a request to notify the end of the process */ + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, service_urls[uri_switch]); + + printf("--Requesting %s--\n", service_urls[uri_switch]); + + PRINT6ADDR(&server_ipaddr); + PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); + + COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + client_chunk_handler); + + printf("\n--Done--\n"); + + + } + } + + PROCESS_END(); +} diff --git a/examples/osd/merkurboard/er-example-server.c b/examples/osd/merkurboard/er-example-server.c new file mode 100644 index 000000000..01686bcd4 --- /dev/null +++ b/examples/osd/merkurboard/er-example-server.c @@ -0,0 +1,172 @@ +/* + * 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 + * Erbium (Er) REST Engine example. + * \author + * Matthias Kovatsch + */ + +#include +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "rest-engine.h" + +#if PLATFORM_HAS_BUTTON +#include "dev/button-sensor.h" +#endif + +#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 + +/* + * 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_hello, + res_mirror, + res_separate, + res_push, + res_event, + res_sub; +#if PLATFORM_HAS_LEDS +#include "dev/leds.h" +extern resource_t res_leds, res_toggle; +#endif +#if PLATFORM_HAS_LIGHT +#include "dev/light-sensor.h" +extern resource_t res_light; +#endif +#if PLATFORM_HAS_BATTERY +#include "dev/battery-sensor.h" +extern resource_t res_battery; +#endif +/* +#if PLATFORM_HAS_RADIO +#include "dev/radio-sensor.h" +extern resource_t res_radio; +#endif +*/ + +void +hw_init() +{ +#if defined (PLATFORM_HAS_LEDS) + leds_off(LEDS_RED); +#endif +} + +PROCESS(er_example_server, "Erbium Example Server"); +AUTOSTART_PROCESSES(&er_example_server); + +PROCESS_THREAD(er_example_server, ev, data) +{ + PROCESS_BEGIN(); + + PROCESS_PAUSE(); + + PRINTF("Starting Erbium Example Server\n"); + +#ifdef RF_CHANNEL + PRINTF("RF channel: %u\n", RF_CHANNEL); +#endif +#ifdef IEEE802154_PANID + PRINTF("PAN ID: 0x%04X\n", IEEE802154_PANID); +#endif + + 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); + + hw_init(); + /* Initialize the REST engine. */ + rest_init_engine(); + + /* + * 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_push, "test/push"); + rest_activate_resource(&res_event, "s/button"); +#if PLATFORM_HAS_LEDS + rest_activate_resource(&res_leds, "a/leds"); + rest_activate_resource(&res_toggle, "a/toggle"); +#endif +#if PLATFORM_HAS_LIGHT + rest_activate_resource(&res_light, "s/light"); + SENSORS_ACTIVATE(light_sensor); +#endif + +#if PLATFORM_HAS_BATTERY + rest_activate_resource(&res_battery, "s/battery"); + SENSORS_ACTIVATE(battery_sensor); +#endif +/* +#if PLATFORM_HAS_RADIO + rest_activate_resource(&res_radio, "s/radio"); + SENSORS_ACTIVATE(radio_sensor); +#endif +*/ + + /* Define application-specific events here. */ + while(1) { + PROCESS_WAIT_EVENT(); +#if PLATFORM_HAS_BUTTON + if(ev == sensors_event && data == &button_sensor) { + PRINTF("*******BUTTON*******\n"); + + /* Call the event_handler for this application-specific event. */ + res_event.trigger(); + + /* Also call the separate response example handler. */ + res_separate.resume(); + } +#endif /* PLATFORM_HAS_BUTTON */ + } /* while (1) */ + + PROCESS_END(); +} diff --git a/examples/osd/merkurboard/er-plugtest-server.c b/examples/osd/merkurboard/er-plugtest-server.c new file mode 100644 index 000000000..ae637dc4c --- /dev/null +++ b/examples/osd/merkurboard/er-plugtest-server.c @@ -0,0 +1,128 @@ +/* + * 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 + * Server for the ETSI IoT CoAP Plugtests, Las Vegas, NV, USA, Nov 2013. + * \author + * Matthias Kovatsch + */ + +#include +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "er-coap.h" +#include "er-coap-transactions.h" +#include "er-coap-separate.h" +#include "rest-engine.h" +#include "er-plugtest.h" + +/* + * 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_plugtest_test, + res_plugtest_validate, + res_plugtest_create1, + res_plugtest_create2, + res_plugtest_create3, + res_plugtest_longpath, + res_plugtest_query, + res_plugtest_locquery, + res_plugtest_multi, + res_plugtest_link1, + res_plugtest_link2, + res_plugtest_link3, + res_plugtest_path, + res_plugtest_separate, + res_plugtest_large, + res_plugtest_large_update, + res_plugtest_large_create, + res_plugtest_obs, + res_mirror; + +PROCESS(plugtest_server, "PlugtestServer"); +AUTOSTART_PROCESSES(&plugtest_server); + +PROCESS_THREAD(plugtest_server, ev, data) +{ + PROCESS_BEGIN(); + + PRINTF("ETSI IoT CoAP Plugtests Server\n"); + +#ifdef RF_CHANNEL + PRINTF("RF channel: %u\n", RF_CHANNEL); +#endif +#ifdef IEEE802154_PANID + PRINTF("PAN ID: 0x%04X\n", IEEE802154_PANID); +#endif + + 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); + + /* Initialize the REST engine. */ + rest_init_engine(); + + /* 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"); + + rest_activate_resource(&res_mirror, "mirror"); + + /* Define application-specific events here. */ + while(1) { + PROCESS_WAIT_EVENT(); + } /* while (1) */ + + PROCESS_END(); +} diff --git a/examples/osd/merkurboard/er-plugtest.h b/examples/osd/merkurboard/er-plugtest.h new file mode 100644 index 000000000..0b156656a --- /dev/null +++ b/examples/osd/merkurboard/er-plugtest.h @@ -0,0 +1,66 @@ +/* + * 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 + * Erbium (Er) CoAP client example + * \author + * Matthias Kovatsch + */ + +#ifndef __ER_PLUGTEST_H__ +#define __ER_PLUGTEST_H__ + +#if !defined(CONTIKI_TARGET_NATIVE) +#warning "Should only be compiled for native!" +#endif + +#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 + +/* double expansion */ +#define TO_STRING2(x) # x +#define TO_STRING(x) TO_STRING2(x) + +#define MAX_PLUGFEST_PAYLOAD 64 + 1 /* +1 for the terminating zero, which is not transmitted */ +#define MAX_PLUGFEST_BODY 2048 +#define CHUNKS_TOTAL 2012 + +#endif /* __ER_PLUGTEST_H__ */ diff --git a/examples/osd/merkurboard/flash.sh b/examples/osd/merkurboard/flash.sh new file mode 100755 index 000000000..e92d472f6 --- /dev/null +++ b/examples/osd/merkurboard/flash.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a diff --git a/examples/osd/merkurboard/flashclient.sh b/examples/osd/merkurboard/flashclient.sh new file mode 100755 index 000000000..30979eed4 --- /dev/null +++ b/examples/osd/merkurboard/flashclient.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-client.osd-merkur.hex:a -U eeprom:w:er-example-client.osd-merkur.eep:a diff --git a/examples/osd/merkurboard/in6addr.patch b/examples/osd/merkurboard/in6addr.patch new file mode 100644 index 000000000..92ca106cf --- /dev/null +++ b/examples/osd/merkurboard/in6addr.patch @@ -0,0 +1,10 @@ +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/osd/merkurboard/resources/res-battery.c b/examples/osd/merkurboard/resources/res-battery.c new file mode 100644 index 000000000..c7a025d38 --- /dev/null +++ b/examples/osd/merkurboard/resources/res-battery.c @@ -0,0 +1,81 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include "contiki.h" + +#if PLATFORM_HAS_BATTERY + +#include +#include "rest-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); + +/* A simple getter example. Returns the reading from light sensor with a simple etag */ +RESOURCE(res_battery, + "title=\"Battery status\";rt=\"Battery\"", + res_get_handler, + NULL, + NULL, + NULL); + +static void +res_get_handler(void *request, void *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); + + 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.%02d", battery/1000, battery % 1000); + + 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, "{'battery':%d.%02d}", battery/1000, battery % 1000); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} +#endif /* PLATFORM_HAS_BATTERY */ diff --git a/examples/osd/merkurboard/resources/res-event.c b/examples/osd/merkurboard/resources/res-event.c new file mode 100644 index 000000000..d20f0caa9 --- /dev/null +++ b/examples/osd/merkurboard/resources/res-event.c @@ -0,0 +1,101 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include +#include "rest-engine.h" +#include "er-coap.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 + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_event_handler(); + +/* + * Example for an event resource. + * Additionally takes a period parameter that defines the interval to call [name]_periodic_handler(). + * A default post_handler takes care of subscriptions and manages a list of subscribers to notify. + */ +EVENT_RESOURCE(res_event, + "title=\"Event demo\";obs", + res_get_handler, + NULL, + NULL, + NULL, + res_event_handler); + +/* + * Use local resource state that is accessed by res_get_handler() and altered by res_event_handler() or PUT or POST. + */ +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) +{ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", event_counter)); + + /* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */ +} +/* + * Additionally, res_event_handler must be implemented for each EVENT_RESOURCE. + * It is called through .trigger(), usually from the server process. + */ +static void +res_event_handler() +{ + /* Do the update triggered by the event here, e.g., sampling a sensor. */ + ++event_counter; + + /* Usually a condition is defined under with subscribers are notified, e.g., event was above a threshold. */ + if(1) { + 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); + } +} diff --git a/examples/osd/merkurboard/resources/res-hello.c b/examples/osd/merkurboard/resources/res-hello.c new file mode 100644 index 000000000..9208f8b74 --- /dev/null +++ b/examples/osd/merkurboard/resources/res-hello.c @@ -0,0 +1,81 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include +#include +#include "rest-engine.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* + * A handler function named [resource name]_handler must be implemented for each RESOURCE. + * A buffer for the response payload is provided through the buffer pointer. Simple resources can ignore + * preferred_size and offset, but must respect the REST_MAX_CHUNK_SIZE limit for the buffer. + * If a smaller block size is requested for CoAP, the REST framework automatically splits the data. + */ +RESOURCE(res_hello, + "title=\"Hello world: ?len=0..\";rt=\"Text\"", + res_get_handler, + NULL, + NULL, + NULL); + +static void +res_get_handler(void *request, void *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. */ + char const *const message = "Hello World! ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"; + 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)) { + length = atoi(len); + if(length < 0) { + length = 0; + } + if(length > REST_MAX_CHUNK_SIZE) { + length = REST_MAX_CHUNK_SIZE; + } + 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); +} diff --git a/examples/osd/merkurboard/resources/res-leds.c b/examples/osd/merkurboard/resources/res-leds.c new file mode 100644 index 000000000..5fbcf6c77 --- /dev/null +++ b/examples/osd/merkurboard/resources/res-leds.c @@ -0,0 +1,108 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include "contiki.h" + +#if PLATFORM_HAS_LEDS + +#include +#include "rest-engine.h" +#include "dev/leds.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 + +static void res_post_put_handler(void *request, void *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*/ +RESOURCE(res_leds, + "title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\"", + NULL, + res_post_put_handler, + res_post_put_handler, + NULL); + +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + size_t len = 0; + const char *color = NULL; + const char *mode = NULL; + uint8_t led = 0; + int success = 1; + + if((len = REST.get_query_variable(request, "color", &color))) { + PRINTF("color %.*s\n", len, color); + + if(strncmp(color, "r", len) == 0) { + led = LEDS_RED; + } else if(strncmp(color, "g", len) == 0) { + led = LEDS_GREEN; + } else if(strncmp(color, "b", len) == 0) { + led = LEDS_BLUE; + } else { + success = 0; + } + } else { + success = 0; + } if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + PRINTF("mode %s\n", mode); + + if(strncmp(mode, "on", len) == 0) { + leds_on(led); + } else if(strncmp(mode, "off", len) == 0) { + leds_off(led); + } else { + success = 0; + } + } else { + success = 0; + } if(!success) { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} +#endif /* PLATFORM_HAS_LEDS */ diff --git a/examples/osd/merkurboard/resources/res-push.c b/examples/osd/merkurboard/resources/res-push.c new file mode 100644 index 000000000..c169b407c --- /dev/null +++ b/examples/osd/merkurboard/resources/res-push.c @@ -0,0 +1,89 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include +#include "rest-engine.h" +#include "er-coap.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_periodic_handler(void); + +PERIODIC_RESOURCE(res_push, + "title=\"Periodic demo\";obs", + res_get_handler, + NULL, + NULL, + NULL, + 5 * CLOCK_SECOND, + res_periodic_handler); + +/* + * Use local resource state that is accessed by res_get_handler() and altered by res_periodic_handler() or PUT or POST. + */ +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) +{ + /* + * 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(). + * 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", event_counter)); + + /* The REST.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. + * It will be called by the REST manager process with the defined period. + */ +static void +res_periodic_handler() +{ + /* Do a periodic task here, e.g., sampling a sensor. */ + ++event_counter; + + /* 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); + } +} diff --git a/examples/osd/merkurboard/resources/res-radio.c b/examples/osd/merkurboard/resources/res-radio.c new file mode 100644 index 000000000..ac09319a3 --- /dev/null +++ b/examples/osd/merkurboard/resources/res-radio.c @@ -0,0 +1,102 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include "contiki.h" + +#if PLATFORM_HAS_RADIO + +#include +#include "rest-engine.h" +#include "dev/radio-sensor.h" + +static void res_get_handler(void *request, void *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, + "title=\"RADIO: ?p=lqi|rssi\";rt=\"RadioSensor\"", + res_get_handler, + NULL, + NULL, + NULL); + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + size_t len = 0; + const char *p = NULL; + uint8_t param = 0; + int success = 1; + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if((len = REST.get_query_variable(request, "p", &p))) { + if(strncmp(p, "lqi", len) == 0) { + param = RADIO_SENSOR_LAST_VALUE; + } else if(strncmp(p, "rssi", len) == 0) { + param = RADIO_SENSOR_LAST_PACKET; + } else { + success = 0; + } + } else { + success = 0; + } 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", radio_sensor.value(param)); + + 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); + + if(param == RADIO_SENSOR_LAST_VALUE) { + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'lqi':%d}", radio_sensor.value(param)); + } else if(param == RADIO_SENSOR_LAST_PACKET) { + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'rssi':%d}", radio_sensor.value(param)); + } + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } + } else { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} +#endif /* PLATFORM_HAS_RADIO */ diff --git a/examples/osd/merkurboard/resources/res-separate.c b/examples/osd/merkurboard/resources/res-separate.c new file mode 100644 index 000000000..bb2248c92 --- /dev/null +++ b/examples/osd/merkurboard/resources/res-separate.c @@ -0,0 +1,127 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include +#include "rest-engine.h" +#include "er-coap-separate.h" +#include "er-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_resume_handler(void); + +SEPARATE_RESOURCE(res_separate, + "title=\"Separate demo\"", + res_get_handler, + NULL, + NULL, + NULL, + res_resume_handler); + +/* A structure to store the information required for the separate handler */ +typedef struct application_separate_store { + + /* Provided by Erbium to store generic request information such as remote address and token. */ + coap_separate_t request_metadata; + + /* Add fields for addition information to be stored for finalizing, e.g.: */ + char buffer[16]; +} application_separate_store_t; + +#define COAP_MAX_OPEN_SEPARATE 2 + +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) +{ + /* + * Example allows only one open separate response. + * For multiple, the application must manage the list of stores. + */ + if(separate_active >= COAP_MAX_OPEN_SEPARATE) { + coap_separate_reject(); + } else { + ++separate_active; + + /* Take over and skip response by engine. */ + coap_separate_accept(request, &separate_store->request_metadata); + /* Be aware to respect the Block2 option, which is also stored in the coap_separate_t. */ + + /* + * At the moment, only the minimal information is stored in the store (client address, port, token, MID, type, and Block2). + * Extend the store, if the application requires additional information from this handler. + * buffer is an example field for custom information. + */ + snprintf(separate_store->buffer, sizeof(separate_store->buffer), "StoredInfo"); + } +} +static void +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. */ + + /* Restore the request information for the response. */ + coap_separate_resume(response, &separate_store->request_metadata, REST.status.OK); + + coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); + + /* + * Be aware to respect the Block2 option, which is also stored in the coap_separate_t. + * As it is a critical option, this example resource pretends to handle it for compliance. + */ + 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); + coap_send_transaction(transaction); + /* The engine will clear the transaction (right after send for NON, after acked for CON). */ + + /* FIXME there could me more! */ + separate_active = 0; + } else { + /* + * Set timer for retry, send error message, ... + * The example simply waits for another button press. + */ + } + } /* if (separate_active) */ +} diff --git a/examples/osd/merkurboard/resources/res-toggle.c b/examples/osd/merkurboard/resources/res-toggle.c new file mode 100644 index 000000000..d8a773306 --- /dev/null +++ b/examples/osd/merkurboard/resources/res-toggle.c @@ -0,0 +1,63 @@ +/* + * 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 + * Example resource + * \author + * Matthias Kovatsch + */ + +#include "contiki.h" + +#if PLATFORM_HAS_LEDS + +#include +#include "contiki.h" +#include "rest-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); + +/* A simple actuator example. Toggles the red led */ +RESOURCE(res_toggle, + "title=\"Red LED\";rt=\"Control\"", + NULL, + res_post_handler, + NULL, + NULL); + +static void +res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + leds_toggle(LEDS_RED); +} +#endif /* PLATFORM_HAS_LEDS */ diff --git a/examples/osd/merkurboard/run.sh b/examples/osd/merkurboard/run.sh new file mode 100755 index 000000000..2efd2cf48 --- /dev/null +++ b/examples/osd/merkurboard/run.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# For the new bootloader (using a jump-table) you want to use +# BOOTLOADER_GET_MAC=0x0001ff80 (which is the current default) +make clean TARGET=osd-merkur +make TARGET=osd-merkur BOOTLOADER_GET_MAC=0x0001f3a0 +avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur +avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex +avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep diff --git a/examples/osd/merkurboard/runclient.sh b/examples/osd/merkurboard/runclient.sh new file mode 100755 index 000000000..70dcea0e5 --- /dev/null +++ b/examples/osd/merkurboard/runclient.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# For the new bootloader (using a jump-table) you want to use +# BOOTLOADER_GET_MAC=0x0001ff80 (which is the current default) +make clean TARGET=osd-merkur +make TARGET=osd-merkur BOOTLOADER_GET_MAC=0x0001f3a0 +avr-size -C --mcu=MCU=atmega128rfa1 er-example-client.osd-merkur +avr-objcopy -j .text -j .data -O ihex er-example-client.osd-merkur er-example-client.osd-merkur.hex +avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-client.osd-merkur er-example-client.osd-merkur.eep