Contiki-NG
lwm2m-object.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015-2018, Yanzi Networks AB.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/**
32 * \addtogroup apps
33 * @{
34 */
35
36/**
37 * \defgroup lwm2m An implementation of LWM2M
38 * @{
39 *
40 * This is an implementation of OMA Lightweight M2M (LWM2M).
41 */
42
43/**
44 * \file
45 * Header file for the LWM2M object API
46 * \author
47 * Joakim Eriksson <joakime@sics.se>
48 * Niclas Finne <nfi@sics.se>
49 */
50
51#ifndef LWM2M_OBJECT_H_
52#define LWM2M_OBJECT_H_
53
54#include "coap.h"
55#include "coap-observe.h"
56
57/* Operation permissions on the resources - read/write/execute */
58#define LWM2M_RESOURCE_READ 0x10000
59#define LWM2M_RESOURCE_WRITE 0x20000
60#define LWM2M_RESOURCE_EXECUTE 0x40000
61#define LWM2M_RESOURCE_OP_MASK 0x70000
62
63/* The resource id type of lwm2m objects - 16 bits for the ID - the rest
64 is flags */
65typedef uint32_t lwm2m_resource_id_t;
66
67/* Defines for the resource definition array */
68#define RO(x) (x | LWM2M_RESOURCE_READ)
69#define WO(x) (x | LWM2M_RESOURCE_WRITE)
70#define RW(x) (x | LWM2M_RESOURCE_READ | LWM2M_RESOURCE_WRITE)
71#define EX(x) (x | LWM2M_RESOURCE_EXECUTE)
72
73#define LWM2M_OBJECT_SECURITY_ID 0
74#define LWM2M_OBJECT_SERVER_ID 1
75#define LWM2M_OBJECT_ACCESS_CONTROL_ID 2
76#define LWM2M_OBJECT_DEVICE_ID 3
77#define LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID 4
78#define LWM2M_OBJECT_FIRMWARE_ID 5
79#define LWM2M_OBJECT_LOCATION_ID 6
80#define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID 7
81
82typedef enum {
83 LWM2M_OP_NONE,
84 LWM2M_OP_READ,
85 LWM2M_OP_DISCOVER,
86 LWM2M_OP_WRITE,
87 LWM2M_OP_WRITE_ATTR,
88 LWM2M_OP_EXECUTE,
89 LWM2M_OP_CREATE,
90 LWM2M_OP_DELETE
91} lwm2m_operation_t;
92
93typedef enum {
94 LWM2M_STATUS_OK,
95
96 /* Internal server error */
97 LWM2M_STATUS_ERROR,
98 /* Error from writer */
99 LWM2M_STATUS_WRITE_ERROR,
100 /* Error from reader */
101 LWM2M_STATUS_READ_ERROR,
102
103 LWM2M_STATUS_BAD_REQUEST,
104 LWM2M_STATUS_UNAUTHORIZED,
105 LWM2M_STATUS_FORBIDDEN,
106 LWM2M_STATUS_NOT_FOUND,
107 LWM2M_STATUS_OPERATION_NOT_ALLOWED,
108 LWM2M_STATUS_NOT_ACCEPTABLE,
109 LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT,
110
111 LWM2M_STATUS_NOT_IMPLEMENTED,
112 LWM2M_STATUS_SERVICE_UNAVAILABLE,
113} lwm2m_status_t;
114
115/* remember that we have already output a value - can be between two block's */
116#define WRITER_OUTPUT_VALUE 1
117#define WRITER_RESOURCE_INSTANCE 2
118#define WRITER_HAS_MORE 4
119
120typedef struct lwm2m_reader lwm2m_reader_t;
121typedef struct lwm2m_writer lwm2m_writer_t;
122
123typedef struct lwm2m_object_instance lwm2m_object_instance_t;
124
125typedef struct {
126 uint16_t len; /* used for current length of the data in the buffer */
127 uint16_t pos; /* position in the buffer - typically write position or similar */
128 uint16_t size;
129 uint8_t *buffer;
130} lwm2m_buffer_t;
131
132/* Data model for OMA LWM2M objects */
133typedef struct lwm2m_context {
134 uint16_t object_id;
135 uint16_t object_instance_id;
136 uint16_t resource_id;
137 uint16_t resource_instance_id;
138
139 uint8_t resource_index;
140 uint8_t resource_instance_index; /* for use when stepping to next sub-resource if having multiple */
141 uint8_t level; /* 0/1/2/3 = 3 = resource */
142 lwm2m_operation_t operation;
143
144 coap_message_t *request;
145 coap_message_t *response;
146
147 unsigned int content_type;
148 lwm2m_buffer_t *outbuf;
149 lwm2m_buffer_t *inbuf;
150
151 uint8_t out_mark_pos_oi; /* mark pos for last object instance */
152 uint8_t out_mark_pos_ri; /* mark pos for last resource instance */
153
154 uint32_t offset; /* If we do blockwise - this needs to change */
155
156 /* Info on last_instance read/write */
157 uint16_t last_instance;
158 uint16_t last_value_len;
159
160 uint8_t writer_flags; /* flags for reader/writer */
161 const lwm2m_reader_t *reader;
162 const lwm2m_writer_t *writer;
163} lwm2m_context_t;
164
165/* LWM2M format writer for the various formats supported */
166struct lwm2m_writer {
167 size_t (* init_write)(lwm2m_context_t *ctx);
168 size_t (* end_write)(lwm2m_context_t *ctx);
169 /* For sub-resources */
170 size_t (* enter_resource_instance)(lwm2m_context_t *ctx);
171 size_t (* exit_resource_instance)(lwm2m_context_t *ctx);
172 size_t (* write_int)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value);
173 size_t (* write_string)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen);
174 size_t (* write_float32fix)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits);
175 size_t (* write_boolean)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value);
176 size_t (* write_opaque_header)(lwm2m_context_t *ctx, size_t total_size);
177};
178
179struct lwm2m_reader {
180 size_t (* read_int)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value);
181 size_t (* read_string)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen);
182 size_t (* read_float32fix)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits);
183 size_t (* read_boolean)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value);
184};
185
186typedef lwm2m_status_t
187(* lwm2m_write_opaque_callback)(lwm2m_object_instance_t *object,
188 lwm2m_context_t *ctx, int num_to_write);
189
190void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb);
191
192static inline void
193lwm2m_notify_observers(char *path)
194{
195 coap_notify_observers_sub(NULL, path);
196}
197
198static inline size_t
199lwm2m_object_read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value)
200{
201 return ctx->reader->read_int(ctx, inbuf, len, value);
202}
203
204static inline size_t
205lwm2m_object_read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen)
206{
207 return ctx->reader->read_string(ctx, inbuf, len, value, strlen);
208}
209
210static inline size_t
211lwm2m_object_read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits)
212{
213 return ctx->reader->read_float32fix(ctx, inbuf, len, value, bits);
214}
215
216static inline size_t
217lwm2m_object_read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value)
218{
219 return ctx->reader->read_boolean(ctx, inbuf, len, value);
220}
221
222static inline size_t
223lwm2m_object_write_int(lwm2m_context_t *ctx, int32_t value)
224{
225 size_t s;
226 s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
227 ctx->outbuf->size - ctx->outbuf->len, value);
228 ctx->outbuf->len += s;
229 return s;
230}
231
232static inline size_t
233lwm2m_object_write_string(lwm2m_context_t *ctx, const char *value, size_t strlen)
234{
235 size_t s;
236 s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
237 ctx->outbuf->size - ctx->outbuf->len, value, strlen);
238 ctx->outbuf->len += s;
239 return s;
240}
241
242static inline size_t
243lwm2m_object_write_float32fix(lwm2m_context_t *ctx, int32_t value, int bits)
244{
245 size_t s;
246 s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
247 ctx->outbuf->size - ctx->outbuf->len, value, bits);
248 ctx->outbuf->len += s;
249 return s;
250}
251
252static inline size_t
253lwm2m_object_write_boolean(lwm2m_context_t *ctx, int value)
254{
255 size_t s;
256 s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
257 ctx->outbuf->size - ctx->outbuf->len, value);
258 ctx->outbuf->len += s;
259 return s;
260}
261
262static inline int
263lwm2m_object_write_opaque_stream(lwm2m_context_t *ctx, int size, lwm2m_write_opaque_callback cb)
264{
265 /* 1. - create a header of either OPAQUE (nothing) or TLV if the format is TLV */
266 size_t s;
267 if(ctx->writer->write_opaque_header != NULL) {
268 s = ctx->writer->write_opaque_header(ctx, size);
269 ctx->outbuf->len += s;
270 } else {
271 return 0;
272 }
273 /* 2. - set the callback so that future data will be grabbed from the callback */
274 lwm2m_engine_set_opaque_callback(ctx, cb);
275 return 1;
276}
277
278/* Resource instance functions (_ri)*/
279
280static inline size_t
281lwm2m_object_write_enter_ri(lwm2m_context_t *ctx)
282{
283 if(ctx->writer->enter_resource_instance != NULL) {
284 size_t s;
285 s = ctx->writer->enter_resource_instance(ctx);
286 ctx->outbuf->len += s;
287 return s;
288 }
289 return 0;
290}
291
292static inline size_t
293lwm2m_object_write_exit_ri(lwm2m_context_t *ctx)
294{
295 if(ctx->writer->exit_resource_instance != NULL) {
296 size_t s;
297 s = ctx->writer->exit_resource_instance(ctx);
298 ctx->outbuf->len += s;
299 return s;
300 }
301 return 0;
302}
303
304static inline size_t
305lwm2m_object_write_int_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value)
306{
307 size_t s;
308 ctx->resource_instance_id = id;
309 s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
310 ctx->outbuf->size - ctx->outbuf->len, value);
311 ctx->outbuf->len += s;
312 return s;
313}
314
315static inline size_t
316lwm2m_object_write_string_ri(lwm2m_context_t *ctx, uint16_t id, const char *value, size_t strlen)
317{
318 size_t s;
319 ctx->resource_instance_id = id;
320 s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
321 ctx->outbuf->size - ctx->outbuf->len, value, strlen);
322 ctx->outbuf->len += s;
323 return s;
324}
325
326static inline size_t
327lwm2m_object_write_float32fix_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value, int bits)
328{
329 size_t s;
330 ctx->resource_instance_id = id;
331 s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
332 ctx->outbuf->size - ctx->outbuf->len, value, bits);
333 ctx->outbuf->len += s;
334 return s;
335}
336
337static inline size_t
338lwm2m_object_write_boolean_ri(lwm2m_context_t *ctx, uint16_t id, int value)
339{
340 size_t s;
341 ctx->resource_instance_id = id;
342 s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
343 ctx->outbuf->size - ctx->outbuf->len, value);
344 ctx->outbuf->len += s;
345 return s;
346}
347
348static inline int
349lwm2m_object_is_final_incoming(lwm2m_context_t *ctx)
350{
351 uint8_t more;
352 if(coap_get_header_block1(ctx->request, NULL, &more, NULL, NULL)) {
353 return !more;
354 }
355 /* If we do not know this is final... it might not be... */
356 return 0;
357}
358
359#include "lwm2m-engine.h"
360
361#endif /* LWM2M_OBJECT_H_ */
362/**
363 * @}
364 * @}
365 */
CoAP module for observing resources (draft-ietf-core-observe-11).
An implementation of the Constrained Application Protocol (RFC 7252).
Header file for the Contiki OMA LWM2M engine.