From b71de57f946899a0905dc16fb947c8ad56427509 Mon Sep 17 00:00:00 2001 From: doganyazar Date: Thu, 28 Oct 2010 12:42:07 +0000 Subject: [PATCH] Initial commit of a RESTful web service example using experimental COAP/HTTP/REST implementation for Contiki --- examples/rest-example/Makefile | 31 +++ examples/rest-example/README | 31 +++ examples/rest-example/rest-example-no-rpl.csc | 185 ++++++++++++++++++ .../rest-example/rest-example-with-rpl.csc | 185 ++++++++++++++++++ examples/rest-example/rest-example.c | 136 +++++++++++++ examples/rest-example/web-conf.h | 47 +++++ 6 files changed, 615 insertions(+) create mode 100644 examples/rest-example/Makefile create mode 100644 examples/rest-example/README create mode 100644 examples/rest-example/rest-example-no-rpl.csc create mode 100644 examples/rest-example/rest-example-with-rpl.csc create mode 100644 examples/rest-example/rest-example.c create mode 100644 examples/rest-example/web-conf.h diff --git a/examples/rest-example/Makefile b/examples/rest-example/Makefile new file mode 100644 index 000000000..d436ca787 --- /dev/null +++ b/examples/rest-example/Makefile @@ -0,0 +1,31 @@ +ifndef TARGET +TARGET=sky +endif + +CONTIKI=../.. + +WITH_UIP6=1 +UIP_CONF_IPV6=1 + +WITH_COAP = 1 + +CFLAGS += -DPROJECT_CONF_H=\"web-conf.h\" + +ifdef WITH_COAP +CFLAGS += -DWITH_COAP +APPS = rest-coap +else +CFLAGS += -DWITH_HTTP +APPS = rest-http +endif + +include $(CONTIKI)/Makefile.include + +$(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 aaaa::1/64 diff --git a/examples/rest-example/README b/examples/rest-example/README new file mode 100644 index 000000000..49989dfbc --- /dev/null +++ b/examples/rest-example/README @@ -0,0 +1,31 @@ +COOJA RUN: + +Open a terminal and go to "rest" directory. +In rest/Makefile, define WITH_COAP = 1 if you want to use COAP, rather than HTTP. +Issue following command to load and compile Rest api with COOJA. +>make rest-example-no-rpl.csc TARGET=cooja + +In another terminal, issue the following command +>make connect-router-cooja + +There are 2 nodes running the Rest code in COOJA (node 2 and 6). Their IP addresses are aaaa::0212:7402:0002:0202 and aaaa::0212:7406:0006:0606 respectively. + +TEST: +Please check the rest/rest-example.c source code to see which resources are available. (check the RESOURCE macros in the code). + +COAP Examples: +You can use COAPTester client to interact with the COOJA motes running REST code. + +java COAPTester GET .well-known/core +java COAPTester POST led?color=blue mode=on #turn on the blue led +java COAPTester GET toggle +java COAPTester GET helloworld #get helloworld plain text + + +HTTP Examples +You can use curl as an http client to interact with the COOJA motes running REST code. +curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/helloworld #get helloworld plain text +curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/led?color=green -d mode=off -i #turn off the green led +curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/.well-known/core -i +curl -X POST -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/helloworld #method not allowed + diff --git a/examples/rest-example/rest-example-no-rpl.csc b/examples/rest-example/rest-example-no-rpl.csc new file mode 100644 index 000000000..9a28d0a54 --- /dev/null +++ b/examples/rest-example/rest-example-no-rpl.csc @@ -0,0 +1,185 @@ + + + [CONTIKI_DIR]/tools/cooja/apps/mrm + [CONTIKI_DIR]/tools/cooja/apps/mspsim + [CONTIKI_DIR]/tools/cooja/apps/avrora + [CONTIKI_DIR]/tools/cooja/apps/serial_socket + + Rest without RPL router + -2147483648 + 123456 + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.mspmote.SkyMoteType + rplroot + Sky RPL Root + [CONTIKI_DIR]/examples/ipv6/border-router-no-rpl/border-router.c + make border-router.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/border-router-no-rpl/border-router.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.SkyByteRadio + 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 + skyweb + Rest + [CONTIKI_DIR]/examples/rest-example/rest-example.c + make rest-example.sky TARGET=sky + [CONTIKI_DIR]/examples/rest-example/rest-example.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.SkyByteRadio + 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 + 33.260163187353555 + 30.643217359962595 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 1 + + rplroot + + + + + se.sics.cooja.interfaces.Position + 62.239287566073514 + 34.43810269527116 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 2 + + skyweb + + + + + se.sics.cooja.interfaces.Position + 47.68359039801751 + 47.26544238238854 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 6 + + skyweb + + + + se.sics.cooja.plugins.SimControl + 259 + 1 + 179 + 0 + 0 + + + se.sics.cooja.plugins.Visualizer + + se.sics.cooja.plugins.skins.IDVisualizerSkin + se.sics.cooja.plugins.skins.UDGMVisualizerSkin + se.sics.cooja.plugins.skins.MoteTypeVisualizerSkin + se.sics.cooja.plugins.skins.AttributeVisualizerSkin + 10.505309204322225 0.0 0.0 10.505309204322225 -249.89475921566975 -141.01191150973983 + + 819 + 5 + 563 + 35 + 306 + + + se.sics.cooja.plugins.LogListener + + + + 762 + 0 + 326 + 36 + 296 + + + se.sics.cooja.plugins.RadioLogger + + 150 + + + 815 + 4 + 385 + 255 + 8 + + + SerialSocketServer + 0 + 422 + 3 + 74 + 1234 + 93 + + + se.sics.cooja.plugins.TimeLine + + 0 + 1 + + + + + 125 + 25.49079397896416 + + 1624 + 2 + 252 + 166 + 699 + + + diff --git a/examples/rest-example/rest-example-with-rpl.csc b/examples/rest-example/rest-example-with-rpl.csc new file mode 100644 index 000000000..001ea683d --- /dev/null +++ b/examples/rest-example/rest-example-with-rpl.csc @@ -0,0 +1,185 @@ + + + [CONTIKI_DIR]/tools/cooja/apps/mrm + [CONTIKI_DIR]/tools/cooja/apps/mspsim + [CONTIKI_DIR]/tools/cooja/apps/avrora + [CONTIKI_DIR]/tools/cooja/apps/serial_socket + + Rest with RPL router + -2147483648 + 123456 + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.mspmote.SkyMoteType + rplroot + Sky RPL Root + [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.c + make border-router.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.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.SkyByteRadio + 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 + skyweb + Rest + [CONTIKI_DIR]/examples/rest-example/rest-example.c + make rest-example.sky TARGET=sky + [CONTIKI_DIR]/examples/rest-example/rest-example.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.SkyByteRadio + 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 + 33.260163187353555 + 30.643217359962595 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 1 + + rplroot + + + + + se.sics.cooja.interfaces.Position + 62.239287566073514 + 34.43810269527116 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 2 + + skyweb + + + + + se.sics.cooja.interfaces.Position + 47.68359039801751 + 47.26544238238854 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 6 + + skyweb + + + + se.sics.cooja.plugins.SimControl + 259 + 1 + 179 + 0 + 0 + + + se.sics.cooja.plugins.Visualizer + + se.sics.cooja.plugins.skins.IDVisualizerSkin + se.sics.cooja.plugins.skins.UDGMVisualizerSkin + se.sics.cooja.plugins.skins.MoteTypeVisualizerSkin + se.sics.cooja.plugins.skins.AttributeVisualizerSkin + 10.505309204322225 0.0 0.0 10.505309204322225 -249.89475921566975 -141.01191150973983 + + 819 + 5 + 563 + 35 + 306 + + + se.sics.cooja.plugins.LogListener + + + + 762 + 0 + 326 + 36 + 296 + + + se.sics.cooja.plugins.RadioLogger + + 150 + + + 815 + 4 + 385 + 255 + 8 + + + SerialSocketServer + 0 + 422 + 3 + 74 + 1234 + 93 + + + se.sics.cooja.plugins.TimeLine + + 0 + 1 + + + + + 125 + 25.49079397896416 + + 1624 + 2 + 252 + 166 + 699 + + + diff --git a/examples/rest-example/rest-example.c b/examples/rest-example/rest-example.c new file mode 100644 index 000000000..063b939b2 --- /dev/null +++ b/examples/rest-example/rest-example.c @@ -0,0 +1,136 @@ +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "dev/leds.h" + +#include "rest.h" + +PROCESS(rest_example, "Rest Example"); +AUTOSTART_PROCESSES(&rest_example); + +#define DEBUG 1 +#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 ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_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 + +char temp[100]; + +/* Resources are defined by RESOURCE macro, signature: resource name, the http methods it handles and its url*/ +RESOURCE(helloworld, METHOD_GET, "helloworld"); + +/* For each resource defined, there corresponds an handler method which should be defined too. + * Name of the handler method should be [resource name]_handler + * */ +void +helloworld_handler(REQUEST* request, RESPONSE* response) +{ + sprintf(temp,"Hello World!\n"); + + rest_set_header_content_type(response, TEXT_PLAIN); + rest_set_payload(response, temp, strlen(temp)); +} + +/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ +RESOURCE(led, METHOD_POST | METHOD_PUT , "led"); + +void +led_handler(REQUEST* request, RESPONSE* response) +{ + char color[10]; + char mode[10]; + uint8_t led = 0; + int success = 1; + + if (rest_get_query_variable(request, "color", color, 10)) { + PRINTF("color %s\n", color); + + if (!strcmp(color,"red")) { + led = LEDS_RED; + } else if(!strcmp(color,"green")) { + led = LEDS_GREEN; + } else if ( !strcmp(color,"blue") ) { + led = LEDS_BLUE; + } else { + success = 0; + } + } else { + success = 0; + } + + if (success && rest_get_post_variable(request, "mode", mode, 10)) { + PRINTF("mode %s\n", mode); + + if (!strcmp(mode, "on")) { + leds_on(led); + } else if (!strcmp(mode, "off")) { + leds_off(led); + } else { + success = 0; + } + } else { + success = 0; + } + + if (!success) { + rest_set_response_status(response, BAD_REQUEST_400); + } +} + +/*A simple getter example. Returns the reading from light sensor with a simple etag*/ +RESOURCE(light, METHOD_GET, "light"); +void +light_handler(REQUEST* request, RESPONSE* response) +{ + sprintf(temp,"%d.%d", 131,6); + + char etag[4] = "ABCD"; + rest_set_header_content_type(response, TEXT_PLAIN); + rest_set_header_etag(response, etag, sizeof(etag)); + rest_set_payload(response, temp, strlen(temp)); +} + +/*A simple actuator example. Toggles the red led*/ +RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "toggle"); +void +toggle_handler(REQUEST* request, RESPONSE* response) +{ + leds_toggle(LEDS_RED); +} + +RESOURCE(discover, METHOD_GET, ".well-known/core"); +void +discover_handler(REQUEST* request, RESPONSE* response) +{ + char temp[100]; + int index = 0; + index += sprintf(temp + index, "%s\n", ";n=\"HelloWorld\""); + index += sprintf(temp + index, "%s\n", ";n=\"LedControl\""); + index += sprintf(temp + index, "%s\n", ";n=\"Light\""); + + rest_set_payload(response, temp, strlen(temp)); + rest_set_header_content_type(response, APPLICATION_LINK_FORMAT); +} + +PROCESS_THREAD(rest_example, ev, data) +{ + PROCESS_BEGIN(); + PRINTF("REST Example\n"); + + rest_init(); + + rest_activate_resource(&resource_helloworld); + rest_activate_resource(&resource_led); + rest_activate_resource(&resource_light); + rest_activate_resource(&resource_toggle); + rest_activate_resource(&resource_discover); + + PROCESS_END(); +} diff --git a/examples/rest-example/web-conf.h b/examples/rest-example/web-conf.h new file mode 100644 index 000000000..5e0df54e2 --- /dev/null +++ b/examples/rest-example/web-conf.h @@ -0,0 +1,47 @@ +/* + * 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. + * + * $Id: web-conf.h,v 1.1 2010/10/28 12:42:07 doganyazar Exp $ + */ + +#ifndef __PROJECT_RPL_WEB_CONF_H__ +#define __PROJECT_RPL_WEB_CONF_H__ + +#undef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 6 + +#undef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 140 + +#undef UIP_CONF_RECEIVE_WINDOW +#define UIP_CONF_RECEIVE_WINDOW 60 + +#undef WEBSERVER_CONF_CFS_CONNS +#define WEBSERVER_CONF_CFS_CONNS 2 + +#endif /* __PROJECT_RPL_WEB_CONF_H__ */