1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/wakaama/contrib/objects/device.c
2024-11-12 08:47:13 +01:00

312 lines
9.8 KiB
C

/*
* Copyright (C) 2018 Beduino Master Projekt - University of Bremen
* 2021 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
* @ingroup lwm2m_objects_device
*
* @file
* @brief Device object implementation for LwM2M client using Wakaama
*
* @author Christian Manal <manal@uni-bremen.de>
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
* @}
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kernel_defines.h"
#include "liblwm2m.h"
#include "objects/device.h"
#include "lwm2m_client_config.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/* Set to true if reboot requested. */
static bool reboot;
/**
* @brief 'Execute' callback for the Device object.
*
* @param[in] context LWM2M Context
* @param[in] instance_id Instance ID. Should be 0 as a single instance exists.
* @param[in] resource_id ID of the resource to execute.
* @param[in] buffer Information needed for the execution.
* @param[in] length Length of @p buffer.
* @param[in] object Device object pointer
*
* @return COAP_204_CHANGED on success
* @return COAP_404_NOT_FOUND when wrong instance specified
* @return COAP_400_BAD_REQUEST when wrong information has been sent
* @return COAP_405_METHOD_NOT_ALLOWED when trying to execute a resource that is not supported
*/
static uint8_t _execute_cb(lwm2m_context_t * context, uint16_t instance_id, uint16_t resource_id,
uint8_t * buffer, int length, lwm2m_object_t * object);
/**
* @brief 'Read' callback for the Device object.
*
* @param[in] context LWM2M Context
* @param[in] instance_id Instance ID. Should be 0 as a single instance exists.
* @param[in, out] num_data Number of resources requested. 0 means all.
* @param[in, out] data_array Initialized data array to output the values,
* when @p num_data != 0. Uninitialized otherwise.
* @param[in] object Device object pointer
*
* @return COAP_205_CONTENT on success
* @return COAP_404_NOT_FOUND when resource can't be found
* @return COAP_500_INTERNAL_SERVER_ERROR otherwise
*/
static uint8_t _read_cb(lwm2m_context_t * context, uint16_t instance_id, int * num_data,
lwm2m_data_t ** data_array, lwm2m_object_t * object);
/**
* @brief 'Discover' callback for the Device object.
*
* @param[in] context LWM2M Context
* @param[in] instance_id Instance ID. Should be 0 as a single instance exists.
* @param[in, out] num_data Number of resources requested. 0 means all.
* @param[in, out] data_array Initialized data array to determine if the resource exists,
* when @p num_data != 0. Uninitialized otherwise.
* @param[in] object Device object pointer
*
* @return COAP_205_CONTENT on success
* @return COAP_404_NOT_FOUND when a resource is not supported
* @return COAP_500_INTERNAL_SERVER_ERROR otherwise
*/
static uint8_t _discover_cb(lwm2m_context_t * context, uint16_t instance_id, int * num_data,
lwm2m_data_t ** data_array, lwm2m_object_t * object);
typedef struct {
lwm2m_list_t list; /**< Linked list handle */
} lwm2m_obj_device_inst_t;
static const lwm2m_obj_device_inst_t _instance;
/**
* @brief Implementation of the object interface for the Device Object.
*/
static lwm2m_object_t _device_object = {
.next = NULL,
.objID = LWM2M_DEVICE_OBJECT_ID,
.instanceList = (lwm2m_list_t *)&_instance,
.readFunc = _read_cb,
.executeFunc = _execute_cb,
.discoverFunc = _discover_cb,
.writeFunc = NULL,
.deleteFunc = NULL,
.createFunc = NULL,
.userData = NULL
};
static uint8_t _discover_cb(lwm2m_context_t * context, uint16_t instance_id, int * num_data,
lwm2m_data_t ** data_array, lwm2m_object_t * object)
{
uint8_t result;
int i;
(void)context;
(void)object;
if (instance_id != 0) {
return COAP_404_NOT_FOUND;
}
result = COAP_205_CONTENT;
if (*num_data == 0) {
/* This list must contain all available resources */
uint16_t res[] = {
LWM2M_RES_MANUFACTURER, LWM2M_RES_MODEL_NO, LWM2M_RES_SERIAL,
LWM2M_RES_FW_VER, LWM2M_RES_REBOOT, LWM2M_RES_ERROR_CODE,
/* LWM2M_RES_ERROR_CODE_RESET, TODO */
LWM2M_RES_BINDINGS, LWM2M_RES_TYPE, LWM2M_RES_HW_VERSION,
LWM2M_RES_SW_VERSION,
};
int len = ARRAY_SIZE(res);
*data_array = lwm2m_data_new(len);
*num_data = len;
if (*data_array == NULL) {
DEBUG("[lwm2m:device:discover] could not allocate data array\n");
return COAP_500_INTERNAL_SERVER_ERROR;
}
for (i = 0; i < len; i++) {
(*data_array)[i].id = res[i];
}
}
else {
/* Check if each given resource is present */
for (i = 0; i < *num_data && result == COAP_205_CONTENT; i++) {
switch ((*data_array)[i].id) {
case LWM2M_RES_MANUFACTURER:
case LWM2M_RES_MODEL_NO:
case LWM2M_RES_SERIAL:
case LWM2M_RES_FW_VER:
case LWM2M_RES_REBOOT:
case LWM2M_RES_ERROR_CODE:
/* case LWM2M_RES_ERROR_CODE_RESET: TODO */
case LWM2M_RES_BINDINGS:
case LWM2M_RES_TYPE:
case LWM2M_RES_HW_VERSION:
case LWM2M_RES_SW_VERSION:
break;
default:
result = COAP_404_NOT_FOUND;
}
}
}
return result;
}
static uint8_t _read_cb(lwm2m_context_t * context, uint16_t instance_id, int * num_data,
lwm2m_data_t ** data_array, lwm2m_object_t * object)
{
(void)context;
(void)object;
int i;
DEBUG("[lwm2m:device:read]\n");
/* Single instance object */
if (instance_id != 0) {
return COAP_404_NOT_FOUND;
}
/* Full object requested */
if (*num_data == 0) {
DEBUG("[lwm2m:device:read] all resources are requested\n");
/* This list must contain all readable resources */
uint16_t resList[] = {
LWM2M_RES_MANUFACTURER, LWM2M_RES_MODEL_NO, LWM2M_RES_SERIAL,
LWM2M_RES_FW_VER, LWM2M_RES_HW_VERSION, LWM2M_RES_SW_VERSION,
LWM2M_RES_BINDINGS, LWM2M_RES_TYPE, LWM2M_RES_ERROR_CODE,
};
int cnt = ARRAY_SIZE(resList);
*data_array = lwm2m_data_new(cnt);
*num_data = cnt;
if (*data_array == NULL) {
DEBUG("[lwm2m:device:read] could not allocate data array\n");
return COAP_500_INTERNAL_SERVER_ERROR;
}
for (i = 0; i < cnt; i++) {
(*data_array)[i].id = resList[i];
}
}
for (i = 0; i < *num_data; i++) {
lwm2m_data_t *data = &(*data_array)[i];
DEBUG("[lwm2m:device:read] reading resource %d\n", data->id);
switch (data->id) {
/* Exec resources, can't be read */
case LWM2M_RES_REBOOT:
case LWM2M_RES_FRESET:
case LWM2M_RES_ERROR_CODE_RESET:
return COAP_405_METHOD_NOT_ALLOWED;
break;
case LWM2M_RES_ERROR_CODE:
/* TODO: Here some error reporting should be implemented. For now returning no error */
lwm2m_data_encode_int(LWM2M_DEVICE_ERR_NO_ERR, data);
break;
case LWM2M_RES_MANUFACTURER:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_MANUFACTURER, data);
break;
case LWM2M_RES_MODEL_NO:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_MODEL, data);
break;
case LWM2M_RES_SERIAL:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_SERIAL, data);
break;
case LWM2M_RES_FW_VER:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_FW_VERSION, data);
break;
case LWM2M_RES_BINDINGS:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_BINDINGS, data);
break;
case LWM2M_RES_TYPE:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_TYPE, data);
break;
case LWM2M_RES_HW_VERSION:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_HW_VERSION, data);
break;
case LWM2M_RES_SW_VERSION:
lwm2m_data_encode_string(CONFIG_LWM2M_DEVICE_SW_VERSION, data);
break;
case LWM2M_DEVICE_RESOURCES:
lwm2m_data_encode_string(NULL, data);
break;
/* The rest are not defined resources */
default:
return COAP_404_NOT_FOUND;
}
}
return COAP_205_CONTENT;
}
static uint8_t _execute_cb(lwm2m_context_t * context, uint16_t instance_id, uint16_t resource_id,
uint8_t * buffer, int length, lwm2m_object_t * object)
{
(void)context;
(void)buffer;
(void)object;
/* single instance object */
if (instance_id != 0) {
return COAP_404_NOT_FOUND;
}
if (length != 0) {
return COAP_400_BAD_REQUEST;
}
/* for now only rebooting is available */
if (resource_id == LWM2M_RES_REBOOT) {
reboot = true;
return COAP_204_CHANGED;
}
return COAP_405_METHOD_NOT_ALLOWED;
}
/*
* Call this from the main loop to check whether a reboot was requested.
*/
bool lwm2m_device_reboot_requested(void)
{
return reboot;
}
lwm2m_object_t *lwm2m_object_device_init(lwm2m_client_data_t *client_data)
{
assert(client_data);
_device_object.userData = client_data;
return &_device_object;
}