Imported ipso-objects from lwm2m-contiki at https://github.com/sics-iot/lwm2m-contiki

This commit is contained in:
Niclas Finne 2017-10-25 02:27:14 +02:00
parent 49d9ec182d
commit 83446e3f58
14 changed files with 1055 additions and 146 deletions

View File

@ -38,7 +38,13 @@
#include "contiki.h"
#include "services/lwm2m/lwm2m-engine.h"
#include "services/lwm2m/lwm2m-rd-client.h"
#include "services/lwm2m/lwm2m-device.h"
#include "services/lwm2m/lwm2m-server.h"
#include "services/lwm2m/lwm2m-security.h"
#include "services/ipso-objects/ipso-objects.h"
#include "services/ipso-objects/ipso-sensor-template.h"
#include "services/ipso-objects/ipso-control-template.h"
#define DEBUG DEBUG_NONE
#include "net/ipv6/uip-debug.h"
@ -52,7 +58,101 @@
#endif
#ifndef LWM2M_SERVER_ADDRESS
#define LWM2M_SERVER_ADDRESS "fd00::1"
#define LWM2M_SERVER_ADDRESS "coap://[fd00::1]"
#endif
#if BOARD_SENSORTAG
#include "board-peripherals.h"
/* Temperature reading */
static lwm2m_status_t
read_temp_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP);
return LWM2M_STATUS_OK;
}
/* Humitidy reading */
static lwm2m_status_t
read_hum_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY);
return LWM2M_STATUS_OK;
}
/* Lux reading */
static lwm2m_status_t
read_lux_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * opt_3001_sensor.value(0);
return LWM2M_STATUS_OK;
}
/* Barometer reading */
static lwm2m_status_t
read_bar_value(const ipso_sensor_t *s, int32_t *value)
{
*value = 10 * bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS);
return LWM2M_STATUS_OK;
}
/* LED control */
static lwm2m_status_t
leds_set_val(uint8_t value)
{
if(value > 0) {
leds_on(LEDS_YELLOW);
} else {
leds_off(LEDS_YELLOW);
}
return LWM2M_STATUS_OK;
}
/*---------------------------------------------------------------------------*/
static ipso_sensor_value_t temp_value;
static ipso_sensor_value_t hum_value;
static ipso_sensor_value_t lux_value;
static ipso_sensor_value_t bar_value;
static ipso_control_t led_control = {
.reg_object.object_id = 3311,
.reg_object.instance_id = 0,
.set_value = leds_set_val
};
static const ipso_sensor_t temp_sensor = {
.object_id = 3303,
.sensor_value = &temp_value,
.max_range = 100000, /* 100 cel milli celcius */
.min_range = -10000, /* -10 cel milli celcius */
.get_value_in_millis = read_temp_value,
.unit = "Cel",
.update_interval = 30
};
static const ipso_sensor_t hum_sensor = {
.object_id = 3304,
.sensor_value = &hum_value,
.max_range = 100000, /* 100 % RH */
.min_range = 0,
.get_value_in_millis = read_hum_value,
.unit = "% RH",
.update_interval = 30
};
static const ipso_sensor_t lux_sensor = {
.object_id = 3301,
.sensor_value = &lux_value,
.max_range = 100000,
.min_range = -10000,
.get_value_in_millis = read_lux_value,
.unit = "LUX",
.update_interval = 30
};
static const ipso_sensor_t bar_sensor = {
.object_id = 3315,
.sensor_value = &bar_value,
.max_range = 100000, /* 100 cel milli celcius */
.min_range = -10000, /* -10 cel milli celcius */
.get_value_in_millis = read_bar_value,
.unit = "hPa",
.update_interval = 30
};
#endif
PROCESS(example_ipso_objects, "IPSO object example");
@ -62,39 +162,70 @@ static void
setup_lwm2m_servers(void)
{
#ifdef LWM2M_SERVER_ADDRESS
uip_ipaddr_t addr;
if(uiplib_ipaddrconv(LWM2M_SERVER_ADDRESS, &addr)) {
lwm2m_engine_register_with_bootstrap_server(&addr, 0);
lwm2m_engine_register_with_server(&addr, 0);
coap_endpoint_t server_ep;
if(coap_endpoint_parse(LWM2M_SERVER_ADDRESS, strlen(LWM2M_SERVER_ADDRESS),
&server_ep) != 0) {
lwm2m_rd_client_register_with_bootstrap_server(&server_ep);
lwm2m_rd_client_register_with_server(&server_ep);
}
#endif /* LWM2M_SERVER_ADDRESS */
lwm2m_engine_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER);
lwm2m_engine_use_registration_server(REGISTER_WITH_LWM2M_SERVER);
lwm2m_rd_client_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER);
lwm2m_rd_client_use_registration_server(REGISTER_WITH_LWM2M_SERVER);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_ipso_objects, ev, data)
{
static struct etimer periodic;
PROCESS_BEGIN();
PROCESS_PAUSE();
PRINTF("Starting IPSO objects example\n");
PRINTF("Starting IPSO objects example%s\n",
REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER ? " (bootstrap)" : "");
/* Initialize the OMA LWM2M engine */
lwm2m_engine_init();
/* Register default LWM2M objects */
lwm2m_engine_register_default_objects();
lwm2m_device_init();
lwm2m_security_init();
lwm2m_server_init();
/* Register default IPSO objects */
#if BOARD_SENSORTAG
ipso_sensor_add(&temp_sensor);
ipso_sensor_add(&hum_sensor);
ipso_sensor_add(&lux_sensor);
ipso_sensor_add(&bar_sensor);
ipso_control_add(&led_control);
ipso_button_init();
SENSORS_ACTIVATE(hdc_1000_sensor);
SENSORS_ACTIVATE(opt_3001_sensor);
SENSORS_ACTIVATE(bmp_280_sensor);
#else /* BOARD_SENSORTAG */
/* Register default IPSO objects - such as button..*/
ipso_objects_init();
#endif /* BOARD_SENSORTAG */
setup_lwm2m_servers();
/* Tick loop each 5 seconds */
etimer_set(&periodic, CLOCK_SECOND * 5);
while(1) {
PROCESS_WAIT_EVENT();
}
if(ev == PROCESS_EVENT_TIMER && etimer_expired(&periodic)) {
#if BOARD_SENSORTAG
/* deactive / activate to do a new reading */
SENSORS_DEACTIVATE(hdc_1000_sensor);
SENSORS_DEACTIVATE(opt_3001_sensor);
SENSORS_DEACTIVATE(bmp_280_sensor);
SENSORS_ACTIVATE(hdc_1000_sensor);
SENSORS_ACTIVATE(opt_3001_sensor);
SENSORS_ACTIVATE(bmp_280_sensor);
#endif /* BOARD_SENSORTAG */
etimer_reset(&periodic);
}
}
PROCESS_END();
}

