diff --git a/examples/osd/climate/Makefile b/examples/osd/climate/Makefile index e12d01b5c..61bba988c 100644 --- a/examples/osd/climate/Makefile +++ b/examples/osd/climate/Makefile @@ -1,74 +1,37 @@ all: er-example-server -# use this target explicitly if requried: er-plugtest-server - - -# variable for this Makefile -# configure CoAP implementation (3|7|12|13) (er-coap-07 also supports CoAP draft 08) -WITH_COAP=13 - - -# variable for Makefile.include -WITH_UIP6=1 -# for some platforms -UIP_CONF_IPV6=1 -# IPv6 make config disappeared completely -CFLAGS += -DUIP_CONF_IPV6 -CFLAGS += -DUIP_CONF_IPV6_RPL +# use target "er-plugtest-server" explicitly when requried CONTIKI=../../.. + +# Contiki IPv6 configuration +WITH_UIP6=1 +UIP_CONF_IPV6=1 +CFLAGS += -DUIP_CONF_IPV6=1 +CFLAGS += -DUIP_CONF_IPV6_RPL=1 + CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" -# variable for Makefile.include -ifneq ($(TARGET), minimal-net) -CFLAGS += -DUIP_CONF_IPV6_RPL=1 +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +ifndef TARGET +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c')) else -# minimal-net does not support RPL under Linux and is mostly used to test CoAP only -${info INFO: compiling without RPL} -CFLAGS += -DUIP_CONF_IPV6_RPL=0 -CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" -${info INFO: compiling with large buffers} -CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048 -CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 -CFLAGS += -DCOAP_MAX_HEADER_SIZE=640 +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 framework, requires WITH_COAP -ifeq ($(WITH_COAP), 13) -${info INFO: compiling with CoAP-13} -CFLAGS += -DWITH_COAP=13 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-13 -else ifeq ($(WITH_COAP), 12) -${info INFO: compiling with CoAP-12} -CFLAGS += -DWITH_COAP=12 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-12 -else ifeq ($(WITH_COAP), 7) -${info INFO: compiling with CoAP-08} -CFLAGS += -DWITH_COAP=7 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-07 -else ifeq ($(WITH_COAP), 3) -${info INFO: compiling with CoAP-03} -CFLAGS += -DWITH_COAP=3 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-03 -else -${info INFO: compiling with HTTP} -CFLAGS += -DWITH_HTTP -CFLAGS += -DREST=http_rest_implementation -CFLAGS += -DUIP_CONF_TCP=1 -APPS += er-http-engine -endif - -APPS += erbium +# 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 @@ -76,6 +39,16 @@ APPS += erbium 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 +CFLAGS += -DUIP_CONF_IPV6_RPL=0 +endif + # optional rules to get assembly #$(OBJECTDIR)/%.o: asmdir/%.S # $(CC) $(CFLAGS) -MMD -c $< -o $@ @@ -92,7 +65,10 @@ 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 aaaa::1/64 + 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 + sudo ip address add fdfd::1/64 dev tap0 diff --git a/examples/osd/climate/er-example-server.c b/examples/osd/climate/er-example-server.c index ee744ce68..79088af1f 100644 --- a/examples/osd/climate/er-example-server.c +++ b/examples/osd/climate/er-example-server.c @@ -42,18 +42,16 @@ #include #include "contiki.h" #include "contiki-net.h" - +#include "rest-engine.h" /* Define which resources to include to meet memory constraints. */ #define REST_RES_INFO 1 -#define REST_RES_DS1820 0 +#define REST_RES_DS1820 1 #define REST_RES_DHT11 1 -#define REST_RES_DHT11TEMP 1 +#define REST_RES_DHT11TEMP 0 #define REST_RES_LEDS 1 -#define REST_RES_TOGGLE 0 #define REST_RES_BATTERY 1 -#include "erbium.h" #if REST_RES_DS1820 #include "dev/ds1820.h" @@ -66,9 +64,7 @@ uint16_t dht11_temp=0, dht11_hum=0; #if defined (PLATFORM_HAS_BUTTON) #include "dev/button-sensor.h" #endif -#if defined (PLATFORM_HAS_LEDS) -#include "dev/leds.h" -#endif + #if defined (PLATFORM_HAS_TEMPERATURE) #include "dev/temperature-sensor.h" #endif @@ -80,19 +76,6 @@ uint16_t dht11_temp=0, dht11_hum=0; #endif -/* For CoAP-specific example: not required for normal RESTful Web service. */ -#if WITH_COAP == 3 -#include "er-coap-03.h" -#elif WITH_COAP == 7 -#include "er-coap-07.h" -#elif WITH_COAP == 12 -#include "er-coap-12.h" -#elif WITH_COAP == 13 -#include "er-coap-13.h" -#else -#warning "Erbium example without CoAP-specifc functionality" -#endif /* CoAP-specific example */ - #define DEBUG 0 #if DEBUG #define PRINTF(...) printf(__VA_ARGS__) @@ -104,6 +87,28 @@ uint16_t dht11_temp=0, dht11_hum=0; #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. + */ + + +#if defined (PLATFORM_HAS_LEDS) +#include "dev/leds.h" +extern resource_t res_leds; +#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 + + /******************************************************************************/ @@ -112,16 +117,24 @@ uint16_t dht11_temp=0, dht11_hum=0; * Resources are defined by the RESOURCE macro. * Signature: resource name, the RESTful methods it handles, and its URI path (omitting the leading slash). */ -RESOURCE(info, METHOD_GET, "info", "title=\"Info\";rt=\"text\""); +//RESOURCE(info, METHOD_GET, "info", "title=\"Info\";rt=\"text\""); +static void res_get_info_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_info, + "title=\"Info\";rt=\"text\"", + res_get_info_handler, + NULL, + NULL, + NULL); /* * 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. */ -void -info_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +static void +res_get_info_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { char message[100]; int index = 0; @@ -147,9 +160,20 @@ info_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_ #define DS1820_TEMP_MSB 1 #define DS1820_COUNT_REMAIN 6 #define DS1820_COUNT_PER_C 7 -RESOURCE(ds1820, METHOD_GET, "s/temp", "title=\"Temperatur DS1820\";rt=\"temperature-c\""); -void -ds1820_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) + +//RESOURCE(ds1820, METHOD_GET, "s/temp", "title=\"Temperatur DS1820\";rt=\"temperature-c\""); +static void res_get_ds1820_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_ds1820, + "title=\"Temperature DHTxx\";rt=\"temperature c\"", + res_get_ds1820_handler, + NULL, + NULL, + NULL); + +static void +res_get_ds1820_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { char message[100]; @@ -162,8 +186,8 @@ ds1820_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre int temp_integral; int temp_centi; - const uint16_t *accept = NULL; - int num = REST.get_header_accept(request, &accept); + unsigned int accept = -1; + REST.get_header_accept(request, &accept); // temp = temp_read - 0.25°C + (count_per_c - count_remain) / count_per_c; temp_raw.u_int16 = ds1820_ok[DS1820_TEMP_MSB] << 8 | ds1820_ok[DS1820_TEMP_LSB]; @@ -174,7 +198,7 @@ ds1820_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre temp_integral = (int) temp_c; temp_centi = (int) (fabs (temp_c - (int) temp_c) * 100.0); - if ((num==0) || (num && accept[0]==REST.type.TEXT_PLAIN)) + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { REST.set_header_content_type(response, REST.type.TEXT_PLAIN); snprintf(message, REST_MAX_CHUNK_SIZE, "%d.%02d C", temp_integral, temp_centi); @@ -184,7 +208,7 @@ ds1820_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre REST.set_response_payload(response, buffer, length); } - else if (num && (accept[0]==REST.type.APPLICATION_JSON)) + else if (accept == REST.type.APPLICATION_JSON) { REST.set_header_content_type(response, REST.type.APPLICATION_JSON); snprintf(message, REST_MAX_CHUNK_SIZE, "{\"temp\":\"%d.%02d\"}", temp_integral, temp_centi); @@ -204,9 +228,20 @@ ds1820_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre #if REST_RES_DHT11TEMP /*A simple getter example. Returns the reading from dhtxx sensor*/ -RESOURCE(dht11temp, METHOD_GET, "s/temp", "title=\"Temperatur DHTxx\";rt=\"temperature-c\""); -void -dht11temp_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +//RESOURCE(dht11temp, METHOD_GET, "s/temp", "title=\"Temperatur DHTxx\";rt=\"temperature-c\""); + +static void res_get_dht11temp_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_dht11temp, + "title=\"Temperature DHTxx\";rt=\"temperature c\"", + res_get_dht11temp_handler, + NULL, + NULL, + NULL); + +static void +res_get_dht11temp_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { char message[100]; int length = 0; /* |<-------->| */ @@ -244,17 +279,27 @@ dht11temp_handler(void* request, void* response, uint8_t *buffer, uint16_t prefe #if REST_RES_DHT11 /*A simple getter example. Returns the reading from dhtxx sensor*/ -RESOURCE(dht11, METHOD_GET, "s/hum", "title=\"Humidity DHTxx\";rt=\"humidity-%\""); -void -dht11_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +//RESOURCE(dht11, METHOD_GET, "s/hum", "title=\"Humidity DHTxx\";rt=\"humidity-%\""); + +static void res_get_dht11hum_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_dht11hum, + "title=\"Humidity DHTxx\";rt=\"humidity %\"", + res_get_dht11hum_handler, + NULL, + NULL, + NULL); +static void +res_get_dht11hum_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { char message[100]; int length = 0; /* |<-------->| */ - const uint16_t *accept = NULL; - int num = REST.get_header_accept(request, &accept); + unsigned int accept = -1; + REST.get_header_accept(request, &accept); - if ((num==0) || (num && accept[0]==REST.type.TEXT_PLAIN)) + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { REST.set_header_content_type(response, REST.type.TEXT_PLAIN); snprintf(message, REST_MAX_CHUNK_SIZE, "%d.%02d",dht11_hum/100, dht11_hum % 100); @@ -264,7 +309,7 @@ dht11_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred REST.set_response_payload(response, buffer, length); } - else if (num && (accept[0]==REST.type.APPLICATION_JSON)) + else if (accept == REST.type.APPLICATION_JSON) { REST.set_header_content_type(response, REST.type.APPLICATION_JSON); snprintf(message, REST_MAX_CHUNK_SIZE, "{\"hum\":\"%d.%02d\"}",dht11_hum/100, dht11_hum % 100); @@ -282,104 +327,6 @@ dht11_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred } #endif //REST_RES_DHT11 -/******************************************************************************/ -#if defined (PLATFORM_HAS_LEDS) -/******************************************************************************/ -#if REST_RES_LEDS -/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ -RESOURCE(leds, METHOD_POST | METHOD_PUT , "a/leds", "title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\""); - -void -leds_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 - -/******************************************************************************/ -#if REST_RES_TOGGLE -/* A simple actuator example. Toggles the red led */ -RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "a/toggle", "title=\"Red LED\";rt=\"Control\""); -void -toggle_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) -{ - leds_toggle(LEDS_RED); -} -#endif -#endif /* PLATFORM_HAS_LEDS */ - -/******************************************************************************/ -#if REST_RES_BATTERY && defined (PLATFORM_HAS_BATTERY) -/* A simple getter example. Returns the reading from light sensor with a simple etag */ -RESOURCE(battery, METHOD_GET, "s/battery", "title=\"Battery status\";rt=\"battery-mV\""); -void -battery_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) -{ - int battery = battery_sensor.value(0); - - const uint16_t *accept = NULL; - int num = REST.get_header_accept(request, &accept); - - if ((num==0) || (num && accept[0]==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, (uint8_t *)buffer, strlen((char *)buffer)); - } - else if (num && (accept[0]==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 */ void hw_init() @@ -438,23 +385,20 @@ PROCESS_THREAD(rest_server_example, ev, data) /* Activate the application-specific resources. */ #if REST_RES_DS1820 - rest_activate_resource(&resource_ds1820); + rest_activate_resource(&res_ds1820,"s/temp"); #endif #if REST_RES_DHT11 - rest_activate_resource(&resource_dht11); + rest_activate_resource(&res_dht11hum,"s/hum"); #endif #if REST_RES_DHT11TEMP - rest_activate_resource(&resource_dht11temp); + rest_activate_resource(&res_dht11temp,"s/temp"); #endif #if REST_RES_INFO - rest_activate_resource(&resource_info); + rest_activate_resource(&res_info,"info"); #endif #if defined (PLATFORM_HAS_LEDS) #if REST_RES_LEDS - rest_activate_resource(&resource_leds); -#endif -#if REST_RES_TOGGLE - rest_activate_resource(&resource_toggle); + rest_activate_resource(&res_leds,"a/leds"); #endif #endif /* PLATFORM_HAS_LEDS */ #if defined (PLATFORM_HAS_TEMPERATURE) && REST_RES_TEMPERATURE @@ -463,7 +407,7 @@ PROCESS_THREAD(rest_server_example, ev, data) #endif #if defined (PLATFORM_HAS_BATTERY) && REST_RES_BATTERY SENSORS_ACTIVATE(battery_sensor); - rest_activate_resource(&resource_battery); + rest_activate_resource(&res_battery,"s/battery"); #endif /* Define application-specific events here. */ diff --git a/examples/osd/climate/resources/res-battery.c b/examples/osd/climate/resources/res-battery.c new file mode 100644 index 000000000..b82523594 --- /dev/null +++ b/examples/osd/climate/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", 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); + + 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/climate/resources/res-leds.c b/examples/osd/climate/resources/res-leds.c new file mode 100644 index 000000000..5fbcf6c77 --- /dev/null +++ b/examples/osd/climate/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/climate/resources/res-radio.c b/examples/osd/climate/resources/res-radio.c new file mode 100644 index 000000000..ac09319a3 --- /dev/null +++ b/examples/osd/climate/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/climate/resources/res-sht11.c b/examples/osd/climate/resources/res-sht11.c new file mode 100644 index 000000000..56ed86c01 --- /dev/null +++ b/examples/osd/climate/resources/res-sht11.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, Nimbus Centre for Embedded Systems Research, Cork Institute of Technology. + * 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 + * SHT11 Sensor Resource + * + * This is a simple GET resource that returns the temperature in Celsius + * and the humidity reading from the SHT11. + * \author + * Pablo Corbalan + */ + +#include "contiki.h" + +#if PLATFORM_HAS_SHT11 + +#include +#include "rest-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); + +/* Get Method Example. Returns the reading from temperature and humidity sensors. */ +RESOURCE(res_sht11, + "title=\"Temperature and Humidity\";rt=\"Sht11\"", + 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) +{ + /* Temperature in Celsius (t in 14 bits resolution at 3 Volts) + * T = -39.60 + 0.01*t + */ + uint16_t temperature = ((sht11_sensor.value(SHT11_SENSOR_TEMP) / 10) - 396) / 10; + /* Relative Humidity in percent (h in 12 bits resolution) + * RH = -4 + 0.0405*h - 2.8e-6*(h*h) + */ + uint16_t rh = sht11_sensor.value(SHT11_SENSOR_HUMIDITY); + + 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, "%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); + + 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); + + 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, application/xml, and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} +#endif /* PLATFORM_HAS_SHT11 */