Commit 70b0734b authored by Pavel Vasilyev's avatar Pavel Vasilyev Committed by Johan Hedberg
Browse files

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: default avatarPavel Vasilyev <pavel.vasilyev@nordicsemi.no>
parent f2e45d75
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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
===============

+41 −1
Original line number Diff line number Diff line
@@ -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.
+10 −1
Original line number Diff line number Diff line
@@ -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));