diff --git a/doc/connectivity/bluetooth/api/mesh/access.rst b/doc/connectivity/bluetooth/api/mesh/access.rst index 06236f98cb6..37d5d6fddef 100644 --- a/doc/connectivity/bluetooth/api/mesh/access.rst +++ b/doc/connectivity/bluetooth/api/mesh/access.rst @@ -149,6 +149,22 @@ storage. The model can retrieve the data by calling the ``read_cb`` passed as a parameter to the callback. See the :ref:`settings_api` module documentation for details. +When model data changes frequently, storing it on every change may lead to +increased wear of flash. To reduce the wear, the model can postpone storing of +data by calling :c:func:`bt_mesh_model_data_store_schedule`. The stack will +schedule a work item with delay defined by the +:kconfig:option:`CONFIG_BT_MESH_STORE_TIMEOUT` option. When the work item is +running, the stack will call the :c:member:`bt_mesh_model_cb.pending_store` +callback for every model that has requested storing of data. The model can +then call :c:func:`bt_mesh_model_data_store` to store the data. + +If :kconfig:option:`CONFIG_BT_MESH_SETTINGS_WORKQ` is enabled, the +:c:member:`bt_mesh_model_cb.pending_store` callback is called from a dedicated +thread. This allows the stack to process other incoming and outgoing messages +while model data is being stored. It is recommended to use this option and the +:c:func:`bt_mesh_model_data_store_schedule` function when large amount of data +needs to be stored. + API reference ************* diff --git a/include/zephyr/bluetooth/mesh/access.h b/include/zephyr/bluetooth/mesh/access.h index 80e3948f1eb..75fa81c9089 100644 --- a/include/zephyr/bluetooth/mesh/access.h +++ b/include/zephyr/bluetooth/mesh/access.h @@ -662,6 +662,16 @@ struct bt_mesh_model_cb { * @param model Model this callback belongs to. */ void (*const reset)(struct bt_mesh_model *model); + + /** @brief Callback used to store pending model's user data. + * + * Triggered by @ref bt_mesh_model_data_store_schedule. + * + * To store the user data, call @ref bt_mesh_model_data_store. + * + * @param model Model this callback belongs to. + */ + void (*const pending_store)(struct bt_mesh_model *model); }; /** Vendor model ID */ @@ -842,6 +852,19 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, const char *name, const void *data, size_t data_len); +/** @brief Schedule the model's user data store in persistent storage. + * + * This function triggers the @ref bt_mesh_model_cb.pending_store callback + * for the corresponding model after delay defined by + * @kconfig{CONFIG_BT_MESH_STORE_TIMEOUT}. + * + * The delay is global for all models. Once scheduled, the callback can + * not be re-scheduled until previous schedule completes. + * + * @param mod Mesh model. + */ +void bt_mesh_model_data_store_schedule(struct bt_mesh_model *mod); + /** @brief Let a model extend another. * * Mesh models may be extended to reuse their functionality, forming a more diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index d009837c167..d8ba60cbb46 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -1850,6 +1850,11 @@ static void store_pending_mod(struct bt_mesh_model *mod, mod->flags &= ~BT_MESH_MOD_PUB_PENDING; store_pending_mod_pub(mod, vnd); } + + if (mod->flags & BT_MESH_MOD_DATA_PENDING) { + mod->flags &= ~BT_MESH_MOD_DATA_PENDING; + mod->cb->pending_store(mod); + } } void bt_mesh_model_pending_store(void) @@ -2134,3 +2139,9 @@ void bt_mesh_model_settings_commit(void) { bt_mesh_model_foreach(commit_mod, NULL); } + +void bt_mesh_model_data_store_schedule(struct bt_mesh_model *mod) +{ + mod->flags |= BT_MESH_MOD_DATA_PENDING; + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); +} diff --git a/subsys/bluetooth/mesh/access.h b/subsys/bluetooth/mesh/access.h index 86d7a212344..43ec1839160 100644 --- a/subsys/bluetooth/mesh/access.h +++ b/subsys/bluetooth/mesh/access.h @@ -17,6 +17,7 @@ enum { BT_MESH_MOD_PUB_PENDING = BIT(2), BT_MESH_MOD_EXTENDED = BIT(3), BT_MESH_MOD_DEVKEY_ONLY = BIT(4), + BT_MESH_MOD_DATA_PENDING = BIT(5), }; void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);