View File

@ -44,7 +44,7 @@
#include "coap-constants.h"
#include "coap-engine.h"
#include "lwm2m-engine.h"
#include "oma-tlv.h"
#include "lwm2m-tlv.h"
#include "dev/serial-line.h"
#include "serial-protocol.h"
@ -187,13 +187,13 @@ client_chunk_handler(void *response)
} else {
/* otherwise update the current value */
if(format == LWM2M_TLV) {
oma_tlv_t tlv;
lwm2m_tlv_t tlv;
/* we can only read int32 for now ? */
if(oma_tlv_read(&tlv, chunk, len) > 0) {
if(lwm2m_tlv_read(&tlv, chunk, len) > 0) {
/* printf("TLV.type=%d len=%d id=%d value[0]=%d\n", */
/* tlv.type, tlv.length, tlv.id, tlv.value[0]); */
int value = oma_tlv_get_int32(&tlv);
int value = lwm2m_tlv_get_int32(&tlv);
snprintf(current_value, sizeof(current_value), "%d", value);
}
} else {
@ -269,7 +269,7 @@ PROCESS_THREAD(router_process, ev, data)
PROCESS_PAUSE();
/* receives all CoAP messages */
coap_init_engine();
coap_engine_init();
setup_network();

View File

@ -30,6 +30,9 @@
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
/* No sleep on CC2538 to enable full 32 KiB RAM */
#define LPM_CONF_ENABLE 0
#ifdef BOARD_STRING
#define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING
#elif defined(CONTIKI_TARGET_WISMOTE)
@ -40,10 +43,14 @@
#define PLATFORM_REBOOT watchdog_reboot
#endif
#if BOARD_SENSORTAG
/* Real sensor is present... */
#else
#define IPSO_TEMPERATURE example_ipso_temperature
#endif /* BOARD_SENSORTAG */
/* Increase rpl-border-router IP-buffer when using more than 64. */
#define REST_MAX_CHUNK_SIZE 64
#define COAP_MAX_CHUNK_SIZE 64
/* Multiplies with chunk size, be aware of memory constraints. */
#define COAP_MAX_OPEN_TRANSACTIONS 4

View File

@ -1 +0,0 @@
CFLAGS += -DWITH_IPSO=1

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2016, SICS Swedish ICT AB
* 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 copyright holder 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 COPYRIGHT HOLDER 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup ipso-objects
* @{
*
* Code to test blockwise transfer together with the LWM2M-engine.
* This object tests get with BLOCK2 and put with BLOCK1.
*
*/
#include "lwm2m-engine.h"
#include "coap.h"
#include <string.h>
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
static lwm2m_object_instance_t reg_object;
static char junk[64];
static const lwm2m_resource_id_t resources[] =
{
RO(10000),
RO(11000),
RW(11001)
};
#define LEN 900
static lwm2m_status_t
opaque_callback(lwm2m_object_instance_t *object,
lwm2m_context_t *ctx, int num_to_write)
{
int i;
PRINTF("opaque-stream callback num_to_write: %d off: %d outlen: %d\n",
num_to_write, ctx->offset, ctx->outbuf->len);
for(i = 0; i < num_to_write; i++) {
ctx->outbuf->buffer[i + ctx->outbuf->len] = '0' + (i & 31);
if(i + ctx->offset == LEN) break;
}
ctx->outbuf->len += i;
if(ctx->offset + i < LEN) {
ctx->writer_flags |= WRITER_HAS_MORE;
}
return LWM2M_STATUS_OK;
}
/*---------------------------------------------------------------------------*/
static lwm2m_status_t
lwm2m_callback(lwm2m_object_instance_t *object,
lwm2m_context_t *ctx)
{
uint32_t num;
uint8_t more;
uint16_t size;
uint32_t offset;
char *str = "just a string";
PRINTF("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level);
if(ctx->level == 1) {
/* Should not happen */
return LWM2M_STATUS_ERROR;
}
if(ctx->level == 2) {
/* This is a get whole object - or write whole object */
return LWM2M_STATUS_ERROR;
}
if(ctx->operation == LWM2M_OP_READ) {
#if DEBUG
if(coap_get_header_block2(ctx->request, &num, &more, &size, &offset)) {
PRINTF("CoAP BLOCK2: %d/%d/%d offset:%d\n", num, more, size, offset);
}
#endif
switch(ctx->resource_id) {
case 10000:
lwm2m_object_write_string(ctx, str, strlen(str));
break;
case 11000:
case 11001:
PRINTF("Preparing object write\n");
lwm2m_object_write_opaque_stream(ctx, LEN, opaque_callback);
break;
default:
return LWM2M_STATUS_NOT_FOUND;
}
} else if(ctx->operation == LWM2M_OP_WRITE) {
if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) {
PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset);
coap_set_header_block1(ctx->response, num, 0, size);
}
}
return LWM2M_STATUS_OK;
}
void
ipso_blockwise_test_init(void)
{
int i;
PRINTF("Starting blockwise\n");
reg_object.object_id = 4711;
reg_object.instance_id = 0;
reg_object.resource_ids = resources;
reg_object.resource_count =
sizeof(resources) / sizeof(lwm2m_resource_id_t);
reg_object.callback = lwm2m_callback;
for(i = 0; i < sizeof(junk); i++) {
junk[i] = '0' + i;
}
junk[i - 1] = 0;
lwm2m_engine_add_object(&reg_object);
}

View File

@ -36,6 +36,7 @@
/**
* \file
* Implementation of OMA LWM2M / IPSO button as a digital input
* NOTE: only works with a Contiki Button Sensor (not for Standalone)
* \author
* Joakim Eriksson <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
@ -44,7 +45,6 @@
#include "contiki.h"
#include "lwm2m-object.h"
#include "lwm2m-engine.h"
#include "coap-engine.h"
#define DEBUG 0
#if DEBUG
@ -54,20 +54,55 @@
#define PRINTF(...)
#endif
#define IPSO_INPUT_STATE 5500
#define IPSO_INPUT_COUNTER 5501
#define IPSO_INPUT_POLARITY 5502
#define IPSO_INPUT_DEBOUNCE 5503
#define IPSO_INPUT_EDGE_SEL 5504
#define IPSO_INPUT_CTR_RESET 5505
#define IPSO_INPUT_SENSOR_TYPE 5751
#if PLATFORM_HAS_BUTTON
#include "dev/button-sensor.h"
#if BOARD_SENSORTAG
#include "sensortag/button-sensor.h"
#define IPSO_BUTTON_SENSOR button_left_sensor
#else
#define IPSO_BUTTON_SENSOR button_sensor
#endif
PROCESS(ipso_button_process, "ipso-button");
#endif /* PLATFORM_HAS_BUTTON */
static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object,
lwm2m_context_t *ctx);
static int input_state = 0;
static int polarity = 0;
static int32_t counter = 0;
static int32_t edge_selection = 3;
static int32_t edge_selection = 3; /* both */
static int32_t debounce_time = 10;
static const lwm2m_resource_id_t resources[] = {
RO(IPSO_INPUT_STATE), RO(IPSO_INPUT_COUNTER), RW(IPSO_INPUT_POLARITY),
RW(IPSO_INPUT_DEBOUNCE), RW(IPSO_INPUT_EDGE_SEL), EX(IPSO_INPUT_CTR_RESET),
RO(IPSO_INPUT_SENSOR_TYPE)
};
/* Only support for one button for now */
static lwm2m_object_instance_t reg_object = {
.object_id = 3200,
.instance_id = 0,
.resource_ids = resources,
.resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t),
.callback = lwm2m_callback,
};
/*---------------------------------------------------------------------------*/
static int
read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
read_state(void)
{
int value;
if(polarity == 0) {
@ -77,36 +112,53 @@ read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
}
PRINTF("Read button state (polarity=%d, state=%d): %d\n",
polarity, input_state, value);
return ctx->writer->write_boolean(ctx, outbuf, outsize, value);
return value;
}
/*---------------------------------------------------------------------------*/
static int
reset_counter(lwm2m_context_t *ctx, const uint8_t *arg, size_t len,
uint8_t *outbuf, size_t outlen)
/*---------------------------------------------------------------------------*/
static lwm2m_status_t
lwm2m_callback(lwm2m_object_instance_t *object,
lwm2m_context_t *ctx)
{
counter = 0;
return 0;
if(ctx->operation == LWM2M_OP_READ) {
switch(ctx->resource_id) {
case IPSO_INPUT_STATE:
lwm2m_object_write_int(ctx, read_state());
break;
case IPSO_INPUT_COUNTER:
lwm2m_object_write_int(ctx, counter);
break;
case IPSO_INPUT_POLARITY:
lwm2m_object_write_int(ctx, polarity);
break;
case IPSO_INPUT_DEBOUNCE:
lwm2m_object_write_int(ctx, debounce_time);
break;
case IPSO_INPUT_EDGE_SEL:
lwm2m_object_write_int(ctx, edge_selection);
break;
case IPSO_INPUT_SENSOR_TYPE:
lwm2m_object_write_string(ctx, "button", strlen("button"));
break;
default:
return LWM2M_STATUS_ERROR;
}
} else if(ctx->operation == LWM2M_OP_EXECUTE) {
if(ctx->resource_id == IPSO_INPUT_CTR_RESET) {
counter = 0;
} else {
return LWM2M_STATUS_ERROR;
}
}
return LWM2M_STATUS_OK;
}
/*---------------------------------------------------------------------------*/
LWM2M_RESOURCES(button_resources,
LWM2M_RESOURCE_CALLBACK(5500, { read_state, NULL, NULL }),
LWM2M_RESOURCE_INTEGER_VAR(5501, &counter),
LWM2M_RESOURCE_BOOLEAN_VAR(5502, &polarity),
LWM2M_RESOURCE_INTEGER_VAR(5503, &debounce_time),
LWM2M_RESOURCE_INTEGER_VAR(5504, &edge_selection),
LWM2M_RESOURCE_CALLBACK(5505, { NULL, NULL, reset_counter }),
LWM2M_RESOURCE_STRING(5751, "Button")
);
LWM2M_INSTANCES(button_instances,
LWM2M_INSTANCE(0, button_resources));
LWM2M_OBJECT(button, 3200, button_instances);
/*---------------------------------------------------------------------------*/
void
ipso_button_init(void)
{
/* register this device and its handlers - the handlers automatically
sends in the object to handle */
lwm2m_engine_register_object(&button);
lwm2m_engine_add_object(&reg_object);
#if PLATFORM_HAS_BUTTON
process_start(&ipso_button_process, NULL);
@ -121,19 +173,19 @@ PROCESS_THREAD(ipso_button_process, ev, data)
PROCESS_BEGIN();
SENSORS_ACTIVATE(button_sensor);
SENSORS_ACTIVATE(IPSO_BUTTON_SENSOR);
while(1) {
PROCESS_WAIT_EVENT();
if(ev == sensors_event && data == &button_sensor) {
if(ev == sensors_event && data == &IPSO_BUTTON_SENSOR) {
if(!input_state) {
input_state = 1;
counter++;
if((edge_selection & 2) != 0) {
lwm2m_object_notify_observers(&button, "/0/5500");
lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_STATE);
}
lwm2m_object_notify_observers(&button, "/0/5501");
lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_COUNTER);
time = (debounce_time * CLOCK_SECOND / 1000);
if(time < 1) {
@ -144,13 +196,13 @@ PROCESS_THREAD(ipso_button_process, ev, data)
} else if(ev == PROCESS_EVENT_TIMER && data == &timer) {
if(!input_state) {
/* Button is not in pressed state */
} else if(button_sensor.value(0) != 0) {
} else if(IPSO_BUTTON_SENSOR.value(0) != 0) {
/* Button is still pressed */
etimer_reset(&timer);
} else {
input_state = 0;
if((edge_selection & 1) != 0) {
lwm2m_object_notify_observers(&button, "/0/5500");
lwm2m_notify_object_observers(&reg_object, IPSO_INPUT_STATE);
}
}
}

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2016, SICS Swedish ICT AB
* 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 copyright holder 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 COPYRIGHT HOLDER 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup ipso-objects
* @{
*
*/
/**
* \file
* Implementation of OMA LWM2M / IPSO control template.
* Useful for implementing controllable objects
* \author
* Joakim Eriksson <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
#include "ipso-control-template.h"
#include "lwm2m-engine.h"
#include "coap-timer.h"
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#define IPSO_ONOFF 5850
#define IPSO_DIMMER 5851
#define IPSO_ON_TIME 5852
static const lwm2m_resource_id_t resources[] =
{
RW(IPSO_ONOFF),
RW(IPSO_DIMMER),
RW(IPSO_ON_TIME)
};
/*---------------------------------------------------------------------------*/
lwm2m_status_t
ipso_control_set_on(ipso_control_t *control, uint8_t onoroff)
{
uint8_t v;
if(onoroff) {
v = control->value & 0x7f;
if(v == 0) {
v = 100;
}
} else {
v = 0;
}
return ipso_control_set_value(control, v);
}
/*---------------------------------------------------------------------------*/
lwm2m_status_t
ipso_control_set_value(ipso_control_t *control, uint8_t value)
{
lwm2m_status_t status = LWM2M_STATUS_OK;
int was_on;
was_on = ipso_control_is_on(control);
if(value == 0) {
if(was_on) {
/* Turn off */
status = control->set_value(0);
if(status == LWM2M_STATUS_OK) {
control->value &= 0x7f;
control->on_time +=
(coap_timer_uptime() - control->last_on_time) / 1000;
}
}
} else {
/* Restrict value between 0 - 100 */
if(value > 100) {
value = 100;
}
value |= 0x80;
if(value != control->value) {
status = control->set_value(value & 0x7f);
if(status == LWM2M_STATUS_OK) {
control->value = value;
if(! was_on) {
control->last_on_time = coap_timer_uptime();
}
}
}
}
return status;
}
/*---------------------------------------------------------------------------*/
static lwm2m_status_t
lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx)
{
ipso_control_t *control;
int32_t v;
/* Here we cast to our sensor-template struct */
control = (ipso_control_t *)object;
if(ctx->operation == LWM2M_OP_READ) {
switch(ctx->resource_id) {
case IPSO_ONOFF:
v = ipso_control_is_on(control) ? 1 : 0;
break;
case IPSO_DIMMER:
v = ipso_control_get_value(control);
break;
case IPSO_ON_TIME:
v = control->on_time;
if(ipso_control_is_on(control)) {
v += (coap_timer_uptime() - control->last_on_time) / 1000;
}
printf("ON-TIME: %"PRId32" (last on: %"PRIu32"\n", v, control->on_time);
break;
default:
return LWM2M_STATUS_ERROR;
}
lwm2m_object_write_int(ctx, v);
return LWM2M_STATUS_OK;
} else if(ctx->operation == LWM2M_OP_WRITE) {
switch(ctx->resource_id) {
case IPSO_ONOFF:
if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) {
return LWM2M_STATUS_ERROR;
}
return ipso_control_set_on(control, v > 0);
case IPSO_DIMMER:
if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) {
return LWM2M_STATUS_ERROR;
}
if(v < 0) {
v = 0;
} else if(v > 100) {
v = 100;
}
return ipso_control_set_value(control, v & 0xff);
case IPSO_ON_TIME:
if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) {
return LWM2M_STATUS_ERROR;
}
if(v == 0) {
control->on_time = 0;
control->last_on_time = coap_timer_uptime();
return LWM2M_STATUS_OK;
} else {
/* Only allowed to write 0 to reset ontime */
return LWM2M_STATUS_FORBIDDEN;
}
break;
default:
return LWM2M_STATUS_ERROR;
}
} else {
return LWM2M_STATUS_OPERATION_NOT_ALLOWED;
}
}
/*---------------------------------------------------------------------------*/
int
ipso_control_add(ipso_control_t *control)
{
control->reg_object.resource_ids = resources;
control->reg_object.resource_count =
sizeof(resources) / sizeof(lwm2m_resource_id_t);
control->reg_object.callback = lwm2m_callback;
return lwm2m_engine_add_object(&control->reg_object);
}
/*---------------------------------------------------------------------------*/
int
ipso_control_remove(ipso_control_t *control)
{
lwm2m_engine_remove_object(&control->reg_object);
return 1;
}
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2016, SICS Swedish ICT AB
* 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 copyright holder 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 COPYRIGHT HOLDER 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup ipso-objects
* @{
*
*/
/**
* \file
* Implementation of OMA LWM2M / IPSO sensor template.
* \author
* Joakim Eriksson <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
#ifndef IPSO_CONTROL_TEMPLATE_H_
#define IPSO_CONTROL_TEMPLATE_H_
#include "lwm2m-engine.h"
typedef struct ipso_control ipso_control_t;
#define IPSO_CONTROL_USE_DIMMER 0x01
typedef lwm2m_status_t (*ipso_control_set_value_t)(uint8_t v);
/* Values of the IPSO control object */
struct ipso_control {
lwm2m_object_instance_t reg_object;
uint8_t flags;
uint8_t value; /* used to emulate on/off and dim-value */
uint32_t on_time; /* on-time in seconds */
uint64_t last_on_time;
ipso_control_set_value_t set_value;
};
int ipso_control_add(ipso_control_t *control);
int ipso_control_remove(ipso_control_t *control);
static inline uint16_t
ipso_control_get_object_id(const ipso_control_t *control)
{
return control->reg_object.object_id;
}
static inline uint16_t
ipso_control_get_instance_id(const ipso_control_t *control)
{
return control->reg_object.instance_id;
}
static inline uint8_t
ipso_control_is_on(const ipso_control_t *control)
{
return (control->value & 0x80) != 0;
}
static inline uint8_t
ipso_control_get_value(const ipso_control_t *control)
{
return (control->value & 0x80) != 0 ? (control->value & 0x7f) : 0;
}
lwm2m_status_t ipso_control_set_on(ipso_control_t *control, uint8_t onoroff);
lwm2m_status_t ipso_control_set_value(ipso_control_t *control, uint8_t dimm_value);
#endif /* IPSO_CONTROL_TEMPLATE_H_ */
/** @} */

View File

@ -44,7 +44,6 @@
#include "lwm2m-object.h"
#include "lwm2m-engine.h"
#include "coap-engine.h"
#include "dev/leds.h"
#include <stdint.h>
@ -62,6 +61,7 @@
#define LEDS_CONTROL_NUMBER 1
#endif
#if 0
struct led_state {
unsigned long last_on_time;
uint32_t total_on_time;
@ -79,7 +79,7 @@ read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
if(idx >= LEDS_CONTROL_NUMBER) {
return 0;
}
return ctx->writer->write_boolean(ctx, outbuf, outsize,
return lwm2m_object_write_boolean(ctx, outbuf, outsize,
states[idx].is_on ? 1 : 0);
}
/*---------------------------------------------------------------------------*/
@ -95,7 +95,7 @@ write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize,
return 0;
}
len = ctx->reader->read_boolean(ctx, inbuf, insize, &value);
len = lwm2m_object_read_boolean(ctx, inbuf, insize, &value);
if(len > 0) {
if(value) {
if(!states[idx].is_on) {
@ -140,7 +140,7 @@ read_color(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
return 0;
}
value = get_color(states[idx].led_value);
return ctx->writer->write_string(ctx, outbuf, outsize,
return lwm2m_object_write_string(ctx, outbuf, outsize,
value, strlen(value));
}
/*---------------------------------------------------------------------------*/
@ -159,7 +159,7 @@ read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
states[idx].total_on_time += now - states[idx].last_on_time;
states[idx].last_on_time = now;
}
return ctx->writer->write_int(ctx, outbuf, outsize,
return lwm2m_object_write_int(ctx, outbuf, outsize,
(int32_t)states[idx].total_on_time);
}
/*---------------------------------------------------------------------------*/
@ -175,7 +175,7 @@ write_on_time(lwm2m_context_t *ctx,
return 0;
}
len = ctx->reader->read_int(ctx, inbuf, insize, &value);
len = lwm2m_object_read_int(ctx, inbuf, insize, &value);
if(len > 0 && value == 0) {
PRINTF("IPSO leds control - reset On Time\n");
states[idx].total_on_time = 0;
@ -233,4 +233,5 @@ ipso_leds_control_init(void)
LEDS_CONTROL_NUMBER);
}
/*---------------------------------------------------------------------------*/
#endif /* 0 */
/** @} */

View File

@ -46,6 +46,7 @@
#include "lwm2m-object.h"
#include "lwm2m-engine.h"
#if 0
#ifdef IPSO_LIGHT_CONTROL
extern const struct ipso_objects_actuator IPSO_LIGHT_CONTROL;
#endif /* IPSO_LIGHT_CONTROL */
@ -58,7 +59,7 @@ static uint8_t is_on = 0;
static int
read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
{
return ctx->writer->write_boolean(ctx, outbuf, outsize, is_on ? 1 : 0);
return lwm2m_object_write_boolean(ctx, outbuf, outsize, is_on ? 1 : 0);
}
/*---------------------------------------------------------------------------*/
static int
@ -68,7 +69,7 @@ write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize,
int value;
size_t len;
len = ctx->reader->read_boolean(ctx, inbuf, insize, &value);
len = lwm2m_object_read_boolean(ctx, inbuf, insize, &value);
if(len > 0) {
if(value) {
if(!is_on) {
@ -96,7 +97,7 @@ write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize,
static int
read_dim(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
{
return ctx->writer->write_int(ctx, outbuf, outsize, dim_level);
return lwm2m_object_write_int(ctx, outbuf, outsize, dim_level);
}
/*---------------------------------------------------------------------------*/
static int
@ -106,7 +107,7 @@ write_dim(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize,
int32_t value;
size_t len;
len = ctx->reader->read_int(ctx, inbuf, insize, &value);
len = lwm2m_object_read_int(ctx, inbuf, insize, &value);
if(len > 0) {
if(value < 0) {
value = 0;
@ -147,7 +148,7 @@ read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
total_on_time += now - last_on_time;
last_on_time = now;
}
return ctx->writer->write_int(ctx, outbuf, outsize, (int32_t)total_on_time);
return lwm2m_object_write_int(ctx, outbuf, outsize, (int32_t)total_on_time);
}
/*---------------------------------------------------------------------------*/
static int
@ -158,7 +159,7 @@ write_on_time(lwm2m_context_t *ctx,
int32_t value;
size_t len;
len = ctx->reader->read_int(ctx, inbuf, insize, &value);
len = lwm2m_object_read_int(ctx, inbuf, insize, &value);
if(len > 0 && value == 0) {
total_on_time = 0;
if(is_on) {
@ -199,4 +200,5 @@ ipso_light_control_init(void)
lwm2m_engine_register_object(&light_control);
}
/*---------------------------------------------------------------------------*/
#endif /* 0 */
/** @} */

View File

@ -56,11 +56,11 @@ ipso_objects_init(void)
ipso_button_init();
#endif
#ifdef IPSO_LIGHT_CONTROL
ipso_light_control_init();
#elif PLATFORM_HAS_LEDS
ipso_leds_control_init();
#endif
/* #ifdef IPSO_LIGHT_CONTROL */
/* ipso_light_control_init(); */
/* #elif PLATFORM_HAS_LEDS */
/* ipso_leds_control_init(); */
/* #endif */
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2016, SICS Swedish ICT AB
* 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 copyright holder 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 COPYRIGHT HOLDER 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup ipso-objects
* @{
*
*/
/**
* \file
* Implementation of OMA LWM2M / IPSO sensor template.
* \author
* Joakim Eriksson <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
#include "ipso-sensor-template.h"
#include "lwm2m-engine.h"
#include <string.h>
#include <stdio.h>
#define IPSO_SENSOR_VALUE 5700
#define IPSO_SENSOR_UNIT 5701
#define IPSO_SENSOR_MIN_VALUE 5601
#define IPSO_SENSOR_MAX_VALUE 5602
#define IPSO_SENSOR_MIN_RANGE 5603
#define IPSO_SENSOR_MAX_RANGE 5604
#define IPSO_SENSOR_RESET_MINMAX 5605
static const lwm2m_resource_id_t resources[] =
{
RO(IPSO_SENSOR_VALUE), RO(IPSO_SENSOR_UNIT),
RO(IPSO_SENSOR_MIN_VALUE), RO(IPSO_SENSOR_MAX_VALUE),
RO(IPSO_SENSOR_MIN_RANGE), RO(IPSO_SENSOR_MAX_RANGE),
EX(IPSO_SENSOR_RESET_MINMAX)
};
/*---------------------------------------------------------------------------*/
static void update_last_value(ipso_sensor_value_t *sval, int32_t value,
uint8_t notify);
/*---------------------------------------------------------------------------*/
static int init = 0;
static coap_timer_t nt;
/* Currently support max 4 periodic sensors */
#define MAX_PERIODIC 4
struct periodic_sensor {
ipso_sensor_value_t *value;
uint16_t ticks_left;
} periodics[MAX_PERIODIC];
static void
timer_callback(coap_timer_t *timer)
{
int i;
coap_timer_reset(timer, 1000);
for(i = 0; i < MAX_PERIODIC; i++) {
if(periodics[i].value != NULL) {
if(periodics[i].ticks_left > 0) {
periodics[i].ticks_left--;
} else {
int32_t value;
periodics[i].ticks_left = periodics[i].value->sensor->update_interval;
if(periodics[i].value->sensor->get_value_in_millis(periodics[i].value->sensor, &value) == LWM2M_STATUS_OK) {
update_last_value(periodics[i].value, value, 1);
}
}
}
}
}
static void
add_periodic(const ipso_sensor_t *sensor)
{
int i;
for(i = 0; i < MAX_PERIODIC; i++) {
if(periodics[i].value == NULL) {
periodics[i].value = sensor->sensor_value;
periodics[i].ticks_left = sensor->update_interval;
return;
}
}
}
/*---------------------------------------------------------------------------*/
static void
update_last_value(ipso_sensor_value_t *sval, int32_t value, uint8_t notify)
{
/* No notification if this a regular read that cause the update */
if(sval->last_value != value && notify) {
lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_VALUE);
}
sval->last_value = value;
if(sval->min_value > value) {
sval->min_value = value;
lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MIN_VALUE);
}
if(sval->max_value < value) {
sval->max_value = value;
lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MAX_VALUE);
}
}
/*---------------------------------------------------------------------------*/
static inline size_t
write_float32fix(lwm2m_context_t *ctx, int32_t value)
{
int64_t tmp = value;
tmp = (tmp * 1024) / 1000;
return lwm2m_object_write_float32fix(ctx, (int32_t)tmp, 10);
}
/*---------------------------------------------------------------------------*/
static lwm2m_status_t
lwm2m_callback(lwm2m_object_instance_t *object,
lwm2m_context_t *ctx)
{
/* Here we cast to our sensor-template struct */
const ipso_sensor_t *sensor;
ipso_sensor_value_t *value;
value = (ipso_sensor_value_t *) object;
sensor = value->sensor;
/* Do the stuff */
if(ctx->level == 1) {
/* Should not happen 3303 */
return LWM2M_STATUS_ERROR;
}
if(ctx->level == 2) {
/* This is a get whole object - or write whole object 3303/0 */
return LWM2M_STATUS_ERROR;
}
if(ctx->level == 3) {
/* This is a get request on 3303/0/3700 */
/* NOW we assume a get.... which might be wrong... */
if(ctx->operation == LWM2M_OP_READ) {
switch(ctx->resource_id) {
case IPSO_SENSOR_UNIT:
if(sensor->unit != NULL) {
lwm2m_object_write_string(ctx, sensor->unit, strlen(sensor->unit));
}
break;
case IPSO_SENSOR_MAX_RANGE:
write_float32fix(ctx, sensor->max_range);
break;
case IPSO_SENSOR_MIN_RANGE:
write_float32fix(ctx, sensor->min_range);
break;
case IPSO_SENSOR_MAX_VALUE:
write_float32fix(ctx, value->max_value);
break;
case IPSO_SENSOR_MIN_VALUE:
write_float32fix(ctx, value->min_value);
break;
case IPSO_SENSOR_VALUE:
if(sensor->get_value_in_millis != NULL) {
int32_t v;
if(sensor->get_value_in_millis(sensor, &v) == LWM2M_STATUS_OK) {
update_last_value(value, v, 0);
write_float32fix(ctx, value->last_value);
}
}
break;
default:
return LWM2M_STATUS_ERROR;
}
} else if(ctx->operation == LWM2M_OP_EXECUTE) {
if(ctx->resource_id == IPSO_SENSOR_RESET_MINMAX) {
value->min_value = value->last_value;
value->max_value = value->last_value;
}
}
}
return LWM2M_STATUS_OK;
}
/*---------------------------------------------------------------------------*/
int
ipso_sensor_add(const ipso_sensor_t *sensor)
{
if(sensor->update_interval > 0) {
if(init == 0) {
coap_timer_set_callback(&nt, timer_callback);
coap_timer_set(&nt, 1000);
init = 1;
}
add_periodic(sensor);
}
if(sensor->sensor_value == NULL) {
return 0;
}
sensor->sensor_value->reg_object.object_id = sensor->object_id;
sensor->sensor_value->sensor = sensor;
if(sensor->instance_id == 0) {
sensor->sensor_value->reg_object.instance_id = LWM2M_OBJECT_INSTANCE_NONE;
} else {
sensor->sensor_value->reg_object.instance_id = sensor->instance_id;
}
sensor->sensor_value->reg_object.callback = lwm2m_callback;
sensor->sensor_value->reg_object.resource_ids = resources;
sensor->sensor_value->reg_object.resource_count =
sizeof(resources) / sizeof(lwm2m_resource_id_t);
return lwm2m_engine_add_object(&sensor->sensor_value->reg_object);
}
/*---------------------------------------------------------------------------*/
int
ipso_sensor_remove(const ipso_sensor_t *sensor)
{
lwm2m_engine_remove_object(&sensor->sensor_value->reg_object);
return 1;
}
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2016, SICS Swedish ICT AB
* 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 copyright holder 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 COPYRIGHT HOLDER 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup ipso-objects
* @{
*
*/
/**
* \file
* Implementation of OMA LWM2M / IPSO sensor template.
* \author
* Joakim Eriksson <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
*/
#ifndef IPSO_SENSOR_TEMPLATE_H_
#define IPSO_SENSOR_TEMPLATE_H_
#include "lwm2m-engine.h"
typedef struct ipso_sensor ipso_sensor_t;
typedef lwm2m_status_t (*ipso_sensor_get_value_millis_t)(const ipso_sensor_t *sensor, int32_t *v);
/* Values of the IPSO object */
typedef struct ipso_sensor_value {
lwm2m_object_instance_t reg_object;
const ipso_sensor_t *sensor;
uint8_t flags;
int32_t last_value;
int32_t min_value;
int32_t max_value;
} ipso_sensor_value_t;
/* Meta data about an IPSO sensor object */
struct ipso_sensor {
/* LWM2M object type */
uint16_t object_id;
uint16_t instance_id;
/* When we read out the value we send in a context to write to */
ipso_sensor_get_value_millis_t get_value_in_millis;
int32_t min_range;
int32_t max_range;
char *unit;
/* update interval in seconds */
uint16_t update_interval;
ipso_sensor_value_t *sensor_value;
};
int ipso_sensor_add(const ipso_sensor_t *sensor);
int ipso_sensor_remove(const ipso_sensor_t *sensor);
#endif /* IPSO_SENSOR_TEMPLATE_H_ */

View File

@ -42,118 +42,60 @@
*/
#include <stdint.h>
#include "ipso-sensor-template.h"
#include "ipso-objects.h"
#include "lwm2m-object.h"
#include "lwm2m-engine.h"
#include "coap-engine.h"
#ifdef IPSO_TEMPERATURE
extern const struct ipso_objects_sensor IPSO_TEMPERATURE;
#endif /* IPSO_TEMPERATURE */
#ifndef IPSO_TEMPERATURE_MIN
#define IPSO_TEMPERATURE_MIN (-50 * LWM2M_FLOAT32_FRAC)
#define IPSO_TEMPERATURE_MIN -50000
#endif
#ifndef IPSO_TEMPERATURE_MAX
#define IPSO_TEMPERATURE_MAX (80 * LWM2M_FLOAT32_FRAC)
#define IPSO_TEMPERATURE_MAX 80000
#endif
static struct ctimer periodic_timer;
static int32_t min_temp;
static int32_t max_temp;
static int read_temp(int32_t *value);
lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, int32_t *value);
static ipso_sensor_value_t temp_value;
static const ipso_sensor_t temp_sensor = {
.object_id = 3303,
.sensor_value = &temp_value,
.max_range = IPSO_TEMPERATURE_MAX, /* milli celcius */
.min_range = IPSO_TEMPERATURE_MIN, /* milli celcius */
.get_value_in_millis = get_temp_value,
.unit = "Cel",
.update_interval = 10
};
/*---------------------------------------------------------------------------*/
static int
temp(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
{
int32_t value;
if(read_temp(&value)) {
return ctx->writer->write_float32fix(ctx, outbuf, outsize,
value, LWM2M_FLOAT32_BITS);
}
return 0;
}
/*---------------------------------------------------------------------------*/
LWM2M_RESOURCES(temperature_resources,
/* Temperature (Current) */
LWM2M_RESOURCE_CALLBACK(5700, { temp, NULL, NULL }),
/* Units */
LWM2M_RESOURCE_STRING(5701, "Cel"),
/* Min Range Value */
LWM2M_RESOURCE_FLOATFIX(5603, IPSO_TEMPERATURE_MIN),
/* Max Range Value */
LWM2M_RESOURCE_FLOATFIX(5604, IPSO_TEMPERATURE_MAX),
/* Min Measured Value */
LWM2M_RESOURCE_FLOATFIX_VAR(5601, &min_temp),
/* Max Measured Value */
LWM2M_RESOURCE_FLOATFIX_VAR(5602, &max_temp),
);
LWM2M_INSTANCES(temperature_instances,
LWM2M_INSTANCE(0, temperature_resources));
LWM2M_OBJECT(temperature, 3303, temperature_instances);
/*---------------------------------------------------------------------------*/
static int
read_temp(int32_t *value)
lwm2m_status_t
get_temp_value(const ipso_sensor_t *s, int32_t *value)
{
#ifdef IPSO_TEMPERATURE
int32_t temp;
if(IPSO_TEMPERATURE.read_value == NULL ||
IPSO_TEMPERATURE.read_value(&temp) != 0) {
return 0;
IPSO_TEMPERATURE.read_value(value) != 0) {
return LWM2M_STATUS_OK;
}
/* Convert milliCelsius to fix float */
*value = (temp * LWM2M_FLOAT32_FRAC) / 1000;
if(*value < min_temp) {
min_temp = *value;
lwm2m_object_notify_observers(&temperature, "/0/5601");
}
if(*value > max_temp) {
max_temp = *value;
lwm2m_object_notify_observers(&temperature, "/0/5602");
}
return 1;
#else /* IPSO_TEMPERATURE */
return 0;
#endif /* IPSO_TEMPERATURE */
}
/*---------------------------------------------------------------------------*/
static void
handle_periodic_timer(void *ptr)
{
static int32_t last_value = IPSO_TEMPERATURE_MIN;
int32_t v;
/* Only notify when the value has changed since last */
if(read_temp(&v) && v != last_value) {
last_value = v;
lwm2m_object_notify_observers(&temperature, "/0/5700");
}
ctimer_reset(&periodic_timer);
return LWM2M_STATUS_ERROR;
}
/*---------------------------------------------------------------------------*/
void
ipso_temperature_init(void)
{
int32_t v;
min_temp = IPSO_TEMPERATURE_MAX;
max_temp = IPSO_TEMPERATURE_MIN;
#ifdef IPSO_TEMPERATURE
if(IPSO_TEMPERATURE.init) {
IPSO_TEMPERATURE.init();
}
#endif /* IPSO_TEMPERATURE */
/* register this device and its handlers - the handlers automatically
sends in the object to handle */
lwm2m_engine_register_object(&temperature);
/* update temp and min/max + notify any listeners */
read_temp(&v);
ctimer_set(&periodic_timer, CLOCK_SECOND * 10, handle_periodic_timer, NULL);
ipso_sensor_add(&temp_sensor);
}
/*---------------------------------------------------------------------------*/
/** @} */