308 lines
9.2 KiB
C
308 lines
9.2 KiB
C
/*******************************************************************************
|
|
*
|
|
* Copyright (c) 2013, 2014, 2015 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
|
|
* 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>
|
|
|
|
*/
|
|
|
|
/*
|
|
* This object is single instance only, and is mandatory to all LWM2M device as it describe the object such as its
|
|
* manufacturer, model, etc...
|
|
*
|
|
* Here we implement only some of the optional resources.
|
|
*
|
|
*/
|
|
|
|
#include "liblwm2m.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
|
|
#define PRV_MANUFACTURER "Open Mobile Alliance"
|
|
#define PRV_MODEL_NUMBER "Lightweight M2M Client"
|
|
#define PRV_BINDING_MODE "U"
|
|
|
|
// Resource Id's:
|
|
#define RES_O_MANUFACTURER 0
|
|
#define RES_O_MODEL_NUMBER 1
|
|
#define RES_O_SERIAL_NUMBER 2
|
|
#define RES_O_FIRMWARE_VERSION 3
|
|
#define RES_M_REBOOT 4
|
|
#define RES_O_FACTORY_RESET 5
|
|
#define RES_O_AVL_POWER_SOURCES 6
|
|
#define RES_O_POWER_SOURCE_VOLTAGE 7
|
|
#define RES_O_POWER_SOURCE_CURRENT 8
|
|
#define RES_O_BATTERY_LEVEL 9
|
|
#define RES_O_MEMORY_FREE 10
|
|
#define RES_M_ERROR_CODE 11
|
|
#define RES_O_RESET_ERROR_CODE 12
|
|
#define RES_O_CURRENT_TIME 13
|
|
#define RES_O_UTC_OFFSET 14
|
|
#define RES_O_TIMEZONE 15
|
|
#define RES_M_BINDING_MODES 16
|
|
#define RES_O_DEVICE_TYPE 17
|
|
#define RES_O_HARDWARE_VERSION 18
|
|
#define RES_O_SOFTWARE_VERSION 19
|
|
#define RES_O_BATTERY_STATUS 20
|
|
#define RES_O_MEMORY_TOTAL 21
|
|
|
|
|
|
static uint8_t prv_set_value(lwm2m_data_t * dataP)
|
|
{
|
|
// a simple switch structure is used to respond at the specified resource asked
|
|
switch (dataP->id)
|
|
{
|
|
case RES_O_MANUFACTURER:
|
|
lwm2m_data_encode_string(PRV_MANUFACTURER, dataP);
|
|
return COAP_205_CONTENT;
|
|
|
|
case RES_O_MODEL_NUMBER:
|
|
lwm2m_data_encode_string(PRV_MODEL_NUMBER, dataP);
|
|
return COAP_205_CONTENT;
|
|
|
|
case RES_M_REBOOT:
|
|
return COAP_405_METHOD_NOT_ALLOWED;
|
|
|
|
case RES_M_BINDING_MODES:
|
|
lwm2m_data_encode_string(PRV_BINDING_MODE, dataP);
|
|
return COAP_205_CONTENT;
|
|
|
|
|
|
default:
|
|
return COAP_404_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
static uint8_t prv_device_read(uint16_t instanceId,
|
|
int * numDataP,
|
|
lwm2m_data_t ** dataArrayP,
|
|
lwm2m_object_t * objectP)
|
|
{
|
|
uint8_t result;
|
|
int i;
|
|
|
|
// this is a single instance object
|
|
if (instanceId != 0)
|
|
{
|
|
return COAP_404_NOT_FOUND;
|
|
}
|
|
|
|
// is the server asking for the full object ?
|
|
if (*numDataP == 0)
|
|
{
|
|
uint16_t resList[] = {
|
|
RES_O_MANUFACTURER,
|
|
RES_O_MODEL_NUMBER,
|
|
RES_M_BINDING_MODES
|
|
};
|
|
int nbRes = sizeof(resList)/sizeof(uint16_t);
|
|
|
|
*dataArrayP = lwm2m_data_new(nbRes);
|
|
if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
|
|
*numDataP = nbRes;
|
|
for (i = 0 ; i < nbRes ; i++)
|
|
{
|
|
(*dataArrayP)[i].id = resList[i];
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
do
|
|
{
|
|
result = prv_set_value((*dataArrayP) + i);
|
|
i++;
|
|
} while (i < *numDataP && result == COAP_205_CONTENT);
|
|
|
|
return result;
|
|
}
|
|
|
|
static uint8_t prv_device_discover(uint16_t instanceId,
|
|
int * numDataP,
|
|
lwm2m_data_t ** dataArrayP,
|
|
lwm2m_object_t * objectP)
|
|
{
|
|
uint8_t result;
|
|
int i;
|
|
|
|
// this is a single instance object
|
|
if (instanceId != 0)
|
|
{
|
|
return COAP_404_NOT_FOUND;
|
|
}
|
|
|
|
result = COAP_205_CONTENT;
|
|
|
|
// is the server asking for the full object ?
|
|
if (*numDataP == 0)
|
|
{
|
|
uint16_t resList[] = {
|
|
RES_O_MANUFACTURER,
|
|
RES_O_MODEL_NUMBER,
|
|
RES_M_BINDING_MODES,
|
|
RES_M_REBOOT
|
|
};
|
|
int nbRes = sizeof(resList)/sizeof(uint16_t);
|
|
|
|
*dataArrayP = lwm2m_data_new(nbRes);
|
|
if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
|
|
*numDataP = nbRes;
|
|
for (i = 0 ; i < nbRes ; i++)
|
|
{
|
|
(*dataArrayP)[i].id = resList[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < *numDataP && result == COAP_205_CONTENT; i++)
|
|
{
|
|
switch ((*dataArrayP)[i].id)
|
|
{
|
|
case RES_O_MANUFACTURER:
|
|
case RES_O_MODEL_NUMBER:
|
|
case RES_M_BINDING_MODES:
|
|
case RES_M_REBOOT:
|
|
break;
|
|
default:
|
|
result = COAP_404_NOT_FOUND;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static uint8_t prv_device_execute(uint16_t instanceId,
|
|
uint16_t resourceId,
|
|
uint8_t * buffer,
|
|
int length,
|
|
lwm2m_object_t * objectP)
|
|
{
|
|
// this is a single instance object
|
|
if (instanceId != 0)
|
|
{
|
|
return COAP_404_NOT_FOUND;
|
|
}
|
|
|
|
if (length != 0) return COAP_400_BAD_REQUEST;
|
|
|
|
if (resourceId == RES_M_REBOOT)
|
|
{
|
|
// fprintf(stdout, "\n\t REBOOT\r\n\n");
|
|
return COAP_204_CHANGED;
|
|
}
|
|
|
|
return COAP_405_METHOD_NOT_ALLOWED;
|
|
}
|
|
|
|
lwm2m_object_t * get_object_device()
|
|
{
|
|
/*
|
|
* The get_object_device function create the object itself and return a pointer to the structure that represent it.
|
|
*/
|
|
lwm2m_object_t * deviceObj;
|
|
|
|
deviceObj = (lwm2m_object_t *)lwm2m_malloc(sizeof(lwm2m_object_t));
|
|
|
|
if (NULL != deviceObj)
|
|
{
|
|
memset(deviceObj, 0, sizeof(lwm2m_object_t));
|
|
|
|
/*
|
|
* It assigns his unique ID
|
|
* The 3 is the standard ID for the mandatory object "Object device".
|
|
*/
|
|
deviceObj->objID = LWM2M_DEVICE_OBJECT_ID;
|
|
|
|
/*
|
|
* and its unique instance
|
|
*
|
|
*/
|
|
deviceObj->instanceList = (lwm2m_list_t *)lwm2m_malloc(sizeof(lwm2m_list_t));
|
|
if (NULL != deviceObj->instanceList)
|
|
{
|
|
memset(deviceObj->instanceList, 0, sizeof(lwm2m_list_t));
|
|
}
|
|
else
|
|
{
|
|
lwm2m_free(deviceObj);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* And the private function that will access the object.
|
|
* Those function will be called when a read/write/execute query is made by the server. In fact the library don't need to
|
|
* know the resources of the object, only the server does.
|
|
*/
|
|
deviceObj->readFunc = prv_device_read;
|
|
deviceObj->executeFunc = prv_device_execute;
|
|
deviceObj->discoverFunc = prv_device_discover;
|
|
|
|
}
|
|
|
|
return deviceObj;
|
|
}
|
|
|
|
void free_object_device(lwm2m_object_t * objectP)
|
|
{
|
|
if (NULL != objectP->userData)
|
|
{
|
|
lwm2m_free(objectP->userData);
|
|
objectP->userData = NULL;
|
|
}
|
|
if (NULL != objectP->instanceList)
|
|
{
|
|
lwm2m_free(objectP->instanceList);
|
|
objectP->instanceList = NULL;
|
|
}
|
|
|
|
lwm2m_free(objectP);
|
|
}
|