From ba3c167ceffe5153819cd47de4436aa4c0faa2b2 Mon Sep 17 00:00:00 2001 From: Cristiano De Alti Date: Mon, 21 Sep 2015 23:12:16 +0200 Subject: [PATCH 1/2] Add a new periodic temperature resource. The temperature sensor is sampled once per second. If observed, temperature readings are reported on change or every Max-Age interval (default: 60s). --- .../resources/res-temperature.c | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 examples/er-rest-example/resources/res-temperature.c diff --git a/examples/er-rest-example/resources/res-temperature.c b/examples/er-rest-example/resources/res-temperature.c new file mode 100644 index 000000000..c8bce8ba8 --- /dev/null +++ b/examples/er-rest-example/resources/res-temperature.c @@ -0,0 +1,125 @@ +/* + * 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 of an observable "on-change" temperature resource + * \author + * Matthias Kovatsch + * \author + * Cristiano De Alti + */ + +#include "contiki.h" + +#if PLATFORM_HAS_TEMPERATURE + +#include +#include +#include +#include "rest-engine.h" +#include "dev/temperature-sensor.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_periodic_handler(void); + +#define MAX_AGE 60 +#define INTERVAL_MIN 5 +#define INTERVAL_MAX (MAX_AGE - 1) +#define CHANGE 1 + +static int32_t interval_counter = INTERVAL_MIN; +static int temperature_old = INT_MIN; + +PERIODIC_RESOURCE(res_temperature, + "title=\"Temperature\";rt=\"Temperature\";obs", + res_get_handler, + NULL, + NULL, + NULL, + CLOCK_SECOND, + res_periodic_handler); + +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/! + */ + + int temperature = temperature_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", temperature); + + REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature); + + 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)); + } + + REST.set_header_max_age(response, MAX_AGE); + + /* 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() +{ + int temperature = temperature_sensor.value(0); + + ++interval_counter; + + if((abs(temperature - temperature_old) >= CHANGE && interval_counter >= INTERVAL_MIN) || + interval_counter >= INTERVAL_MAX) { + interval_counter = 0; + temperature_old = temperature; + /* Notify the registered observers which will trigger the res_get_handler to create the response. */ + REST.notify_subscribers(&res_temperature); + } +} +#endif /* PLATFORM_HAS_TEMPERATURE */ From 6e91cb3a3919a153cd65c08baf39f5142867e248 Mon Sep 17 00:00:00 2001 From: Cristiano De Alti Date: Mon, 21 Sep 2015 23:20:45 +0200 Subject: [PATCH 2/2] Activate battery and temperature resources if they are supported by the platform. --- examples/er-rest-example/er-example-server.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/er-rest-example/er-example-server.c b/examples/er-rest-example/er-example-server.c index 41a07a501..d8e1c79b2 100644 --- a/examples/er-rest-example/er-example-server.c +++ b/examples/er-rest-example/er-example-server.c @@ -79,11 +79,17 @@ extern resource_t res_leds, res_toggle; #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_TEMPERATURE +#include "dev/temperature-sensor.h" +extern resource_t res_temperature; +#endif +/* +extern resource_t res_battery; +#endif #if PLATFORM_HAS_RADIO #include "dev/radio-sensor.h" extern resource_t res_radio; @@ -141,11 +147,15 @@ PROCESS_THREAD(er_example_server, ev, data) rest_activate_resource(&res_light, "sensors/light"); SENSORS_ACTIVATE(light_sensor); #endif -/* #if PLATFORM_HAS_BATTERY rest_activate_resource(&res_battery, "sensors/battery"); SENSORS_ACTIVATE(battery_sensor); #endif +#if PLATFORM_HAS_TEMPERATURE + rest_activate_resource(&res_temperature, "sensors/temperature"); + SENSORS_ACTIVATE(temperature_sensor); +#endif +/* #if PLATFORM_HAS_RADIO rest_activate_resource(&res_radio, "sensors/radio"); SENSORS_ACTIVATE(radio_sensor);