Bluetooth: Mesh: Fix publication period measurement
Period measurement should be started right after a message is updated. That is because `struct bt_mesh_send_cb.start` callback is called from the advertiser thread which is not necessary to be scheduled immeditely and a user may see some delays between update handler calls. The publication timer still needs to be scheduled after a message being actually sent out to the air so that access layer doesn't overflow the advertiser's buffer. To achieve some specific use cases, where a published message needs to be retransmitted with 50ms interval, a user has to switch off network retransmissions to make the legacy advertiser sleep for the shortest possible time. Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
This commit is contained in:
parent
188c8c47a8
commit
1f9c606f95
|
@ -114,17 +114,33 @@ int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
|||
static int32_t next_period(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
uint32_t elapsed, period;
|
||||
|
||||
period = bt_mesh_model_pub_period_get(mod);
|
||||
if (!period) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t period = 0;
|
||||
uint32_t elapsed;
|
||||
|
||||
elapsed = k_uptime_get_32() - pub->period_start;
|
||||
|
||||
BT_DBG("Publishing took %ums", elapsed);
|
||||
|
||||
if (mod->pub->count) {
|
||||
/* If a message is to be retransmitted, period should include time since the first
|
||||
* publication until the last publication.
|
||||
*/
|
||||
period = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
|
||||
period *= BT_MESH_PUB_MSG_NUM(mod->pub);
|
||||
|
||||
if (period && elapsed >= period) {
|
||||
BT_WARN("Retransmission interval is too short");
|
||||
/* Return smallest positive number since 0 means disabled */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!period) {
|
||||
period = bt_mesh_model_pub_period_get(mod);
|
||||
if (!period) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (elapsed >= period) {
|
||||
BT_WARN("Publication sending took longer than the period");
|
||||
/* Return smallest positive number since 0 means disabled */
|
||||
|
@ -139,13 +155,9 @@ static void publish_sent(int err, void *user_data)
|
|||
struct bt_mesh_model *mod = user_data;
|
||||
int32_t delay;
|
||||
|
||||
BT_DBG("err %d", err);
|
||||
BT_DBG("err %d, time %u", err, k_uptime_get_32());
|
||||
|
||||
if (mod->pub->count) {
|
||||
delay = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
|
||||
} else {
|
||||
delay = next_period(mod);
|
||||
}
|
||||
delay = next_period(mod);
|
||||
|
||||
if (delay) {
|
||||
BT_DBG("Publishing next time in %dms", delay);
|
||||
|
@ -158,19 +170,11 @@ static void publish_sent(int err, void *user_data)
|
|||
|
||||
static void publish_start(uint16_t duration, int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
|
||||
if (err) {
|
||||
BT_ERR("Failed to publish: err %d", err);
|
||||
publish_sent(err, user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the timestamp for the beginning of a new period */
|
||||
if (pub->count == BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit)) {
|
||||
pub->period_start = k_uptime_get_32();
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bt_mesh_send_cb pub_sent_cb = {
|
||||
|
@ -209,11 +213,13 @@ static int pub_period_start(struct bt_mesh_model_pub *pub)
|
|||
}
|
||||
|
||||
err = pub->update(pub->mod);
|
||||
|
||||
pub->period_start = k_uptime_get_32();
|
||||
|
||||
if (err) {
|
||||
/* Skip this publish attempt. */
|
||||
BT_DBG("Update failed, skipping publish (err: %d)", err);
|
||||
pub->count = 0;
|
||||
pub->period_start = k_uptime_get_32();
|
||||
publish_sent(err, pub->mod);
|
||||
return err;
|
||||
}
|
||||
|
@ -237,7 +243,7 @@ static void mod_publish(struct k_work *work)
|
|||
return;
|
||||
}
|
||||
|
||||
BT_DBG("");
|
||||
BT_DBG("%u", k_uptime_get_32());
|
||||
|
||||
if (pub->count) {
|
||||
pub->count--;
|
||||
|
@ -261,10 +267,6 @@ static void mod_publish(struct k_work *work)
|
|||
err = publish_transmit(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Failed to publish (err %d)", err);
|
||||
if (pub->count == BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit)) {
|
||||
pub->period_start = k_uptime_get_32();
|
||||
}
|
||||
|
||||
publish_sent(err, pub->mod);
|
||||
}
|
||||
}
|
||||
|
@ -776,6 +778,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
|||
|
||||
/* Account for initial transmission */
|
||||
pub->count = BT_MESH_PUB_MSG_TOTAL(pub);
|
||||
pub->period_start = k_uptime_get_32();
|
||||
|
||||
BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
|
||||
BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));
|
||||
|
|
Loading…
Reference in a new issue