Browse Source

net: lwm2m: Implement notified value registry for gt/lt/st attributes

Greater than, Less than and Step attributes require to track the last
notified value of a resource/resource instance in order to be able to
apply the specific thershold/step rules that the attributes define.

Therefore, implement a simple registry of the last notified values. When
one of the gt/lt/st attributes is configured on a resource/resource
instance, a registry entry is allocated for respective resource.
Whenever a notification is sent (either as a reply to Observe message,
or proactively) the registry is updated for the notified resources.

The stored resource values have been unified as "double" variables, to
avoid implementation complexity of having to support different
integer/floating point resource types.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
pull/89265/head
Robert Lubos 2 weeks ago committed by Daniel DeGrasse
parent
commit
1ee6943cb5
  1. 8
      subsys/net/lib/lwm2m/Kconfig
  2. 150
      subsys/net/lib/lwm2m/lwm2m_observation.c
  3. 2
      subsys/net/lib/lwm2m/lwm2m_observation.h
  4. 4
      subsys/net/lib/lwm2m/lwm2m_registry.c

8
subsys/net/lib/lwm2m/Kconfig

@ -446,6 +446,14 @@ config LWM2M_NUM_ATTR @@ -446,6 +446,14 @@ config LWM2M_NUM_ATTR
This value sets up the maximum number of LwM2M attributes that
we can handle at the same time.
config LWM2M_MAX_NOTIFIED_NUMERICAL_RES_TRACKED
int "Maximum # of resources that can track last notified value for gt/lt/st"
default 4
help
This value specifies the maximum number of numerical LwM2M resources
that can track the last notified resource value for gt/lt/st attribute
handling.
endmenu # "Memory and buffer size configuration"
menu "Content format supports"

150
subsys/net/lib/lwm2m/lwm2m_observation.c

