blob: d145698983f98262dbed7e1d5f487da6bfbcf14c [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*******************************************************************************
2 *
3 * Copyright (c) 2013, 2014 Intel Corporation and others.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * and Eclipse Distribution License v1.0 which accompany this distribution.
7 *
8 * The Eclipse Public License is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 * The Eclipse Distribution License is available at
11 * http://www.eclipse.org/org/documents/edl-v10.php.
12 *
13 * Contributors:
14 * David Navarro, Intel Corporation - initial API and implementation
15 * domedambrosio - Please refer to git log
16 * Fabien Fleutot - Please refer to git log
17 * Axel Lorente - Please refer to git log
18 * Achim Kraus, Bosch Software Innovations GmbH - Please refer to git log
19 * Pascal Rieux - Please refer to git log
20 *
21 *******************************************************************************/
22
23/*
24 Copyright (c) 2013, 2014 Intel Corporation
25
26 Redistribution and use in source and binary forms, with or without modification,
27 are permitted provided that the following conditions are met:
28
29 * Redistributions of source code must retain the above copyright notice,
30 this list of conditions and the following disclaimer.
31 * Redistributions in binary form must reproduce the above copyright notice,
32 this list of conditions and the following disclaimer in the documentation
33 and/or other materials provided with the distribution.
34 * Neither the name of Intel Corporation nor the names of its contributors
35 may be used to endorse or promote products derived from this software
36 without specific prior written permission.
37
38 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
39 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
43 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
47 THE POSSIBILITY OF SUCH DAMAGE.
48
49 David Navarro <david.navarro@intel.com>
50
51*/
52
53/*
54 * Implements an object for testing purpose
55 *
56 * Multiple
57 * Object | ID | Instances | Mandatoty |
58 * Test | 1024 | Yes | No |
59 *
60 * Ressources:
61 * Supported Multiple
62 * Name | ID | Operations | Instances | Mandatory | Type | Range | Units | Description |
63 * test | 1 | R/W | No | Yes | Integer | 0-255 | | |
64 * exec | 2 | E | No | Yes | | | | |
65 * dec | 3 | R/W | No | Yes | Float | | | |
66 *
67 */
68
69#include "liblwm2m.h"
70
71#include <stdio.h>
72#include <stdlib.h>
73#include <string.h>
74#include <ctype.h>
75
76static void prv_output_buffer(uint8_t * buffer,
77 int length)
78{
79 int i;
80 uint8_t array[16];
81
82 i = 0;
83 while (i < length)
84 {
85 int j;
86 fprintf(stderr, " ");
87
88 memcpy(array, buffer+i, 16);
89
90 for (j = 0 ; j < 16 && i+j < length; j++)
91 {
92 fprintf(stderr, "%02X ", array[j]);
93 }
94 while (j < 16)
95 {
96 fprintf(stderr, " ");
97 j++;
98 }
99 fprintf(stderr, " ");
100 for (j = 0 ; j < 16 && i+j < length; j++)
101 {
102 if (isprint(array[j]))
103 fprintf(stderr, "%c ", array[j]);
104 else
105 fprintf(stderr, ". ");
106 }
107 fprintf(stderr, "\n");
108
109 i += 16;
110 }
111}
112
113/*
114 * Multiple instance objects can use userdata to store data that will be shared between the different instances.
115 * The lwm2m_object_t object structure - which represent every object of the liblwm2m as seen in the single instance
116 * object - contain a chained list called instanceList with the object specific structure prv_instance_t:
117 */
118typedef struct _prv_instance_
119{
120 /*
121 * The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest
122 * is the instance scope user data (uint8_t test in this case)
123 */
124 struct _prv_instance_ * next; // matches lwm2m_list_t::next
125 uint16_t shortID; // matches lwm2m_list_t::id
126 uint8_t test;
127 double dec;
128} prv_instance_t;
129
130static uint8_t prv_read(uint16_t instanceId,
131 int * numDataP,
132 lwm2m_tlv_t ** dataArrayP,
133 lwm2m_object_t * objectP)
134{
135 prv_instance_t * targetP;
136 int i;
137
138 targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId);
139 if (NULL == targetP) return COAP_404_NOT_FOUND;
140
141 if (*numDataP == 0)
142 {
143 *dataArrayP = lwm2m_tlv_new(2);
144 if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
145 *numDataP = 2;
146 (*dataArrayP)[0].id = 1;
147 (*dataArrayP)[1].id = 3;
148 }
149
150 for (i = 0 ; i < *numDataP ; i++)
151 {
152 switch ((*dataArrayP)[i].id)
153 {
154 case 1:
155 (*dataArrayP)[i].type = LWM2M_TYPE_RESOURCE;
156 lwm2m_tlv_encode_int(targetP->test, *dataArrayP + i);
157 break;
158 case 2:
159 return COAP_405_METHOD_NOT_ALLOWED;
160 case 3:
161 (*dataArrayP)[i].type = LWM2M_TYPE_RESOURCE;
162 lwm2m_tlv_encode_float(targetP->dec, *dataArrayP + i);
163 break;
164 default:
165 return COAP_404_NOT_FOUND;
166 }
167 if ((*dataArrayP)[i].length == 0) return COAP_500_INTERNAL_SERVER_ERROR;
168 }
169
170 return COAP_205_CONTENT;
171}
172
173static uint8_t prv_write(uint16_t instanceId,
174 int numData,
175 lwm2m_tlv_t * dataArray,
176 lwm2m_object_t * objectP)
177{
178 prv_instance_t * targetP;
179 int i;
180
181 targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId);
182 if (NULL == targetP) return COAP_404_NOT_FOUND;
183
184 for (i = 0 ; i < numData ; i++)
185 {
186 switch (dataArray[i].id)
187 {
188 case 1:
189 {
190 int64_t value;
191
192 if (1 != lwm2m_tlv_decode_int(dataArray + i, &value) || value < 0 || value > 0xFF)
193 {
194 return COAP_400_BAD_REQUEST;
195 }
196 targetP->test = (uint8_t)value;
197 }
198 break;
199 case 2:
200 return COAP_405_METHOD_NOT_ALLOWED;
201 case 3:
202 if (1 != lwm2m_tlv_decode_float(dataArray + i, &(targetP->dec)))
203 {
204 return COAP_400_BAD_REQUEST;
205 }
206 break;
207 default:
208 return COAP_404_NOT_FOUND;
209 }
210 }
211
212 return COAP_204_CHANGED;
213}
214
215static uint8_t prv_delete(uint16_t id,
216 lwm2m_object_t * objectP)
217{
218 prv_instance_t * targetP;
219
220 objectP->instanceList = lwm2m_list_remove(objectP->instanceList, id, (lwm2m_list_t **)&targetP);
221 if (NULL == targetP) return COAP_404_NOT_FOUND;
222
223 lwm2m_free(targetP);
224
225 return COAP_202_DELETED;
226}
227
228static uint8_t prv_create(uint16_t instanceId,
229 int numData,
230 lwm2m_tlv_t * dataArray,
231 lwm2m_object_t * objectP)
232{
233 prv_instance_t * targetP;
234 uint8_t result;
235
236
237 targetP = (prv_instance_t *)lwm2m_malloc(sizeof(prv_instance_t));
238 if (NULL == targetP) return COAP_500_INTERNAL_SERVER_ERROR;
239 memset(targetP, 0, sizeof(prv_instance_t));
240
241 targetP->shortID = instanceId;
242 objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, targetP);
243
244 result = prv_write(instanceId, numData, dataArray, objectP);
245
246 if (result != COAP_204_CHANGED)
247 {
248 (void)prv_delete(instanceId, objectP);
249 }
250 else
251 {
252 result = COAP_201_CREATED;
253 }
254
255 return result;
256}
257
258static uint8_t prv_exec(uint16_t instanceId,
259 uint16_t resourceId,
260 uint8_t * buffer,
261 int length,
262 lwm2m_object_t * objectP)
263{
264
265 if (NULL == lwm2m_list_find(objectP->instanceList, instanceId)) return COAP_404_NOT_FOUND;
266
267 switch (resourceId)
268 {
269 case 1:
270 return COAP_405_METHOD_NOT_ALLOWED;
271 case 2:
272 fprintf(stdout, "\r\n-----------------\r\n"
273 "Execute on %hu/%d/%d\r\n"
274 " Parameter (%d bytes):\r\n",
275 objectP->objID, instanceId, resourceId, length);
276 prv_output_buffer((uint8_t*)buffer, length);
277 fprintf(stdout, "-----------------\r\n\r\n");
278 return COAP_204_CHANGED;
279 case 3:
280 return COAP_405_METHOD_NOT_ALLOWED;
281 default:
282 return COAP_404_NOT_FOUND;
283 }
284}
285
286static void prv_test_close(lwm2m_object_t * object)
287{
288 LWM2M_LIST_FREE(object->instanceList);
289 if (object->userData != NULL)
290 {
291 lwm2m_free(object->userData);
292 object->userData = NULL;
293 }
294}
295
296lwm2m_object_t * get_test_object(void)
297{
298 lwm2m_object_t * testObj;
299
300 testObj = (lwm2m_object_t *)lwm2m_malloc(sizeof(lwm2m_object_t));
301
302 if (NULL != testObj)
303 {
304 int i;
305 prv_instance_t * targetP;
306
307 memset(testObj, 0, sizeof(lwm2m_object_t));
308
309 testObj->objID = 1024;
310 for (i=0 ; i < 3 ; i++)
311 {
312 targetP = (prv_instance_t *)lwm2m_malloc(sizeof(prv_instance_t));
313 if (NULL == targetP) return NULL;
314 memset(targetP, 0, sizeof(prv_instance_t));
315 targetP->shortID = 10 + i;
316 targetP->test = 20 + i;
317 targetP->dec = -30 + i + (double)i/100.0;
318 testObj->instanceList = LWM2M_LIST_ADD(testObj->instanceList, targetP);
319 }
320 /*
321 * From a single instance object, two more functions are available.
322 * - The first one (createFunc) create a new instance and filled it with the provided informations. If an ID is
323 * provided a check is done for verifying his disponibility, or a new one is generated.
324 * - The other one (deleteFunc) delete an instance by removing it from the instance list (and freeing the memory
325 * allocated to it)
326 */
327 testObj->readFunc = prv_read;
328 testObj->writeFunc = prv_write;
329 testObj->executeFunc = prv_exec;
330 testObj->createFunc = prv_create;
331 testObj->deleteFunc = prv_delete;
332 testObj->closeFunc = prv_test_close;
333 }
334
335 return testObj;
336}