diff --git a/doc/reference/bluetooth/mesh/access.rst b/doc/reference/bluetooth/mesh/access.rst index e2acbc2fe2e92c..acfb98cda9efcc 100644 --- a/doc/reference/bluetooth/mesh/access.rst +++ b/doc/reference/bluetooth/mesh/access.rst @@ -100,6 +100,16 @@ populate the :c:member:`bt_mesh_model_pub.update` callback. The message is published, allowing the model to change the payload to reflect its current state. +By setting :c:member:`bt_mesh_model_pub.retr_update` to 1, the model can +configure the :c:member:`bt_mesh_model_pub.update` callback to be triggered +on every retransmission. This can, for example, be used by models that make +use of a Delay parameter, which can be adjusted for every retransmission. +The :c:func:`bt_mesh_model_pub_is_retransmission` function can be +used to differentiate a first publication and a retransmission. +The :c:macro:`BT_MESH_PUB_MSG_TOTAL` and :c:macro:`BT_MESH_PUB_MSG_NUM` macros +can be used to return total number of transmissions and the retransmission +number within one publication interval. + Extended models =============== diff --git a/include/bluetooth/mesh/access.h b/include/bluetooth/mesh/access.h index 43c9af62fc0dce..971dd75eb7f29f 100644 --- a/include/bluetooth/mesh/access.h +++ b/include/bluetooth/mesh/access.h @@ -343,6 +343,29 @@ struct bt_mesh_model_op { */ #define BT_MESH_PUB_TRANSMIT_INT(transmit) ((((transmit) >> 3) + 1) * 50) +/** @def BT_MESH_PUB_MSG_TOTAL + * + * @brief Get total number of messages within one publication interval including initial + * publication. + * + * @param pub Model publication context. + * + * @return total number of messages. + */ +#define BT_MESH_PUB_MSG_TOTAL(pub) (BT_MESH_PUB_TRANSMIT_COUNT((pub)->retransmit) + 1) + +/** @def BT_MESH_PUB_MSG_NUM + * + * @brief Get message number within one publication interval. + * + * Meant to be used inside @ref bt_mesh_model_pub.update. + * + * @param pub Model publication context. + * + * @return message number starting from 1. + */ +#define BT_MESH_PUB_MSG_NUM(pub) (BT_MESH_PUB_TRANSMIT_COUNT((pub)->retransmit) + 1 - (pub)->count) + /** Model publication context. * * The context should primarily be created using the @@ -356,7 +379,8 @@ struct bt_mesh_model_pub { uint16_t key:12, /**< Publish AppKey Index. */ cred:1, /**< Friendship Credentials Flag. */ send_rel:1, /**< Force reliable sending (segment acks) */ - fast_period:1; /**< Use FastPeriodDivisor */ + fast_period:1, /**< Use FastPeriodDivisor */ + retr_update:1; /**< Call update callback on every retransmission. */ uint8_t ttl; /**< Publish Time to Live. */ uint8_t retransmit; /**< Retransmit Count & Interval Steps. */ @@ -386,6 +410,9 @@ struct bt_mesh_model_pub { * If the callback returns non-zero, the publication is skipped * and will resume on the next periodic publishing interval. * + * When @ref bt_mesh_model_pub.retr_update is set to 1, + * the callback will be called on every retransmission. + * * @param mod The Model the Publication Context belogs to. * * @return Zero on success or (negative) error code otherwise. @@ -572,6 +599,19 @@ int bt_mesh_model_send(struct bt_mesh_model *model, */ int bt_mesh_model_publish(struct bt_mesh_model *model); +/** @brief Check if a message is being retransmitted. + * + * Meant to be used inside the @ref bt_mesh_model_pub.update callback. + * + * @param model Mesh Model that supports publication. + * + * @return true if this is a retransmission, false if this is a first publication. + */ +static inline bool bt_mesh_model_pub_is_retransmission(const struct bt_mesh_model *model) +{ + return model->pub->count != BT_MESH_PUB_TRANSMIT_COUNT(model->pub->retransmit); +} + /** @brief Get the element that a model belongs to. * * @param mod Mesh model. diff --git a/subsys/bluetooth/mesh/access.c b/subsys/bluetooth/mesh/access.c index addf18f43277f4..fc9c39085dcbef 100644 --- a/subsys/bluetooth/mesh/access.c +++ b/subsys/bluetooth/mesh/access.c @@ -241,6 +241,15 @@ static void mod_publish(struct k_work *work) if (pub->count) { pub->count--; + + if (pub->retr_update && pub->update && + bt_mesh_model_pub_is_retransmission(pub->mod)) { + err = pub->update(pub->mod); + if (err) { + publish_sent(err, pub->mod); + return; + } + } } else { /* First publication in this period */ err = pub_period_start(pub); @@ -766,7 +775,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) } /* Account for initial transmission */ - pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit) + 1; + pub->count = BT_MESH_PUB_MSG_TOTAL(pub); BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count, BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));