diff --git a/examples/er-rest-example/er-example-observe-client.c b/examples/er-rest-example/er-example-observe-client.c new file mode 100644 index 000000000..c950fdfd7 --- /dev/null +++ b/examples/er-rest-example/er-example-observe-client.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014, Daniele Alessandrelli. + * 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 observe client example. + * \author + * Daniele Alessandrelli + */ + +#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 +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINTFLN(format, ...) printf(format "\n", ##__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \ + "%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \ + ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \ + ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \ + ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \ + ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \ + ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \ + ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \ + ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \ + ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#define PRINTFLN(...) +#endif + +/*----------------------------------------------------------------------------*/ +/* FIXME: This server address is hard-coded for Cooja */ +#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, \ + 0x7402, 0x0002, 0x0202) +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +/* Toggle interval in seconds */ +#define TOGGLE_INTERVAL 30 +/* The path of the resource to observe */ +#define OBS_RESOURCE_URI "test/push" + +/*----------------------------------------------------------------------------*/ +static uip_ipaddr_t server_ipaddr[1]; /* holds the server ip address */ +static coap_observee_t *obs; + +/*----------------------------------------------------------------------------*/ +PROCESS(er_example_observe_client, "Erbium Coap Observe Client Example"); +AUTOSTART_PROCESSES(&er_example_observe_client); + +/*----------------------------------------------------------------------------*/ +/* + * Handle the response to the observe request and the following notifications + */ +static void +notification_callback(coap_observee_t *obs, void *notification, + coap_notification_flag_t flag) +{ + int len = 0; + const uint8_t *payload = NULL; + + printf("Notification handler\n"); + printf("Observee URI: %s\n", obs->url); + if(notification) { + len = coap_get_payload(notification, &payload); + } + switch(flag) { + case NOTIFICATION_OK: + printf("NOTIFICATION OK: %*s\n", len, (char *)payload); + break; + case OBSERVE_OK: /* server accepeted observation request */ + printf("OBSERVE_OK: %*s\n", len, (char *)payload); + break; + case OBSERVE_NOT_SUPPORTED: + printf("OBSERVE_NOT_SUPPORTED: %*s\n", len, (char *)payload); + obs = NULL; + break; + case ERROR_RESPONSE_CODE: + printf("ERROR_RESPONSE_CODE: %*s\n", len, (char *)payload); + obs = NULL; + break; + case NO_REPLY_FROM_SERVER: + printf("NO_REPLY_FROM_SERVER: " + "removing observe registration with token %x%x\n", + obs->token[0], obs->token[1]); + obs = NULL; + break; + } +} +/*----------------------------------------------------------------------------*/ +/* + * Toggle the observation of the remote resource + */ +void +toggle_observation(void) +{ + if(obs) { + printf("Stopping observation\n"); + coap_obs_remove_observee(obs); + obs = NULL; + } else { + printf("Starting observation\n"); + obs = coap_obs_request_registration(server_ipaddr, REMOTE_PORT, + OBS_RESOURCE_URI, notification_callback, NULL); + } +} +/*----------------------------------------------------------------------------*/ +/* + * The main (proto-)thread. It starts/stops the observation of the remote + * resource every time the timer elapses or the button (if available) is + * pressed + */ +PROCESS_THREAD(er_example_observe_client, ev, data) +{ + PROCESS_BEGIN(); + + static struct etimer et; + + /* store server address in server_ipaddr */ + SERVER_NODE(server_ipaddr); + /* receives all CoAP messages */ + coap_init_engine(); + /* init timer and button (if available) */ + etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND); +#if PLATFORM_HAS_BUTTON + SENSORS_ACTIVATE(button_sensor); + printf("Press a button to start/stop observation of remote resource\n"); +#endif + /* toggle observation every time the timer elapses or the button is pressed */ + while(1) { + PROCESS_YIELD(); + if(etimer_expired(&et)) { + printf("--Toggle timer--\n"); + toggle_observation(); + printf("\n--Done--\n"); + etimer_reset(&et); +#if PLATFORM_HAS_BUTTON + } else if(ev == sensors_event && data == &button_sensor) { + printf("--Toggle tutton--\n"); + toggle_observation(); + printf("\n--Done--\n"); +#endif + } + } + PROCESS_END(); +} diff --git a/examples/er-rest-example/project-conf.h b/examples/er-rest-example/project-conf.h index 93c3c7281..53662619a 100644 --- a/examples/er-rest-example/project-conf.h +++ b/examples/er-rest-example/project-conf.h @@ -93,4 +93,6 @@ #undef COAP_PROXY_OPTION_PROCESSING #define COAP_PROXY_OPTION_PROCESSING 0 +/* Enable client-side support for COAP observe */ +#define COAP_OBSERVE_CLIENT 1 #endif /* __PROJECT_ERBIUM_CONF_H__ */ diff --git a/examples/er-rest-example/server-client-observe.csc b/examples/er-rest-example/server-client-observe.csc new file mode 100644 index 000000000..5d006056a --- /dev/null +++ b/examples/er-rest-example/server-client-observe.csc @@ -0,0 +1,203 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + REST with RPL router + 1.0 + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.mspmote.SkyMoteType + rplroot + Sky RPL Root + [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.c + make border-router.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + org.contikios.cooja.mspmote.SkyMoteType + server + Erbium Server + [CONTIKI_DIR]/examples/er-rest-example/er-example-server.c + make er-example-server.sky TARGET=sky + [CONTIKI_DIR]/examples/er-rest-example/er-example-server.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + org.contikios.cooja.mspmote.SkyMoteType + client + Erbium Client + [CONTIKI_DIR]/examples/er-rest-example/er-example-observe-client.c + make er-example-observe-client.sky TARGET=sky + [CONTIKI_DIR]/examples/er-rest-example/er-example-observe-client.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + + + org.contikios.cooja.interfaces.Position + 33.260163187353555 + 30.643217359962595 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 1 + + rplroot + + + + + org.contikios.cooja.interfaces.Position + 54.537149936813485 + 51.51086225537906 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 2 + + server + + + + + org.contikios.cooja.interfaces.Position + 77.97942851220571 + 67.86182390447284 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 3 + + client + + + + org.contikios.cooja.plugins.SimControl + 259 + 3 + 179 + 2 + 1 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + org.contikios.cooja.plugins.skins.AttributeVisualizerSkin + org.contikios.cooja.plugins.skins.LEDVisualizerSkin + org.contikios.cooja.plugins.skins.AddressVisualizerSkin + 2.092412892721766 0.0 0.0 2.092412892721766 34.70057915472623 -45.606066372444175 + + 300 + 4 + 178 + 261 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 762 + 0 + 491 + 2 + 182 + + + org.contikios.cooja.plugins.RadioLogger + + 167 + + false + false + + + 560 + 1 + 492 + 764 + 181 + + + org.contikios.cooja.serialsocket.SerialSocketServer + 0 + + 60001 + true + + 362 + 2 + 116 + 561 + 1 + + +