Skip to content

Commit

Permalink
Bluetooth: Mesh: do not send time status often than 30 seconds
Browse files Browse the repository at this point in the history
Commit adds restriction for the Time model
to not send Time Status more often than 30 seconds
if this is aresult of state update after Time Set or
Time Status commands.

Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
  • Loading branch information
alxelax committed Aug 14, 2023
1 parent 1547339 commit 533638e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 5 deletions.
4 changes: 4 additions & 0 deletions include/bluetooth/mesh/time_srv.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ struct bt_mesh_time_srv_data {
struct bt_mesh_time_tai_utc_change tai_utc_change;
/* The Time Role of the Server instance */
enum bt_mesh_time_role role;
/* The timestamp of the last published Time Status. */
int64_t timestamp;
};

/** Time Server instance.
Expand All @@ -103,6 +105,8 @@ struct bt_mesh_time_srv {
struct bt_mesh_msg_ack_ctx ack_ctx;
/** Model state structure */
struct bt_mesh_time_srv_data data;
/** Delayable work to randomize status relaying. */
struct k_work_delayable status_delay;

/** @brief Update callback.
*
Expand Down
52 changes: 47 additions & 5 deletions subsys/bluetooth/mesh/time_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "time_util.h"

#define SUBSEC_STEPS 256U
#define STATUS_INTERVAL_MIN 30000ll

struct bt_mesh_time_srv_settings_data {
uint8_t role;
Expand Down Expand Up @@ -186,6 +187,14 @@ static int send_time_status(struct bt_mesh_model *model,
return bt_mesh_msg_send(model, ctx, &msg);
}

static void time_status_send_after_delay(struct k_work *work)
{
struct k_work_delayable *tmp = k_work_delayable_from_work(work);
struct bt_mesh_time_srv *srv = CONTAINER_OF(tmp, struct bt_mesh_time_srv, status_delay);

(void)bt_mesh_time_srv_time_status_send(srv, NULL);
}

static int handle_time_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
Expand Down Expand Up @@ -217,7 +226,22 @@ static int handle_time_status(struct bt_mesh_model *model, struct bt_mesh_msg_ct
}

if (srv->data.role == BT_MESH_TIME_RELAY) {
(void)bt_mesh_time_srv_time_status_send(srv, NULL);
/* The time server shouldn't send out statuses more often than every 30 seconds. */
if (srv->data.sync.uptime < (srv->data.timestamp + STATUS_INTERVAL_MIN)) {
return 0;
}

/* Random delay has been already scheduled. */
if (k_work_delayable_is_pending(&srv->status_delay)) {
return 0;
}

uint8_t rnd;

bt_rand(&rnd, sizeof(uint8_t));
rnd = 20 + rnd % 30;
srv->data.sync.status.uncertainty += rnd;
k_work_schedule(&srv->status_delay, K_MSEC(rnd));
}

return 0;
Expand All @@ -243,6 +267,9 @@ static int handle_time_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *
srv->time_update_cb(srv, ctx, BT_MESH_TIME_SRV_SET_UPDATE);
}

/* publish state changing */
(void)bt_mesh_time_srv_time_status_send(srv, NULL);

send_time_status(model, ctx, srv->data.sync.uptime);

return 0;
Expand Down Expand Up @@ -387,18 +414,22 @@ static int bt_mesh_time_srv_init(struct bt_mesh_model *model)
struct bt_mesh_time_srv *srv = model->user_data;

srv->model = model;
srv->data.timestamp = -STATUS_INTERVAL_MIN;
net_buf_simple_init(srv->pub.msg, 0);

k_work_init_delayable(&srv->status_delay, time_status_send_after_delay);

return 0;
}

static void bt_mesh_time_srv_reset(struct bt_mesh_model *model)
{
struct bt_mesh_time_srv *srv = model->user_data;
struct bt_mesh_time_srv_data data = { 0 };
struct bt_mesh_time_srv_data data = { .timestamp = -STATUS_INTERVAL_MIN };

srv->data = data;
net_buf_simple_reset(srv->pub.msg);
(void)k_work_cancel_delayable(&srv->status_delay);

if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
(void)bt_mesh_model_data_store(srv->model, false, NULL, NULL,
Expand Down Expand Up @@ -452,18 +483,21 @@ int _bt_mesh_time_srv_update_handler(struct bt_mesh_model *model)
{
struct bt_mesh_time_srv *srv = model->user_data;
struct bt_mesh_time_status status;
int64_t uptime;
int err;

if (srv->data.role != BT_MESH_TIME_AUTHORITY &&
srv->data.role != BT_MESH_TIME_RELAY) {
return -EPERM;
}

err = bt_mesh_time_srv_status(srv, k_uptime_get(), &status);
uptime = k_uptime_get();
err = bt_mesh_time_srv_status(srv, uptime, &status);
if (err) {
return err;
}

srv->data.timestamp = uptime;
/* Account for delay in TX processing: */
status.uncertainty += CONFIG_BT_MESH_TIME_MESH_HOP_UNCERTAINTY;

Expand All @@ -476,7 +510,8 @@ int _bt_mesh_time_srv_update_handler(struct bt_mesh_model *model)
int bt_mesh_time_srv_time_status_send(struct bt_mesh_time_srv *srv,
struct bt_mesh_msg_ctx *ctx)
{
srv->model->pub->ttl = 0;
int64_t uptime = k_uptime_get();
int err;

/** Mesh Model Specification 5.3.1.2.2:
* The message (Time Status) may be sent as an unsolicited message at any time
Expand All @@ -486,7 +521,14 @@ int bt_mesh_time_srv_time_status_send(struct bt_mesh_time_srv *srv,
return -EOPNOTSUPP;
}

return send_time_status(srv->model, ctx, k_uptime_get());
srv->model->pub->ttl = 0;

err = send_time_status(srv->model, ctx, uptime);
if (!err) {
srv->data.timestamp = uptime;
}

return err;
}

int bt_mesh_time_srv_status(struct bt_mesh_time_srv *srv, uint64_t uptime,
Expand Down

0 comments on commit 533638e

Please sign in to comment.