/* * Copyright (c) 2015, Yanzi Networks 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 apps * @{ */ /** * \defgroup oma-lwm2m An implementation of OMA LWM2M * @{ * * This application is an implementation of OMA Lightweight M2M. */ /** * \file * Header file for the Contiki OMA LWM2M object API * \author * Joakim Eriksson * Niclas Finne */ #ifndef LWM2M_OBJECT_H_ #define LWM2M_OBJECT_H_ #include "rest-engine.h" #include "er-coap-observe.h" #define LWM2M_OBJECT_SECURITY_ID 0 #define LWM2M_OBJECT_SERVER_ID 1 #define LWM2M_OBJECT_ACCESS_CONTROL_ID 2 #define LWM2M_OBJECT_DEVICE_ID 3 #define LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID 4 #define LWM2M_OBJECT_FIRMWARE_ID 5 #define LWM2M_OBJECT_LOCATION_ID 6 #define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID 7 #define LWM2M_SECURITY_SERVER_URI 0 #define LWM2M_SECURITY_BOOTSTRAP_SERVER 1 #define LWM2M_SECURITY_MODE 2 #define LWM2M_SECURITY_CLIENT_PKI 3 #define LWM2M_SECURITY_SERVER_PKI 4 #define LWM2M_SECURITY_KEY 5 #define LWM2M_SECURITY_SHORT_SERVER_ID 10 /* Pre-shared key mode */ #define LWM2M_SECURITY_MODE_PSK 0 /* Raw Public Key mode */ #define LWM2M_SECURITY_MODE_RPK 1 /* Certificate mode */ #define LWM2M_SECURITY_MODE_CERTIFICATE 2 /* NoSec mode */ #define LWM2M_SECURITY_MODE_NOSEC 3 #define LWM2M_OBJECT_STR_HELPER(x) (uint8_t *) #x #define LWM2M_OBJECT_STR(x) LWM2M_OBJECT_STR_HELPER(x) #define LWM2M_OBJECT_PATH_STR_HELPER(x) #x #define LWM2M_OBJECT_PATH_STR(x) LWM2M_OBJECT_PATH_STR_HELPER(x) struct lwm2m_reader; struct lwm2m_writer; /* Data model for OMA LWM2M objects */ typedef struct lwm2m_context { uint16_t object_id; uint16_t object_instance_id; uint16_t resource_id; uint8_t object_instance_index; uint8_t resource_index; /* TODO - add uint16_t resource_instance_id */ const struct lwm2m_reader *reader; const struct lwm2m_writer *writer; } lwm2m_context_t; /* LWM2M format writer for the various formats supported */ typedef struct lwm2m_writer { size_t (* write_int)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value); size_t (* write_string)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen); size_t (* write_float32fix)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits); size_t (* write_boolean)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value); } lwm2m_writer_t; typedef struct lwm2m_reader { size_t (* read_int)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value); size_t (* read_string)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen); size_t (* read_float32fix)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits); size_t (* read_boolean)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value); } lwm2m_reader_t; typedef struct lwm2m_value_callback { int (* read)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen); int (* write)(lwm2m_context_t *ctx, const uint8_t *buffer, size_t len, uint8_t *outbuf, size_t outlen); int (* exec)(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, uint8_t *outbuf, size_t outlen); } lwm2m_value_callback_t; #define LWM2M_RESOURCE_TYPE_STR_VALUE 1 #define LWM2M_RESOURCE_TYPE_STR_VARIABLE 2 #define LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY 3 #define LWM2M_RESOURCE_TYPE_INT_VALUE 4 #define LWM2M_RESOURCE_TYPE_INT_VARIABLE 5 #define LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY 6 #define LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE 7 #define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE 8 #define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY 9 #define LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE 10 #define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE 11 #define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY 12 #define LWM2M_RESOURCE_TYPE_CALLBACK 16 #define LWM2M_RESOURCE_TYPE_INSTANCES 17 typedef struct lwm2m_resource { uint16_t id; uint8_t type; /* indicate value type and multi-instance resource */ union { struct { uint16_t len; const uint8_t *value; } string; struct { uint16_t size; uint16_t *len; uint8_t **var; } stringvar; struct { uint16_t count; uint16_t size; /* string var array with counting entries */ uint16_t *len; uint8_t *var; } stringvararr; struct { int32_t value; } integer; struct { int32_t *var; } integervar; struct { /* used for multiple instances (dynamic) NOTE: this is an index into the instance so having two instances means that there is need for allocation of two ints here */ uint16_t count; int32_t *var; /* used as an array? */ } integervararr; struct { int32_t value; } floatfix; struct { int32_t *var; } floatfixvar; struct { uint16_t count; int32_t *var; } floatfixvararr; struct { int value; } boolean; struct { int *var; } booleanvar; struct { uint16_t count; int *var; } booleanvararr; lwm2m_value_callback_t callback; /* lwm2m_resource *resources[]; TO BE ADDED LATER*/ } value; } lwm2m_resource_t; #define LWM2M_INSTANCE_FLAG_USED 1 typedef struct lwm2m_instance { uint16_t id; uint16_t count; uint16_t flag; const lwm2m_resource_t *resources; } lwm2m_instance_t; typedef struct lwm2m_object { uint16_t id; uint16_t count; const char *path; resource_t *coap_resource; lwm2m_instance_t *instances; } lwm2m_object_t; #define LWM2M_RESOURCES(name, ...) \ static const lwm2m_resource_t name[] = { __VA_ARGS__ } #define LWM2M_RESOURCE_STRING(id, s) \ { id, LWM2M_RESOURCE_TYPE_STR_VALUE, .value.string.len = sizeof(s) - 1, .value.string.value = (uint8_t *) s } #define LWM2M_RESOURCE_STRING_VAR(id, s, l, v) \ { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE, .value.stringvar.size = (s), .value.stringvar.len = (l), .value.stringvar.var = (v) } #define LWM2M_RESOURCE_STRING_VAR_ARR(id, c, s, l, v) \ { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY, .value.stringvararr.count = c, .value.stringvararr.size = s, .value.stringvararr.len = l, .value.stringvararr.var = (uint8_t *) v } #define LWM2M_RESOURCE_INTEGER(id, v) \ { id, LWM2M_RESOURCE_TYPE_INT_VALUE, .value.integer.value = (v) } #define LWM2M_RESOURCE_INTEGER_VAR(id, v) \ { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE, .value.integervar.var = (v) } #define LWM2M_RESOURCE_INTEGER_VAR_ARR(id, c, v) \ { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY, .value.integervararr.count = (c), .value.integervararr.var = (v) } #define LWM2M_RESOURCE_FLOATFIX(id, v) \ { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE, .value.floatfix.value = (v) } #define LWM2M_RESOURCE_FLOATFIX_VAR(id, v) \ { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE, .value.floatfixvar.var = (v) } #define LWM2M_RESOURCE_FLOATFIX_VAR_ARR(id, c, v) \ { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY, .value.floatfixvararr.count = (c), .value.floatfixvararr.var = (v) } #define LWM2M_RESOURCE_BOOLEAN(id, v) \ { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE, .value.boolean.value = (v) } #define LWM2M_RESOURCE_BOOLEAN_VAR(id, v) \ { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE, .value.booleanvar.var = (v) } #define LWM2M_RESOURCE_BOOLEAN_VAR_ARR(id, c, v) \ { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY, .value.booleanvararr.count = (c), .value.booleanvararr.var = (v) } #define LWM2M_RESOURCE_CALLBACK(id, ...) \ { id, LWM2M_RESOURCE_TYPE_CALLBACK, .value.callback = __VA_ARGS__ } #define LWM2M_INSTANCE(id, resources) \ { id, sizeof(resources)/sizeof(lwm2m_resource_t), LWM2M_INSTANCE_FLAG_USED, resources } #define LWM2M_INSTANCE_UNUSED(id, resources) \ { id, sizeof(resources)/sizeof(lwm2m_resource_t), 0, resources } #define LWM2M_INSTANCES(name, ...) \ static lwm2m_instance_t name[] = { __VA_ARGS__ } #define LWM2M_OBJECT(name, id, instances) \ static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ static resource_t rest_rsc_##name = { NULL, NULL, HAS_SUB_RESOURCES | IS_OBSERVABLE, NULL, lwm2m_get_h_##name, lwm2m_post_h_##name, lwm2m_put_h_##name, lwm2m_delete_h_##name, { NULL } }; \ static const lwm2m_object_t name = { id, sizeof(instances)/sizeof(lwm2m_instance_t), LWM2M_OBJECT_PATH_STR(id), &rest_rsc_##name, instances}; \ static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ lwm2m_engine_delete_handler(&name, request, response, buffer, preferred_size, offset); } /* how do we register attributes in the above resource here ??? */ int lwm2m_object_is_resource_string(const lwm2m_resource_t *resource); int lwm2m_object_is_resource_int(const lwm2m_resource_t *resource); int lwm2m_object_is_resource_floatfix(const lwm2m_resource_t *resource); int lwm2m_object_is_resource_boolean(const lwm2m_resource_t *resource); static inline int lwm2m_object_is_resource_callback(const lwm2m_resource_t *resource) { return resource != NULL && resource->type == LWM2M_RESOURCE_TYPE_CALLBACK; } const uint8_t * lwm2m_object_get_resource_string(const lwm2m_resource_t *resource, const lwm2m_context_t *context); uint16_t lwm2m_object_get_resource_strlen(const lwm2m_resource_t *resource, const lwm2m_context_t *context); int lwm2m_object_set_resource_string(const lwm2m_resource_t *resource, const lwm2m_context_t *context, uint16_t len, const uint8_t *string); int lwm2m_object_get_resource_int(const lwm2m_resource_t *resource, const lwm2m_context_t *context, int32_t *value); int lwm2m_object_set_resource_int(const lwm2m_resource_t *resource, const lwm2m_context_t *context, int32_t value); int lwm2m_object_get_resource_floatfix(const lwm2m_resource_t *resource, const lwm2m_context_t *context, int32_t *value); int lwm2m_object_set_resource_floatfix(const lwm2m_resource_t *resource, const lwm2m_context_t *context, int32_t value); int lwm2m_object_get_resource_boolean(const lwm2m_resource_t *resource, const lwm2m_context_t *context, int *value); int lwm2m_object_set_resource_boolean(const lwm2m_resource_t *resource, const lwm2m_context_t *context, int value); static inline resource_t * lwm2m_object_get_coap_resource(const lwm2m_object_t *object) { return (resource_t *)object->coap_resource; } static inline void lwm2m_object_notify_observers(const lwm2m_object_t *object, char *path) { coap_notify_observers_sub(lwm2m_object_get_coap_resource(object), path); } #include "lwm2m-engine.h" #endif /* LWM2M_OBJECT_H_ */ /** * @} * @} */