Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions doc/connectivity/networking/api/lwm2m.rst
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,9 @@ Read and Write operations
Full content of data cache is written into a payload when any READ, SEND or NOTIFY operation
internally reads the content of a given resource. This has a side effect that any read callbacks
registered for a that resource are ignored when cache is enabled.
Data is written into a cache when any of the ``lwm2m_set_*`` functions are called. To filter
the data entering the cache, application may register a validation callback using
:c:func:`lwm2m_register_validate_callback`.
Data is written into a cache when any of the ``lwm2m_set_*`` functions are called. Applications can
register a cache filter callback with :c:func:`lwm2m_set_cache_filter` to drop otherwise valid samples
based on application-specific rules.

Limitations
===========
Expand Down
29 changes: 29 additions & 0 deletions include/zephyr/net/lwm2m.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,20 @@ struct lwm2m_time_series_elem {
};
};

/**
* @typedef lwm2m_cache_filter_cb_t
* @brief Callback type for filtering cached time series samples.
*
* Returning false skips storing the provided sample in the LwM2M cache.
*
* @param path Object path of the cached resource.
* @param element Sample produced by the engine for the cache.
*
* @return true to keep the sample, false to discard it.
*/
typedef bool (*lwm2m_cache_filter_cb_t)(const struct lwm2m_obj_path *path,
const struct lwm2m_time_series_elem *element);

/**
* @brief Asynchronous callback to get a resource buffer and length.
*
Expand Down Expand Up @@ -1590,6 +1604,21 @@ struct lwm2m_ctx *lwm2m_rd_client_ctx(void);
int lwm2m_enable_cache(const struct lwm2m_obj_path *path, struct lwm2m_time_series_elem *data_cache,
size_t cache_len);

/**
* @brief Register a filtering callback for cached resource samples.
*
* The callback is invoked whenever the LwM2M engine attempts to append a new
* sample to the resource cache. Returning false prevents the sample from being
* stored. Passing a NULL callback removes any previously registered filter.
*
* @param path LwM2M path to the cached resource.
* @param filter_cb Callback used to decide whether samples should be cached.
*
* @return 0 for success or a negative errno code in case of error.
*/
int lwm2m_set_cache_filter(const struct lwm2m_obj_path *path,
lwm2m_cache_filter_cb_t filter_cb);

/**
* @brief Security modes as defined in LwM2M Security object.
*/
Expand Down
32 changes: 32 additions & 0 deletions subsys/net/lib/lwm2m/lwm2m_registry.c
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,7 @@ lwm2m_cache_entry_allocate(const struct lwm2m_obj_path *path)
for (i = 0; i < ARRAY_SIZE(lwm2m_cache_entries); i++) {
if (lwm2m_cache_entries[i].path.level == 0) {
lwm2m_cache_entries[i].path = *path;
lwm2m_cache_entries[i].filter_cb = NULL;
sys_slist_append(&lwm2m_timed_cache_list, &lwm2m_cache_entries[i].node);
return &lwm2m_cache_entries[i];
}
Expand Down Expand Up @@ -1542,6 +1543,14 @@ static void lwm2m_engine_cache_write(const struct lwm2m_engine_obj_field *obj_fi
break;
}

if (cache_entry->filter_cb &&
!cache_entry->filter_cb(&cache_entry->path, &elements)) {
LOG_DBG("Cache filter dropped sample for %u/%u/%u",
cache_entry->path.obj_id, cache_entry->path.obj_inst_id,
cache_entry->path.res_id);
return;
}

if (!lwm2m_cache_write(cache_entry, &elements)) {
LOG_WRN("Data cache full");
}
Expand Down Expand Up @@ -1628,6 +1637,29 @@ int lwm2m_enable_cache(const struct lwm2m_obj_path *path, struct lwm2m_time_seri
#endif /* CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT */
}

int lwm2m_set_cache_filter(const struct lwm2m_obj_path *path,
lwm2m_cache_filter_cb_t filter_cb)
{
#if defined(CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT)
struct lwm2m_time_series_resource *cache_entry;

if (path == NULL) {
return -EINVAL;
}

cache_entry = lwm2m_cache_entry_get_by_object(path);
if (cache_entry == NULL) {
return -ENOENT;
}

cache_entry->filter_cb = filter_cb;

return 0;
#else
return -ENOTSUP;
#endif /* CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT */
}

#if defined(CONFIG_LWM2M_RESOURCE_DATA_CACHE_SUPPORT)
static int lwm2m_engine_data_cache_init(void)
{
Expand Down
2 changes: 2 additions & 0 deletions subsys/net/lib/lwm2m/lwm2m_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ struct lwm2m_time_series_resource {
sys_snode_t node;
/* Resource Path url */
struct lwm2m_obj_path path;
/* Optional filter for cached samples */
lwm2m_cache_filter_cb_t filter_cb;
/* Ring buffer */
struct ring_buf rb;
};
Expand Down
1 change: 1 addition & 0 deletions tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ ZTEST(lwm2m_registry, test_resource_cache)
/* Resource cache is turned off */
zassert_is_null(lwm2m_cache_entry_get_by_object(&path));
zassert_equal(lwm2m_enable_cache(&path, &e, 1), -ENOTSUP);
zassert_equal(lwm2m_set_cache_filter(&path, NULL), -ENOTSUP);
zassert_false(lwm2m_cache_write(NULL, NULL));
zassert_false(lwm2m_cache_read(NULL, NULL));
zassert_equal(lwm2m_cache_size(NULL), 0);
Expand Down