Bluetooth: Mesh: Add option to call update cb on every retransmission

A user may want to control message parameters (for example, delay
parameter) on every retransmission of a published message (for example,
see section 1.4.1 of the mesh model specification). This is essential
for lighting messages as time gap between messages retransmitted via
the publish-retransmit mechanism introduces unwanted jitter/pop-corn
when such retransmissions are received by a large 'group' of lights.

This commit adds an option to `struct bt_mesh_model_pub` to make the
access layer call `bt_mesh_model_pub.update` callback on every
retransmission. This also addes few macros and functions that can be
used for further calculations.

Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
Pavel Vasilyev 2021-11-05 16:25:51 +01:00 committed by Johan Hedberg
commit 70b0734b5e
3 changed files with 61 additions and 2 deletions

View file

@ -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 message is published, allowing the model to change the payload to reflect its
current state. 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 Extended models
=============== ===============

View file

@ -343,6 +343,29 @@ struct bt_mesh_model_op {
*/ */
#define BT_MESH_PUB_TRANSMIT_INT(transmit) ((((transmit) >> 3) + 1) * 50) #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. /** Model publication context.
* *
* The context should primarily be created using the * The context should primarily be created using the
@ -356,7 +379,8 @@ struct bt_mesh_model_pub {
uint16_t key:12, /**< Publish AppKey Index. */ uint16_t key:12, /**< Publish AppKey Index. */
cred:1, /**< Friendship Credentials Flag. */ cred:1, /**< Friendship Credentials Flag. */
send_rel:1, /**< Force reliable sending (segment acks) */ 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 ttl; /**< Publish Time to Live. */
uint8_t retransmit; /**< Retransmit Count & Interval Steps. */ 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 * If the callback returns non-zero, the publication is skipped
* and will resume on the next periodic publishing interval. * 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. * @param mod The Model the Publication Context belogs to.
* *
* @return Zero on success or (negative) error code otherwise. * @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); 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. /** @brief Get the element that a model belongs to.
* *
* @param mod Mesh model. * @param mod Mesh model.

View file

@ -241,6 +241,15 @@ static void mod_publish(struct k_work *work)
if (pub->count) { if (pub->count) {
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 { } else {
/* First publication in this period */ /* First publication in this period */
err = pub_period_start(pub); err = pub_period_start(pub);
@ -766,7 +775,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
} }
/* Account for initial transmission */ /* 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_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
BT_MESH_PUB_TRANSMIT_INT(pub->retransmit)); BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));