| /******************************************************************************* |
| * |
| * Copyright (c) 2013, 2014 Intel Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * and Eclipse Distribution License v1.0 which accompany this distribution. |
| * |
| * The Eclipse Public License is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * The Eclipse Distribution License is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * Contributors: |
| * David Navarro, Intel Corporation - initial API and implementation |
| * domedambrosio - Please refer to git log |
| * Fabien Fleutot - Please refer to git log |
| * Axel Lorente - Please refer to git log |
| * Achim Kraus, Bosch Software Innovations GmbH - Please refer to git log |
| * Pascal Rieux - Please refer to git log |
| * |
| *******************************************************************************/ |
| |
| /* |
| Copyright (c) 2013, 2014 Intel Corporation |
| |
| Redistribution and use in source and binary forms, with or without modification, |
| are permitted provided that the following conditions are met: |
| |
| * Redistributions of source code must retain the above copyright notice, |
| this list of conditions and the following disclaimer. |
| * 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. |
| * Neither the name of Intel Corporation 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 HOLDERS 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 OWNER 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. |
| |
| David Navarro <david.navarro@intel.com> |
| |
| */ |
| |
| /* |
| * Implements an object for testing purpose |
| * |
| * Multiple |
| * Object | ID | Instances | Mandatoty | |
| * Test | 1024 | Yes | No | |
| * |
| * Ressources: |
| * Supported Multiple |
| * Name | ID | Operations | Instances | Mandatory | Type | Range | Units | Description | |
| * test | 1 | R/W | No | Yes | Integer | 0-255 | | | |
| * exec | 2 | E | No | Yes | | | | | |
| * dec | 3 | R/W | No | Yes | Float | | | | |
| * |
| */ |
| |
| #include "liblwm2m.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <ctype.h> |
| |
| static void prv_output_buffer(uint8_t * buffer, |
| int length) |
| { |
| int i; |
| uint8_t array[16]; |
| |
| i = 0; |
| while (i < length) |
| { |
| int j; |
| fprintf(stderr, " "); |
| |
| memcpy(array, buffer+i, 16); |
| |
| for (j = 0 ; j < 16 && i+j < length; j++) |
| { |
| fprintf(stderr, "%02X ", array[j]); |
| } |
| while (j < 16) |
| { |
| fprintf(stderr, " "); |
| j++; |
| } |
| fprintf(stderr, " "); |
| for (j = 0 ; j < 16 && i+j < length; j++) |
| { |
| if (isprint(array[j])) |
| fprintf(stderr, "%c ", array[j]); |
| else |
| fprintf(stderr, ". "); |
| } |
| fprintf(stderr, "\n"); |
| |
| i += 16; |
| } |
| } |
| |
| /* |
| * Multiple instance objects can use userdata to store data that will be shared between the different instances. |
| * The lwm2m_object_t object structure - which represent every object of the liblwm2m as seen in the single instance |
| * object - contain a chained list called instanceList with the object specific structure prv_instance_t: |
| */ |
| typedef struct _prv_instance_ |
| { |
| /* |
| * The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest |
| * is the instance scope user data (uint8_t test in this case) |
| */ |
| struct _prv_instance_ * next; // matches lwm2m_list_t::next |
| uint16_t shortID; // matches lwm2m_list_t::id |
| uint8_t test; |
| double dec; |
| } prv_instance_t; |
| |
| static uint8_t prv_read(uint16_t instanceId, |
| int * numDataP, |
| lwm2m_tlv_t ** dataArrayP, |
| lwm2m_object_t * objectP) |
| { |
| prv_instance_t * targetP; |
| int i; |
| |
| targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); |
| if (NULL == targetP) return COAP_404_NOT_FOUND; |
| |
| if (*numDataP == 0) |
| { |
| *dataArrayP = lwm2m_tlv_new(2); |
| if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; |
| *numDataP = 2; |
| (*dataArrayP)[0].id = 1; |
| (*dataArrayP)[1].id = 3; |
| } |
| |
| for (i = 0 ; i < *numDataP ; i++) |
| { |
| switch ((*dataArrayP)[i].id) |
| { |
| case 1: |
| (*dataArrayP)[i].type = LWM2M_TYPE_RESOURCE; |
| lwm2m_tlv_encode_int(targetP->test, *dataArrayP + i); |
| break; |
| case 2: |
| return COAP_405_METHOD_NOT_ALLOWED; |
| case 3: |
| (*dataArrayP)[i].type = LWM2M_TYPE_RESOURCE; |
| lwm2m_tlv_encode_float(targetP->dec, *dataArrayP + i); |
| break; |
| default: |
| return COAP_404_NOT_FOUND; |
| } |
| if ((*dataArrayP)[i].length == 0) return COAP_500_INTERNAL_SERVER_ERROR; |
| } |
| |
| return COAP_205_CONTENT; |
| } |
| |
| static uint8_t prv_write(uint16_t instanceId, |
| int numData, |
| lwm2m_tlv_t * dataArray, |
| lwm2m_object_t * objectP) |
| { |
| prv_instance_t * targetP; |
| int i; |
| |
| targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); |
| if (NULL == targetP) return COAP_404_NOT_FOUND; |
| |
| for (i = 0 ; i < numData ; i++) |
| { |
| switch (dataArray[i].id) |
| { |
| case 1: |
| { |
| int64_t value; |
| |
| if (1 != lwm2m_tlv_decode_int(dataArray + i, &value) || value < 0 || value > 0xFF) |
| { |
| return COAP_400_BAD_REQUEST; |
| } |
| targetP->test = (uint8_t)value; |
| } |
| break; |
| case 2: |
| return COAP_405_METHOD_NOT_ALLOWED; |
| case 3: |
| if (1 != lwm2m_tlv_decode_float(dataArray + i, &(targetP->dec))) |
| { |
| return COAP_400_BAD_REQUEST; |
| } |
| break; |
| default: |
| return COAP_404_NOT_FOUND; |
| } |
| } |
| |
| return COAP_204_CHANGED; |
| } |
| |
| static uint8_t prv_delete(uint16_t id, |
| lwm2m_object_t * objectP) |
| { |
| prv_instance_t * targetP; |
| |
| objectP->instanceList = lwm2m_list_remove(objectP->instanceList, id, (lwm2m_list_t **)&targetP); |
| if (NULL == targetP) return COAP_404_NOT_FOUND; |
| |
| lwm2m_free(targetP); |
| |
| return COAP_202_DELETED; |
| } |
| |
| static uint8_t prv_create(uint16_t instanceId, |
| int numData, |
| lwm2m_tlv_t * dataArray, |
| lwm2m_object_t * objectP) |
| { |
| prv_instance_t * targetP; |
| uint8_t result; |
| |
| |
| targetP = (prv_instance_t *)lwm2m_malloc(sizeof(prv_instance_t)); |
| if (NULL == targetP) return COAP_500_INTERNAL_SERVER_ERROR; |
| memset(targetP, 0, sizeof(prv_instance_t)); |
| |
| targetP->shortID = instanceId; |
| objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, targetP); |
| |
| result = prv_write(instanceId, numData, dataArray, objectP); |
| |
| if (result != COAP_204_CHANGED) |
| { |
| (void)prv_delete(instanceId, objectP); |
| } |
| else |
| { |
| result = COAP_201_CREATED; |
| } |
| |
| return result; |
| } |
| |
| static uint8_t prv_exec(uint16_t instanceId, |
| uint16_t resourceId, |
| uint8_t * buffer, |
| int length, |
| lwm2m_object_t * objectP) |
| { |
| |
| if (NULL == lwm2m_list_find(objectP->instanceList, instanceId)) return COAP_404_NOT_FOUND; |
| |
| switch (resourceId) |
| { |
| case 1: |
| return COAP_405_METHOD_NOT_ALLOWED; |
| case 2: |
| fprintf(stdout, "\r\n-----------------\r\n" |
| "Execute on %hu/%d/%d\r\n" |
| " Parameter (%d bytes):\r\n", |
| objectP->objID, instanceId, resourceId, length); |
| prv_output_buffer((uint8_t*)buffer, length); |
| fprintf(stdout, "-----------------\r\n\r\n"); |
| return COAP_204_CHANGED; |
| case 3: |
| return COAP_405_METHOD_NOT_ALLOWED; |
| default: |
| return COAP_404_NOT_FOUND; |
| } |
| } |
| |
| static void prv_test_close(lwm2m_object_t * object) |
| { |
| LWM2M_LIST_FREE(object->instanceList); |
| if (object->userData != NULL) |
| { |
| lwm2m_free(object->userData); |
| object->userData = NULL; |
| } |
| } |
| |
| lwm2m_object_t * get_test_object(void) |
| { |
| lwm2m_object_t * testObj; |
| |
| testObj = (lwm2m_object_t *)lwm2m_malloc(sizeof(lwm2m_object_t)); |
| |
| if (NULL != testObj) |
| { |
| int i; |
| prv_instance_t * targetP; |
| |
| memset(testObj, 0, sizeof(lwm2m_object_t)); |
| |
| testObj->objID = 1024; |
| for (i=0 ; i < 3 ; i++) |
| { |
| targetP = (prv_instance_t *)lwm2m_malloc(sizeof(prv_instance_t)); |
| if (NULL == targetP) return NULL; |
| memset(targetP, 0, sizeof(prv_instance_t)); |
| targetP->shortID = 10 + i; |
| targetP->test = 20 + i; |
| targetP->dec = -30 + i + (double)i/100.0; |
| testObj->instanceList = LWM2M_LIST_ADD(testObj->instanceList, targetP); |
| } |
| /* |
| * From a single instance object, two more functions are available. |
| * - The first one (createFunc) create a new instance and filled it with the provided informations. If an ID is |
| * provided a check is done for verifying his disponibility, or a new one is generated. |
| * - The other one (deleteFunc) delete an instance by removing it from the instance list (and freeing the memory |
| * allocated to it) |
| */ |
| testObj->readFunc = prv_read; |
| testObj->writeFunc = prv_write; |
| testObj->executeFunc = prv_exec; |
| testObj->createFunc = prv_create; |
| testObj->deleteFunc = prv_delete; |
| testObj->closeFunc = prv_test_close; |
| } |
| |
| return testObj; |
| } |