@ -87,12 +87,143 @@ static const uint8_t LWM2M_ATTR_LEN[] = {4, 4, 2, 2, 2}; @@ -87,12 +87,143 @@ static const uint8_t LWM2M_ATTR_LEN[] = {4, 4, 2, 2, 2};
static struct lwm2m_attr write_attr_pool[CONFIG_LWM2M_NUM_ATTR];
/* Notification value register is used to store the resource values sent in
* the last notification, for resources that carry one of the numerical
* gt/lt/st attributes. This value is needed to determine whether notification
* send conditions are satisfied for given attributes.
*/
static struct lwm2m_notify_value_register {
/* A pointer to the corresponding resource instance. */
const struct lwm2m_engine_res_inst *ref;
/* Last notified resource value. */
double value;
/* Whether resource was notified already or not. */
bool notified : 1;
} notify_value_pool[CONFIG_LWM2M_MAX_NOTIFIED_NUMERICAL_RES_TRACKED];
/* Forward declarations */
void lwm2m_engine_free_list(sys_slist_t *path_list, sys_slist_t *free_list);
struct lwm2m_obj_path_list *lwm2m_engine_get_from_list(sys_slist_t *path_list);
static struct lwm2m_notify_value_register *notify_value_reg_alloc(
const struct lwm2m_engine_res_inst *ref)
{
for (int i = 0; i < ARRAY_SIZE(notify_value_pool); i++) {
if (notify_value_pool[i].ref == NULL) {
notify_value_pool[i].ref = ref;
notify_value_pool[i].notified = false;
return &notify_value_pool[i];
}
}
return NULL;
}
static void notify_value_reg_free(const struct lwm2m_engine_res_inst *ref)
{
for (int i = 0; i < ARRAY_SIZE(notify_value_pool); i++) {
if (ref == notify_value_pool[i].ref) {
(void)memset(&notify_value_pool[i], 0,
sizeof(notify_value_pool[i]));
break;
}
}
}
static struct lwm2m_notify_value_register *notify_value_reg_get(
const struct lwm2m_engine_res_inst *ref)
{
for (int i = 0; i < ARRAY_SIZE(notify_value_pool); i++) {
if (ref == notify_value_pool[i].ref) {
return &notify_value_pool[i];
}
}
return NULL;
}
static int notify_value_reg_inst_update(const struct lwm2m_engine_res_inst *ref,
bool enable)
{
struct lwm2m_notify_value_register *notify_reg;
if (ref->res_inst_id == RES_INSTANCE_NOT_CREATED) {
return 0;
}
if (!enable) {
notify_value_reg_free(ref);
return 0;
}
notify_reg = notify_value_reg_get(ref);
if (notify_reg == NULL) {
notify_reg = notify_value_reg_alloc(ref);
}
if (notify_reg == NULL) {
LOG_ERR("Failed to allocate entry in notify registry");
return -ENOMEM;
}
return 0;
}
static int notify_value_reg_update(uint8_t level, void *ref, bool enable)
{
struct lwm2m_engine_res *res;
int ret;
if (level < LWM2M_PATH_LEVEL_RESOURCE) {
return -EINVAL;
}
if (level == LWM2M_PATH_LEVEL_RESOURCE_INST) {
return notify_value_reg_inst_update(ref, enable);
}
/* Resource level - need to allocate value registers for all instances */
res = ref;
for (int i = 0; i < res->res_inst_count; i++) {
ret = notify_value_reg_inst_update(&res->res_instances[i],
enable);
if (ret < 0) {
goto cleanup;
}
}
return 0;
cleanup:
for (int i = 0; i < res->res_inst_count; i++) {
bool skip = false;
for (int j = 0; j < ARRAY_SIZE(write_attr_pool); j++) {
struct lwm2m_attr *attr = &write_attr_pool[j];
/* If register was allocated individually for the resource
* instance earlier - skip.
*/
if (attr->ref == &res->res_instances[i] &&
(attr->type == LWM2M_ATTR_LT ||
attr->type == LWM2M_ATTR_GT ||
attr->type == LWM2M_ATTR_STEP)) {
skip = true;
break;
}
}
(void)notify_value_reg_inst_update(&res->res_instances[i], false);
}
return -ENOMEM;
}
const char *const lwm2m_attr_to_str(uint8_t type)
{
switch (type) {
@ -148,7 +279,7 @@ static int update_attrs(void *ref, struct notification_attrs *out) @@ -148,7 +279,7 @@ static int update_attrs(void *ref, struct notification_attrs *out)
return 0;
}
void clear_attrs(void *ref)
void clear_attrs(uint8_t level, void *ref)
{
int i;
@ -157,6 +288,8 @@ void clear_attrs(void *ref) @@ -157,6 +288,8 @@ void clear_attrs(void *ref)
(void)memset(&write_attr_pool[i], 0, sizeof(write_attr_pool[i]));
}
}
(void)notify_value_reg_update(level, ref, false);
}
static bool lwm2m_observer_path_compare(const struct lwm2m_obj_path *o_p,
@ -1309,6 +1442,21 @@ int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj, struct lwm2m_message @@ -1309,6 +1442,21 @@ int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj, struct lwm2m_message
}
}
if (msg->path.level >= LWM2M_PATH_LEVEL_RESOURCE) {
bool enable = false;
if ((nattrs.flags & (BIT(LWM2M_ATTR_LT) |
BIT(LWM2M_ATTR_GT) |
BIT(LWM2M_ATTR_STEP))) != 0) {
enable = true;
}
ret = notify_value_reg_update(msg->path.level, ref, enable);
if (ret < 0) {
return ret;
}
}
/* find matching attributes */
for (i = 0; i < CONFIG_LWM2M_NUM_ATTR; i++) {
if (ref != write_attr_pool[i].ref) {

2
subsys/net/lib/lwm2m/lwm2m_observation.h

@ -32,7 +32,7 @@ const char *lwm2m_engine_get_attr_name(const struct lwm2m_attr *attr); @@ -32,7 +32,7 @@ const char *lwm2m_engine_get_attr_name(const struct lwm2m_attr *attr);
const char *const lwm2m_attr_to_str(uint8_t type);
void clear_attrs(void *ref);
void clear_attrs(uint8_t level, void *ref);
int64_t engine_observe_shedule_next_event(struct observe_node *obs, uint16_t srv_obj_inst,
const int64_t timestamp);

4
subsys/net/lib/lwm2m/lwm2m_registry.c

@ -306,11 +306,11 @@ int lwm2m_delete_obj_inst(uint16_t obj_id, uint16_t obj_inst_id) @@ -306,11 +306,11 @@ int lwm2m_delete_obj_inst(uint16_t obj_id, uint16_t obj_inst_id)
/* reset obj_inst and res_inst data structure */
for (i = 0; i < obj_inst->resource_count; i++) {
clear_attrs(&obj_inst->resources[i]);
clear_attrs(LWM2M_PATH_LEVEL_RESOURCE, &obj_inst->resources[i]);
(void)memset(obj_inst->resources + i, 0, sizeof(struct lwm2m_engine_res));
}
clear_attrs(obj_inst);
clear_attrs(LWM2M_PATH_LEVEL_OBJECT_INST, obj_inst);
(void)memset(obj_inst, 0, sizeof(struct lwm2m_engine_obj_inst));
k_mutex_unlock(&registry_lock);
return ret;

Loading…
Cancel
Save