@@ -87,12 +87,143 @@ static const uint8_t LWM2M_ATTR_LEN[] = {4, 4, 2, 2, 2};
87
87
88
88
static struct lwm2m_attr write_attr_pool [CONFIG_LWM2M_NUM_ATTR ];
89
89
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
+
90
106
/* Forward declarations */
91
107
92
108
void lwm2m_engine_free_list (sys_slist_t * path_list , sys_slist_t * free_list );
93
109
94
110
struct lwm2m_obj_path_list * lwm2m_engine_get_from_list (sys_slist_t * path_list );
95
111
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
+
96
227
const char * const lwm2m_attr_to_str (uint8_t type )
97
228
{
98
229
switch (type ) {
@@ -148,7 +279,7 @@ static int update_attrs(void *ref, struct notification_attrs *out)
148
279
return 0 ;
149
280
}
150
281
151
- void clear_attrs (void * ref )
282
+ void clear_attrs (uint8_t level , void * ref )
152
283
{
153
284
int i ;
154
285
@@ -157,6 +288,8 @@ void clear_attrs(void *ref)
157
288
(void )memset (& write_attr_pool [i ], 0 , sizeof (write_attr_pool [i ]));
158
289
}
159
290
}
291
+
292
+ (void )notify_value_reg_update (level , ref , false);
160
293
}
161
294
162
295
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
1442
}
1310
1443
}
1311
1444
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
+
1312
1460
/* find matching attributes */
1313
1461
for (i = 0 ; i < CONFIG_LWM2M_NUM_ATTR ; i ++ ) {
1314
1462
if (ref != write_attr_pool [i ].ref ) {
0 commit comments