360 lines
14 KiB
C
360 lines
14 KiB
C
/*
|
|
* 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 <joakime@sics.se>
|
|
* Niclas Finne <nfi@sics.se>
|
|
*/
|
|
|
|
#ifndef LWM2M_OBJECT_H_
|
|
#define LWM2M_OBJECT_H_
|
|
|
|
#include "net/app-layer/coap/rest-engine.h"
|
|
#include "net/app-layer/coap/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_ */
|
|
/**
|
|
* @}
|
|
* @}
|
|
*/
|