Skip to content

Commit 1ee6943

Browse files
rlubosdanieldegrasse
authored andcommitted
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 <[email protected]>
1 parent 46aaf28 commit 1ee6943

File tree

4 files changed

+160
-4
lines changed

4 files changed

+160
-4
lines changed

subsys/net/lib/lwm2m/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,14 @@ config LWM2M_NUM_ATTR
446446
This value sets up the maximum number of LwM2M attributes that
447447
we can handle at the same time.
448448

449+
config LWM2M_MAX_NOTIFIED_NUMERICAL_RES_TRACKED
450+
int "Maximum # of resources that can track last notified value for gt/lt/st"
451+
default 4
452+
help
453+
This value specifies the maximum number of numerical LwM2M resources
454+
that can track the last notified resource value for gt/lt/st attribute
455+
handling.
456+
449457
endmenu # "Memory and buffer size configuration"
450458

451459
menu "Content format supports"

subsys/net/lib/lwm2m/lwm2m_observation.c

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,143 @@ static const uint8_t LWM2M_ATTR_LEN[] = {4, 4, 2, 2, 2};
8787

8888
static struct lwm2m_attr write_attr_pool[CONFIG_LWM2M_NUM_ATTR];
8989

90+
/* Notification value register is used to store the resource values sent in
91+
* the last notification, for resources that carry one of the numerical
92+
* gt/lt/st attributes. This value is needed to determine whether notification
93+
* send conditions are satisfied for given attributes.
94+
*/
95+
static struct lwm2m_notify_value_register {
96+
/* A pointer to the corresponding resource instance. */
97+
const struct lwm2m_engine_res_inst *ref;
98+
99+
/* Last notified resource value. */
100+
double value;
101+
102+
/* Whether resource was notified already or not. */
103+
bool notified : 1;
104+
} notify_value_pool[CONFIG_LWM2M_MAX_NOTIFIED_NUMERICAL_RES_TRACKED];
105+
90106
/* Forward declarations */
91107

92108
void lwm2m_engine_free_list(sys_slist_t *path_list, sys_slist_t *free_list);
93109

94110
struct lwm2m_obj_path_list *lwm2m_engine_get_from_list(sys_slist_t *path_list);
95111

112+
static struct lwm2m_notify_value_register *notify_value_reg_alloc(
113+
const struct lwm2m_engine_res_inst *ref)
114+
{
115+
for (int i = 0; i < ARRAY_SIZE(notify_value_pool); i++) {
116+
if (notify_value_pool[i].ref == NULL) {
117+
notify_value_pool[i].ref = ref;
118+
notify_value_pool[i].notified = false;
119+
120+
return &notify_value_pool[i];
121+
}
122+
}
123+
124+
return NULL;
125+
}
126+
127+
static void notify_value_reg_free(const struct lwm2m_engine_res_inst *ref)
128+
{
129+
for (int i = 0; i < ARRAY_SIZE(notify_value_pool); i++) {
130+
if (ref == notify_value_pool[i].ref) {
131+
(void)memset(&notify_value_pool[i], 0,
132+
sizeof(notify_value_pool[i]));
133+
break;
134+
}
135+
}
136+
}
137+
138+
static struct lwm2m_notify_value_register *notify_value_reg_get(
139+
const struct lwm2m_engine_res_inst *ref)
140+
{
141+
for (int i = 0; i < ARRAY_SIZE(notify_value_pool); i++) {
142+
if (ref == notify_value_pool[i].ref) {
143+
return &notify_value_pool[i];
144+
}
145+
}
146+
147+
return NULL;
148+
}
149+
150+
static int notify_value_reg_inst_update(const struct lwm2m_engine_res_inst *ref,
151+
bool enable)
152+
{
153+
struct lwm2m_notify_value_register *notify_reg;
154+
155+
if (ref->res_inst_id == RES_INSTANCE_NOT_CREATED) {
156+
return 0;
157+
}
158+
159+
if (!enable) {
160+
notify_value_reg_free(ref);
161+
return 0;
162+
}
163+
164+
notify_reg = notify_value_reg_get(ref);
165+
if (notify_reg == NULL) {
166+
notify_reg = notify_value_reg_alloc(ref);
167+
}
168+
169+
if (notify_reg == NULL) {
170+
LOG_ERR("Failed to allocate entry in notify registry");
171+
return -ENOMEM;
172+
}
173+
174+
return 0;
175+
}
176+
177+
static int notify_value_reg_update(uint8_t level, void *ref, bool enable)
178+
{
179+
struct lwm2m_engine_res *res;
180+
int ret;
181+
182+
if (level < LWM2M_PATH_LEVEL_RESOURCE) {
183+
return -EINVAL;
184+
}
185+
186+
if (level == LWM2M_PATH_LEVEL_RESOURCE_INST) {
187+
return notify_value_reg_inst_update(ref, enable);
188+
}
189+
190+
/* Resource level - need to allocate value registers for all instances */
191+
res = ref;
192+
for (int i = 0; i < res->res_inst_count; i++) {
193+
ret = notify_value_reg_inst_update(&res->res_instances[i],
194+
enable);
195+
if (ret < 0) {
196+
goto cleanup;
197+
}
198+
}
199+
200+
return 0;
201+
202+
cleanup:
203+
for (int i = 0; i < res->res_inst_count; i++) {
204+
bool skip = false;
205+
206+
for (int j = 0; j < ARRAY_SIZE(write_attr_pool); j++) {
207+
struct lwm2m_attr *attr = &write_attr_pool[j];
208+
209+
/* If register was allocated individually for the resource
210+
* instance earlier - skip.
211+
*/
212+
if (attr->ref == &res->res_instances[i] &&
213+
(attr->type == LWM2M_ATTR_LT ||
214+
attr->type == LWM2M_ATTR_GT ||
215+
attr->type == LWM2M_ATTR_STEP)) {
216+
skip = true;
217+
break;
218+
}
219+
}
220+
221+
(void)notify_value_reg_inst_update(&res->res_instances[i], false);
222+
}
223+
224+
return -ENOMEM;
225+
}
226+
96227
const char *const lwm2m_attr_to_str(uint8_t type)
97228
{
98229
switch (type) {
@@ -148,7 +279,7 @@ static int update_attrs(void *ref, struct notification_attrs *out)
148279
return 0;
149280
}
150281

151-
void clear_attrs(void *ref)
282+
void clear_attrs(uint8_t level, void *ref)
152283
{
153284
int i;
154285

@@ -157,6 +288,8 @@ void clear_attrs(void *ref)
157288
(void)memset(&write_attr_pool[i], 0, sizeof(write_attr_pool[i]));
158289
}
159290
}
291+
292+
(void)notify_value_reg_update(level, ref, false);
160293
}
161294

