From bf6d933f56c1f0bc56f682a51d024ea95b2e08d2 Mon Sep 17 00:00:00 2001 From: Ingar Kulbrandstad Date: Tue, 20 Jun 2023 16:24:08 +0200 Subject: [PATCH] Bluetooth: Mesh: Fix bug DTT spanning multiple elements If a Generic Default Transition Time Server model is not present on the main element of the model, then the Generic Default Transition Time Server model instance that is present on the element with the largest address that is smaller than the address of the main element of the node shall be used; if no model instance is present on any element with an address smaller than the address of the main element, then the Generic Default Transition Time Server is not supported. Signed-off-by: Ingar Kulbrandstad --- .../bluetooth_services/mesh/gen_dtt.rst | 2 +- .../bluetooth_services/mesh/gen_dtt_srv.rst | 7 ++--- doc/nrf/releases/release-notes-changelog.rst | 2 ++ include/bluetooth/mesh/gen_dtt_srv.h | 26 ++++++++++--------- subsys/bluetooth/mesh/gen_dtt_srv.c | 21 +++++++++++++++ subsys/bluetooth/mesh/scene_srv.c | 12 +++------ 6 files changed, 46 insertions(+), 24 deletions(-) diff --git a/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt.rst b/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt.rst index 4131eb1234d4..447f8a905681 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt.rst @@ -3,7 +3,7 @@ Generic Default Transition Time models ###################################### -The Generic Default Transition Time (DTT) models are used to control the transition of any other states on the same element as the DTT Server. +The Generic Default Transition Time (DTT) models are used to control the transition of any other states on any element. The DTT Client can remotely control the default transition time state of the server. The DTT models only use native types, and have no common model-specific types. diff --git a/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt_srv.rst b/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt_srv.rst index afc2a48f10e6..07ab64b8e006 100644 --- a/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt_srv.rst +++ b/doc/nrf/libraries/bluetooth_services/mesh/gen_dtt_srv.rst @@ -7,9 +7,10 @@ Generic Default Transition Time Server :local: :depth: 2 -The DTT Server provides a common way to specify the state transition time for other models on the same element. -If other generic models on the same element receive state change commands without transition parameters, they will use the default transition time specified by the DTT Server model. -This way, the DTT Server can define a consistent transition time for all states on their elements, without depending on client configurations. +The DTT Server provides a common way to specify the state transition time for other models on any element. +If a DTT Server is not present on the model's element, use the DTT Server model instance that is present on the element with the largest address that is smaller than the address of the given element. +This way, if other generic models on any element receive state change commands without transition parameters, they will use the default transition time specified by the DTT Server model. +The DTT Server can then define a consistent transition time for all states on their elements, without depending on client configurations. Configuration ============= diff --git a/doc/nrf/releases/release-notes-changelog.rst b/doc/nrf/releases/release-notes-changelog.rst index f206a38fd38b..fc08d8006911 100644 --- a/doc/nrf/releases/release-notes-changelog.rst +++ b/doc/nrf/releases/release-notes-changelog.rst @@ -314,6 +314,8 @@ Bluetooth libraries and services * The :kconfig:option:`BT_MESH_MODEL_SRV_STORE_TIMEOUT` Kconfig option, that is controlling timeout for storing of model states, is replaced by the :kconfig:option:`BT_MESH_STORE_TIMEOUT` Kconfig option. + * Fixed an issue where the :ref:'bt_mesh_dtt_srv_readme' model could not be found for models spanning multiple elements. + Bootloader libraries -------------------- diff --git a/include/bluetooth/mesh/gen_dtt_srv.h b/include/bluetooth/mesh/gen_dtt_srv.h index 45060950142c..863bc3dedf32 100644 --- a/include/bluetooth/mesh/gen_dtt_srv.h +++ b/include/bluetooth/mesh/gen_dtt_srv.h @@ -107,21 +107,18 @@ void bt_mesh_dtt_srv_set(struct bt_mesh_dtt_srv *srv, uint32_t transition_time); int bt_mesh_dtt_srv_pub(struct bt_mesh_dtt_srv *srv, struct bt_mesh_msg_ctx *ctx); -/** @brief Find the Generic DTT server in a given element. +/** @brief Find the Generic DTT server over multiple elements. * - * @param[in] elem Element to find the DTT server in. + * If the DTT Server is not present on the given element of the model, then the + * try to find the DTT Server model instance that is present on the element with + * the largest address that is smaller than the address of the given element. + * + * @param[in] elem Element to start search of the DTT server in. * * @return A pointer to the DTT server instance, or NULL if no instance is * found. */ -static inline struct bt_mesh_dtt_srv * -bt_mesh_dtt_srv_get(const struct bt_mesh_elem *elem) -{ - struct bt_mesh_model *model = bt_mesh_model_find( - elem, BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV); - - return (struct bt_mesh_dtt_srv *)(model ? model->user_data : NULL); -} +struct bt_mesh_dtt_srv *bt_mesh_dtt_srv_get(const struct bt_mesh_elem *elem); /** @brief Get the default transition parameters for the given model. * @@ -134,8 +131,13 @@ static inline bool bt_mesh_dtt_srv_transition_get(struct bt_mesh_model *model, struct bt_mesh_model_transition *transition) { - struct bt_mesh_dtt_srv *srv = - bt_mesh_dtt_srv_get(bt_mesh_model_elem(model)); + struct bt_mesh_dtt_srv *srv; + + if (IS_ENABLED(CONFIG_BT_MESH_DTT_SRV)) { + srv = bt_mesh_dtt_srv_get(bt_mesh_model_elem(model)); + } else { + srv = NULL; + } transition->time = srv ? srv->transition_time : 0; transition->delay = 0; diff --git a/subsys/bluetooth/mesh/gen_dtt_srv.c b/subsys/bluetooth/mesh/gen_dtt_srv.c index 0c01bb58c353..d39b69458f8b 100644 --- a/subsys/bluetooth/mesh/gen_dtt_srv.c +++ b/subsys/bluetooth/mesh/gen_dtt_srv.c @@ -7,6 +7,7 @@ #include #include #include "model_utils.h" +#include "mesh/access.h" static void encode_status(struct net_buf_simple *buf, uint32_t transition_time) { @@ -188,3 +189,23 @@ int bt_mesh_dtt_srv_pub(struct bt_mesh_dtt_srv *srv, return bt_mesh_msg_send(srv->model, ctx, &msg); } + +struct bt_mesh_dtt_srv *bt_mesh_dtt_srv_get(const struct bt_mesh_elem *elem) +{ + const struct bt_mesh_comp *comp = bt_mesh_comp_get(); + uint16_t index; + + index = elem->addr - comp->elem[0].addr; + for (int i = index; i >= 0; --i) { + struct bt_mesh_elem *element = &comp->elem[i]; + + struct bt_mesh_model *model = + bt_mesh_model_find(element, BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV); + + if (model) { + return (struct bt_mesh_dtt_srv *)(model->user_data); + } + }; + + return NULL; +} diff --git a/subsys/bluetooth/mesh/scene_srv.c b/subsys/bluetooth/mesh/scene_srv.c index 8791a228cd75..2c9d287bf9fa 100644 --- a/subsys/bluetooth/mesh/scene_srv.c +++ b/subsys/bluetooth/mesh/scene_srv.c @@ -820,10 +820,8 @@ const struct bt_mesh_model_cb _bt_mesh_scene_srv_cb = { static int scene_setup_srv_init(struct bt_mesh_model *model) { struct bt_mesh_scene_srv *srv = model->user_data; - const struct bt_mesh_comp *comp = bt_mesh_comp_get(); - struct bt_mesh_model *dtt_srv = NULL; + struct bt_mesh_dtt_srv *dtt_srv = NULL; int err; - int i; if (!srv) { return -EINVAL; @@ -831,10 +829,8 @@ static int scene_setup_srv_init(struct bt_mesh_model *model) srv->setup_mod = model; - for (i = model->elem_idx; (i >= 0) && (dtt_srv == NULL); --i) { - struct bt_mesh_elem *elem = &comp->elem[i]; - - dtt_srv = bt_mesh_model_find(elem, BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV); + if (IS_ENABLED(CONFIG_BT_MESH_DTT_SRV)) { + dtt_srv = bt_mesh_dtt_srv_get(bt_mesh_model_elem(model)); } if (!dtt_srv) { @@ -842,7 +838,7 @@ static int scene_setup_srv_init(struct bt_mesh_model *model) return -EINVAL; } - err = bt_mesh_model_extend(srv->setup_mod, dtt_srv); + err = bt_mesh_model_extend(srv->setup_mod, dtt_srv->model); if (err) { return err; }