From 572dddcef38ef6dd5bfe54c4aaebe6453c5ea438 Mon Sep 17 00:00:00 2001 From: Leandro Lanzieri Date: Sun, 4 Feb 2024 15:19:26 +0100 Subject: [PATCH] pkg/wakaama/objects: add IPSO sensor base --- pkg/wakaama/Kconfig | 4 +- pkg/wakaama/contrib/objects/Kconfig | 5 + pkg/wakaama/contrib/objects/Kconfig.ipso | 8 + .../contrib/objects/ipso_sensor_base.c | 417 ++++++++++++++++++ .../include/objects/ipso_sensor_base.h | 202 +++++++++ 5 files changed, 634 insertions(+), 2 deletions(-) create mode 100644 pkg/wakaama/contrib/objects/Kconfig.ipso create mode 100644 pkg/wakaama/contrib/objects/ipso_sensor_base.c create mode 100644 pkg/wakaama/include/objects/ipso_sensor_base.h diff --git a/pkg/wakaama/Kconfig b/pkg/wakaama/Kconfig index 4d265b095f..609f0f8e31 100644 --- a/pkg/wakaama/Kconfig +++ b/pkg/wakaama/Kconfig @@ -19,6 +19,8 @@ config LWM2M_DTLS_PORT endmenu # Remote server +rsource "contrib/objects/Kconfig" + config LWM2M_DEVICE_TTL int "Lifetime of the device" default 300 @@ -60,6 +62,4 @@ config LWM2M_BOOTSTRAP help Say y to support using a bootstrap server to get server information. -rsource "contrib/objects/Kconfig" - endmenu # Wakaama LwM2M diff --git a/pkg/wakaama/contrib/objects/Kconfig b/pkg/wakaama/contrib/objects/Kconfig index 1b460cde2e..1d8a433128 100644 --- a/pkg/wakaama/contrib/objects/Kconfig +++ b/pkg/wakaama/contrib/objects/Kconfig @@ -5,6 +5,11 @@ # directory for more details. # +menu "LwM2M objects" + rsource "Kconfig.device" rsource "Kconfig.security" +rsource "Kconfig.ipso" rsource "Kconfig.light_control" + +endmenu diff --git a/pkg/wakaama/contrib/objects/Kconfig.ipso b/pkg/wakaama/contrib/objects/Kconfig.ipso new file mode 100644 index 0000000000..086d53258b --- /dev/null +++ b/pkg/wakaama/contrib/objects/Kconfig.ipso @@ -0,0 +1,8 @@ +menu "IPSO sensor objects" + depends on USEMODULE_WAKAAMA_OBJECTS_IPSO_SENSOR_BASE + +config LWM2M_IPSO_SENSOR_BASE_UNITS_MAX_SIZE + int "Maximum size of strings representing units" + default 4 + +endmenu # "IPSO objects" diff --git a/pkg/wakaama/contrib/objects/ipso_sensor_base.c b/pkg/wakaama/contrib/objects/ipso_sensor_base.c new file mode 100644 index 0000000000..a2e498c913 --- /dev/null +++ b/pkg/wakaama/contrib/objects/ipso_sensor_base.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2024 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_ipso_sensor_base + * + * @file + * @brief Implementation of IPSO sensor base functionalities + * + * @author Leandro Lanzieri + * @} + */ + +#include "liblwm2m.h" +#include "lwm2m_client.h" +#include "objects/ipso_sensor_base.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +#define _USED_INSTANCES(obj) (obj->object.instanceList) +#define _FREE_INSTANCES(obj) (obj->free_instances) + +/** + * @brief 'Read' callback for the LwM2M Illuminance Sensor object implementation. + * + * @param[in] instance_id ID of the instance to read resource from. + * @param[in] num_data Number of elements in @p data_array. + * @param[in, out] data_array IDs of resources to read. Array of data structures to place values. + * @param[in] object Illuminance Sensor object handle + * + * @return COAP_205_CONTENT on success + * @return COAP_404_NOT_FOUND if the instance was not found + * @return COAP_500_INTERNAL_SERVER_ERROR otherwise + */ +static uint8_t _read_cb(uint16_t instance_id, int *num_data, lwm2m_data_t **data_array, + lwm2m_object_t *object); + +/** + * @brief 'Execute' callback for the LwM2M Illuminance Sensor object implementation. + * + * @param[in] instance_id ID of the instance to execute resource from. + * @param[in] resource_id ID of the resource to execute. + * @param[in] buffer Pointer to the buffer containing the payload. + * @param[in] length Length of the payload. + * @param[in] object Illuminance Sensor object handle + * + * @return COAP_204_CHANGED on success + * @return COAP_404_NOT_FOUND if the instance was not found + * @return COAP_405_METHOD_NOT_ALLOWED if the resource is not executable + */ +static uint8_t _exec_cb(uint16_t instance_id, uint16_t resource_id, uint8_t *buffer, int length, + lwm2m_object_t *object); + +/** + * @brief Gets the current value of a given @p instance. + * + * @param[in, out] data Initialized data structure. + * @param[in] instance Pointer to the instance to get the value from. + * + * @return COAP_205_CONTENT on success + * @return COAP_404_NOT_FOUND if the value is not found + */ +static uint8_t _get_value(lwm2m_data_t *data, lwm2m_obj_ipso_sensor_base_inst_t *instance); + +/** + * @brief Mark a resource as changed. + * + * @param[in] object Object to mark the resource from. + * @param[in] instance_id ID of the instance to mark the resource from. + * @param[in] resource_id ID of the resource to mark. + */ +static void _mark_resource_as_changed(const lwm2m_object_t *object, uint16_t instance_id, + uint16_t resource_id); + +/** + * @brief Add an instance to the free instance list. + * + * @param[out] object IPSO sensor base object + * @param[in] instance Instance to add to the free list + */ +static void _put_instance_in_free_list(lwm2m_obj_ipso_sensor_base_t *object, + lwm2m_obj_ipso_sensor_base_inst_t *instance); + +/** + * @brief Get a free instance from the list. + * + * @param[in] object IPSO sensor base object + * + * @return Instance if available, NULL otherwise + */ +static lwm2m_obj_ipso_sensor_base_inst_t *_get_instance_from_free_list( + lwm2m_obj_ipso_sensor_base_t *object); + +static void _put_instance_in_free_list(lwm2m_obj_ipso_sensor_base_t *object, + lwm2m_obj_ipso_sensor_base_inst_t *instance) +{ + assert(object); + assert(instance); + + instance->list.id = UINT16_MAX; + instance->list.next = NULL; + + _FREE_INSTANCES(object) = (lwm2m_obj_ipso_sensor_base_inst_t *)LWM2M_LIST_ADD( + _FREE_INSTANCES(object), instance + ); +} + +static lwm2m_obj_ipso_sensor_base_inst_t *_get_instance_from_free_list( + lwm2m_obj_ipso_sensor_base_t *object) +{ + assert(object); + lwm2m_obj_ipso_sensor_base_inst_t *instance = NULL; + + /* try to allocate an instance, by popping a free node from the list */ + _FREE_INSTANCES(object) = (lwm2m_obj_ipso_sensor_base_inst_t *)lwm2m_list_remove( + (lwm2m_list_t *)_FREE_INSTANCES(object), UINT16_MAX, (lwm2m_list_t **)&instance + ); + + return instance; +} + +int lwm2m_object_ipso_sensor_base_init_derived(lwm2m_client_data_t *client_data, + lwm2m_obj_ipso_sensor_base_t *object, + uint16_t object_id, + lwm2m_obj_ipso_sensor_base_inst_t *instances, + size_t instance_count) +{ + assert(object); + assert(instances); + memset(object, 0, sizeof(lwm2m_obj_ipso_sensor_base_t)); + + /* initialize the wakaama LwM2M object */ + object->object.objID = object_id; + object->object.readFunc = _read_cb; + object->object.executeFunc = _exec_cb; + object->object.userData = client_data; + + /* initialize the instances and add them to the free instance list */ + for (unsigned i = 0; i < instance_count; i++) { + _put_instance_in_free_list(object, &instances[i]); + } + + return 0; +} + +static uint8_t _get_value(lwm2m_data_t *data, lwm2m_obj_ipso_sensor_base_inst_t *instance) +{ + assert(data); + assert(instance); + int res; + + switch (data->id) { + case LWM2M_IPSO_BASE_SENSOR_VALUE_ID: + if (instance->read_cb) { + res = instance->read_cb(instance->read_cb_arg, &instance->sensor_value); + if (res) { + DEBUG("[lwm2m IPSO sensor base:read]: read callback failed\n"); + return COAP_500_INTERNAL_SERVER_ERROR; + } + } + lwm2m_data_encode_float(instance->sensor_value, data); + break; + + case LWM2M_IPSO_BASE_SENSOR_MIN_MEASURED_VALUE_ID: + lwm2m_data_encode_float(instance->min_sensor_value, data); + break; + + case LWM2M_IPSO_BASE_SENSOR_MAX_MEASURED_VALUE_ID: + lwm2m_data_encode_float(instance->max_sensor_value, data); + break; + + case LWM2M_IPSO_BASE_SENSOR_MIN_RANGE_VALUE_ID: + lwm2m_data_encode_float(instance->min_range_value, data); + break; + + case LWM2M_IPSO_BASE_SENSOR_MAX_RANGE_VALUE_ID: + lwm2m_data_encode_float(instance->max_range_value, data); + break; + + case LWM2M_IPSO_BASE_SENSOR_UNITS_ID: + lwm2m_data_encode_string(instance->units, data); + break; + + default: + return COAP_404_NOT_FOUND; + } + return COAP_205_CONTENT; +} + +static uint8_t _read_cb(uint16_t instance_id, int *num_data, lwm2m_data_t **data_array, + lwm2m_object_t *object) +{ + lwm2m_obj_ipso_sensor_base_inst_t *instance; + uint8_t result; + int i = 0; + + /* try to get the requested instance from the object list */ + instance = (lwm2m_obj_ipso_sensor_base_inst_t *)lwm2m_list_find(object->instanceList, + instance_id); + if (!instance) { + DEBUG("[lwm2m IPSO sensor base:read]: can't find instance %d\n", instance_id); + result = COAP_404_NOT_FOUND; + goto out; + } + + /* if the number of resources is not specified, we need to read all resources */ + if (!*num_data) { + DEBUG("[lwm2m IPSO sensor base:read]: reading all resources\n"); + + uint16_t res_list[] = { + LWM2M_IPSO_BASE_SENSOR_VALUE_ID, + LWM2M_IPSO_BASE_SENSOR_MIN_MEASURED_VALUE_ID, + LWM2M_IPSO_BASE_SENSOR_MAX_MEASURED_VALUE_ID, + LWM2M_IPSO_BASE_SENSOR_MIN_RANGE_VALUE_ID, + LWM2M_IPSO_BASE_SENSOR_MAX_RANGE_VALUE_ID, + LWM2M_IPSO_BASE_SENSOR_UNITS_ID + }; + + /* allocate structures to return resources */ + int res_num = ARRAY_SIZE(res_list); + *data_array = lwm2m_data_new(res_num); + + if (NULL == *data_array) { + result = COAP_500_INTERNAL_SERVER_ERROR; + goto out; + } + + /* return the number of resources being read */ + *num_data = res_num; + + /* set the IDs of the resources in the data structures */ + for (i = 0; i < res_num; i++) { + (*data_array)[i].id = res_list[i]; + } + } + + /* now get the values */ + i = 0; + do { + DEBUG("[lwm2m IPSO sensor base:read]: reading resource %d\n", (*data_array)[i].id); + result = _get_value(&(*data_array)[i], instance); + i++; + } while (i < *num_data && COAP_205_CONTENT == result); + +out: + return result; +} + +static uint8_t _exec_cb(uint16_t instance_id, uint16_t resource_id, uint8_t *buffer, int length, + lwm2m_object_t *object) +{ + (void)buffer; + (void)length; + + lwm2m_obj_ipso_sensor_base_inst_t *instance; + uint8_t result; + + /* try to get the requested instance from the object list */ + instance = (lwm2m_obj_ipso_sensor_base_inst_t *)lwm2m_list_find(object->instanceList, + instance_id); + if (!instance) { + DEBUG("[lwm2m IPSO sensor base:exec]: can't find instance %d\n", instance_id); + result = COAP_404_NOT_FOUND; + goto out; + } + + switch (resource_id) { + case LWM2M_IPSO_BASE_SENSOR_RESET_MIN_MAX_MEASURED_VALUES_ID: + instance->min_sensor_value = instance->sensor_value; + instance->max_sensor_value = instance->sensor_value; + result = COAP_204_CHANGED; + break; + + default: + result = COAP_405_METHOD_NOT_ALLOWED; + break; + } + +out: + return result; +} + +int32_t lwm2m_object_ipso_sensor_base_instance_create(lwm2m_obj_ipso_sensor_base_t *object, + const lwm2m_obj_ipso_base_sensor_args_t *args) +{ + assert(object); + assert(args); + + int32_t result = -ENOMEM; + lwm2m_obj_ipso_sensor_base_inst_t *instance = NULL; + uint16_t _instance_id; + + if (object->free_instances == NULL) { + DEBUG("[lwm2m:IPSO sensor base]: object not initialized\n"); + result = -EINVAL; + goto out; + } + + mutex_lock(&object->mutex); + + /* determine ID for new instance */ + if (args->instance_id < 0) { + _instance_id = lwm2m_list_newId((lwm2m_list_t *)_USED_INSTANCES(object)); + } + else { + /* sanity check */ + if (args->instance_id >= (UINT16_MAX - 1)) { + DEBUG("[lwm2m:IPSO sensor base]: instance ID %" PRIi32 " is too big\n", + args->instance_id); + result = -EINVAL; + goto free_out; + } + + _instance_id = (uint16_t)args->instance_id; + + /* check that the ID is free to use */ + if (LWM2M_LIST_FIND(_USED_INSTANCES(object), _instance_id ) != NULL) { + DEBUG("[lwm2m:IPSO sensor base]: instance ID %" PRIi32 " already in use\n", + args->instance_id); + goto free_out; + } + } + + /* get a free instance */ + instance = _get_instance_from_free_list(object); + if (!instance) { + DEBUG("[lwm2m:IPSO sensor base]: can't allocate new instance\n"); + goto free_out; + } + + memset(instance, 0, sizeof(lwm2m_obj_ipso_sensor_base_inst_t)); + + instance->list.id = _instance_id; + instance->sensor_value = 0; + instance->min_sensor_value = 0; + instance->max_sensor_value = 0; + instance->min_range_value = args->min_range_value; + instance->max_range_value = args->max_range_value; + instance->read_cb = args->read_cb; + instance->read_cb_arg = args->read_cb_arg; + + /* if units are specified, copy locally */ + if (args->units) { + if (args->units_len > CONFIG_LWM2M_IPSO_SENSOR_BASE_UNITS_MAX_SIZE) { + DEBUG("[lwm2m:IPSO sensor base]: not enough space for units string\n"); + /* restore instance */ + _put_instance_in_free_list(object, instance); + return -ENOBUFS; + } + memcpy(instance->units, args->units, args->units_len); + } + else { + memset(instance->units, 0, CONFIG_LWM2M_IPSO_SENSOR_BASE_UNITS_MAX_SIZE); + } + + DEBUG("[lwm2m:IPSO sensor base]: new instance with ID %d\n", _instance_id); + + /* add the new instance to the list */ + object->object.instanceList = LWM2M_LIST_ADD(object->object.instanceList, instance); + result = instance->list.id; + +free_out: + mutex_unlock(&object->mutex); +out: + return result; +} + +static void _mark_resource_as_changed(const lwm2m_object_t *object, uint16_t instance_id, + uint16_t resource_id) +{ + lwm2m_uri_t uri; + + uri.objectId = object->objID; + uri.instanceId = instance_id; + uri.resourceId = resource_id; + + uri.flag = LWM2M_URI_FLAG_OBJECT_ID | LWM2M_URI_FLAG_INSTANCE_ID | LWM2M_URI_FLAG_RESOURCE_ID; + + lwm2m_resource_value_changed(lwm2m_client_get_ctx(object->userData), &uri); +} + +void lwm2m_object_ipso_sensor_base_update_value(const lwm2m_client_data_t *client_data, + const lwm2m_obj_ipso_sensor_base_t *object, + uint16_t instance_id, int16_t value) +{ + (void)client_data; + lwm2m_obj_ipso_sensor_base_inst_t *instance; + + /* try to get the requested instance from the object list */ + instance = (lwm2m_obj_ipso_sensor_base_inst_t *)lwm2m_list_find(object->object.instanceList, + instance_id); + if (!instance) { + DEBUG("[lwm2m:IPSO sensor base:update]: can't find instance %" PRIiSIZE "\n", instance_id); + return; + } + + instance->sensor_value = value; + _mark_resource_as_changed(&object->object, instance_id, LWM2M_IPSO_BASE_SENSOR_VALUE_ID); + + if (value < instance->min_sensor_value) { + instance->min_sensor_value = value; + _mark_resource_as_changed(&object->object, instance_id, + LWM2M_IPSO_BASE_SENSOR_MIN_MEASURED_VALUE_ID); + } + + if (value > instance->max_sensor_value) { + instance->max_sensor_value = value; + _mark_resource_as_changed(&object->object, instance_id, + LWM2M_IPSO_BASE_SENSOR_MAX_MEASURED_VALUE_ID); + } +} diff --git a/pkg/wakaama/include/objects/ipso_sensor_base.h b/pkg/wakaama/include/objects/ipso_sensor_base.h new file mode 100644 index 0000000000..2d4f233de0 --- /dev/null +++ b/pkg/wakaama/include/objects/ipso_sensor_base.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2024 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 + * @defgroup lwm2m_objects_ipso_sensor_base IPSO Sensor base object + * @brief Base IPSO sensor functionality to implement similar IPSO objects + * + * @experimental + * + * This module is **not a complete object**, but provides common functionalities + * shared among different IPSO sensor objects. It should not be used directly, + * from the application, but rather be used as a dependency for other objects. + * + * To use this module add `USEMODULE += wakaama_objects_ipso_sensor_base` to the dependencies + * of your own object module. + * + * ## Resources + * Given that IPSO sensors share a common set of resources, these are implemented by this module. + * + | Name | ID | Mandatory | Type | Range | Units | Implemented | + |:-----------------------------------:|:----:|:---------:|:------:|:-----:|:--------:|:-----------:| + | Sensor Value | 5700 | Yes | Float | - | See 5701 | Yes | + | Min. Measured Value | 5601 | No | Float | - | See 5701 | Yes | + | Max. Measured Value | 5602 | No | Float | - | See 5701 | Yes | + | Min. Range Value | 5603 | No | Float | - | See 5701 | Yes | + | Max. Range Value | 5604 | No | Float | - | See 5701 | Yes | + | Reset Min. and Max. Measured Values | 5605 | No | - | - | - | Yes | + | Sensor Units | 5701 | No | String | - | - | Yes | + * + * @{ + * + * @file + * + * @author Leandro Lanzieri + */ + +#ifndef OBJECTS_IPSO_SENSOR_BASE_H +#define OBJECTS_IPSO_SENSOR_BASE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mutex.h" +#include "liblwm2m.h" +#include "lwm2m_client.h" + +/** + * @defgroup lwm2m_objects_ipso_sensor_base_config LwM2M IPSO Sensor base object compile configurations + * @ingroup lwm2m_client_config + * @{ + */ +/** + * @brief Maximum size for the units resource string + */ +#ifndef CONFIG_LWM2M_IPSO_SENSOR_BASE_UNITS_MAX_SIZE +#define CONFIG_LWM2M_IPSO_SENSOR_BASE_UNITS_MAX_SIZE (4U) +#endif +/** @} */ + +/** + * @name IPSO sensor base object resource's IDs (shared among many IPSO sensor objects) + * @{ + */ +/** + * @brief Sensor value resource ID. + */ +#define LWM2M_IPSO_BASE_SENSOR_VALUE_ID 5700 +/** + * @brief Min. measured value resource ID. + */ +#define LWM2M_IPSO_BASE_SENSOR_MIN_MEASURED_VALUE_ID 5601 +/** + * @brief Max. measured value resource ID. + */ +#define LWM2M_IPSO_BASE_SENSOR_MAX_MEASURED_VALUE_ID 5602 +/** + * @brief Min. range value resource ID. + */ +#define LWM2M_IPSO_BASE_SENSOR_MIN_RANGE_VALUE_ID 5603 +/** + * @brief Max. range value resource ID. + */ +#define LWM2M_IPSO_BASE_SENSOR_MAX_RANGE_VALUE_ID 5604 +/** + * @brief Reset min. and max. measured values resource ID. + */ +#define LWM2M_IPSO_BASE_SENSOR_RESET_MIN_MAX_MEASURED_VALUES_ID 5605 +/** + * @brief Sensor units resource ID. + */ +#define LWM2M_IPSO_BASE_SENSOR_UNITS_ID 5701 +/** @} */ + +/** + * @brief Callback for reading the sensor value. + * + * @param[in] read_cb_arg Data passed for the read callback when the instance was created. + * @param[out] value Pointer to the variable where the value will be stored. + * + * @return 0 on success + * @return <0 otherwise + */ +typedef int lwm2m_obj_ipso_base_sensor_read_cb_t(void *read_cb_arg, int16_t *value); + +/** + * @brief Arguments for the creation of an object based on the IPSO Sensor Base + * object instance. + */ +typedef struct lwm2m_obj_ipso_sensor_base_args { + int32_t instance_id; /**< ID for the new instance. It must be between 0 and (UINT16_MAX - 1), + if -1 the next available ID will be used. */ + char *units; /**< Null-terminated string of the "Sensor Units" resource. May be NULL. */ + size_t units_len; /**< Length of units */ + int16_t min_range_value; /**< Minimum value that can be measured by the sensor. */ + int16_t max_range_value; /**< Maximum value that can be measured by the sensor. */ + void *read_cb_arg; /**< Data to pass to the read callback. May be NULL. */ + lwm2m_obj_ipso_base_sensor_read_cb_t *read_cb; /**< Callback to read the sensor value. May be NULL. */ +} lwm2m_obj_ipso_base_sensor_args_t; + +/** + * @brief LwM2M IPSO sensor base instance + */ +typedef struct lwm2m_obj_ipso_sensor_base_inst { + lwm2m_list_t list; /**< list handle */ + int16_t sensor_value; /**< sensor value */ + int16_t min_sensor_value; /**< minimum sensor value */ + int16_t max_sensor_value; /**< maximum sensor value */ + int16_t min_range_value; /**< minimum range value */ + int16_t max_range_value; /**< maximum range value */ + char units[CONFIG_LWM2M_IPSO_SENSOR_BASE_UNITS_MAX_SIZE]; /**< units */ + void *read_cb_arg; /**< Data to pass to the read callback. May be NULL. */ + lwm2m_obj_ipso_base_sensor_read_cb_t *read_cb; /**< Callback to read the sensor value. May be NULL. */ +} lwm2m_obj_ipso_sensor_base_inst_t; + +/** + * @brief LwM2M IPSO sensor base object + */ +typedef struct lwm2m_obj_ipso_sensor_base { + lwm2m_object_t object; /**< LwM2M object base */ + lwm2m_obj_ipso_sensor_base_inst_t *free_instances; /**< List of instances */ + uint16_t object_id; /**< Object ID */ + mutex_t mutex; /**< Mutex for the object */ +} lwm2m_obj_ipso_sensor_base_t; + +/** + * @brief Create a new object instance based on the IPSO Sensor Base and add it to the + * @p object list. + * + * @param[in, out] object Pointer to the LwM2M IPSO object. + * @param[in] args Initialize structure with the parameter for the instance. May + * not be NULL. + * + * @retval instance ID (>0) on success + * @retval <0 otherwise + */ +int32_t lwm2m_object_ipso_sensor_base_instance_create(lwm2m_obj_ipso_sensor_base_t *object, + const lwm2m_obj_ipso_base_sensor_args_t *args); + +/** + * @brief Initialize the a LwM2M object derived from the IPSO Sensor Base object. + * + * @param[in, out] client_data Pointer to the LwM2M client. + * @param[in, out] object Pointer to the LwM2M IPSO object. + * @param[in] object_id Object ID. + * @param[in] instances List of allocated instances. + * @param[in] instance_count Number of allocated instances. + * + * @retval 0 on success + * @retval <0 otherwise + */ +int lwm2m_object_ipso_sensor_base_init_derived(lwm2m_client_data_t *client_data, + lwm2m_obj_ipso_sensor_base_t *object, + uint16_t object_id, + lwm2m_obj_ipso_sensor_base_inst_t *instances, + size_t instance_count); + +/** + * @brief Update the value of the illuminance sensor and trigger a notification + * to the observing servers, if any. + * + * @param[in] client_data Pointer to the LwM2M client. + * @param[in] object Pointer to the LwM2M IPSO object. + * @param[in] instance_id ID of the instance to update. + * @param[in] value New value for the sensor. + */ +void lwm2m_object_ipso_sensor_base_update_value(const lwm2m_client_data_t *client_data, + const lwm2m_obj_ipso_sensor_base_t *object, + uint16_t instance_id, int16_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* OBJECTS_IPSO_SENSOR_BASE_H */ +/** @} */