162295
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
13091442
}
13101443
}
13111444

1445+
if (msg->path.level >= LWM2M_PATH_LEVEL_RESOURCE) {
1446+
bool enable = false;
1447+
1448+
if ((nattrs.flags & (BIT(LWM2M_ATTR_LT) |
1449+
BIT(LWM2M_ATTR_GT) |
1450+
BIT(LWM2M_ATTR_STEP))) != 0) {
1451+
enable = true;
1452+
}
1453+
1454+
ret = notify_value_reg_update(msg->path.level, ref, enable);
1455+
if (ret < 0) {
1456+
return ret;
1457+
}
1458+
}
1459+
13121460
/* find matching attributes */
13131461
for (i = 0; i < CONFIG_LWM2M_NUM_ATTR; i++) {
13141462
if (ref != write_attr_pool[i].ref) {

subsys/net/lib/lwm2m/lwm2m_observation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const char *lwm2m_engine_get_attr_name(const struct lwm2m_attr *attr);
3232

3333
const char *const lwm2m_attr_to_str(uint8_t type);
3434

35-
void clear_attrs(void *ref);
35+
void clear_attrs(uint8_t level, void *ref);
3636

3737
int64_t engine_observe_shedule_next_event(struct observe_node *obs, uint16_t srv_obj_inst,
3838
const int64_t timestamp);

subsys/net/lib/lwm2m/lwm2m_registry.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,11 @@ int lwm2m_delete_obj_inst(uint16_t obj_id, uint16_t obj_inst_id)
306306

307307
/* reset obj_inst and res_inst data structure */
308308
for (i = 0; i < obj_inst->resource_count; i++) {
309-
clear_attrs(&obj_inst->resources[i]);
309+
clear_attrs(LWM2M_PATH_LEVEL_RESOURCE, &obj_inst->resources[i]);
310310
(void)memset(obj_inst->resources + i, 0, sizeof(struct lwm2m_engine_res));
311311
}
312312

313-
clear_attrs(obj_inst);
313+
clear_attrs(LWM2M_PATH_LEVEL_OBJECT_INST, obj_inst);
314314
(void)memset(obj_inst, 0, sizeof(struct lwm2m_engine_obj_inst));
315315
k_mutex_unlock(&registry_lock);
316316
return ret;

0 commit comments

Comments
 (0)