Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth: Mesh: do not send time status often than 30 seconds #11997

Merged
merged 2 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;

omkar3141 marked this conversation as resolved.
Show resolved Hide resolved
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
39 changes: 39 additions & 0 deletions tests/subsys/bluetooth/mesh/time_model/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(bt_mesh_time_model_test)

target_include_directories(app PUBLIC
${ZEPHYR_NRF_MODULE_DIR}/subsys/bluetooth/mesh
${ZEPHYR_BASE}/subsys/bluetooth
../common
)

FILE(GLOB app_sources src/*.c)

target_sources(app PRIVATE
${app_sources}
${ZEPHYR_NRF_MODULE_DIR}/subsys/bluetooth/mesh/time_srv.c
${ZEPHYR_NRF_MODULE_DIR}/subsys/bluetooth/mesh/time.c
${ZEPHYR_NRF_MODULE_DIR}/subsys/bluetooth/mesh/time_util.c
)

target_compile_options(app
PRIVATE
-DCONFIG_BT_MESH_MODEL_KEY_COUNT=5
-DCONFIG_BT_MESH_MODEL_GROUP_COUNT=5
-DCONFIG_BT_LOG_LEVEL=0
-DCONFIG_BT_MESH_TIME_SRV=1
-DCONFIG_BT_MESH_TIME_SRV_CLOCK_ACCURACY=500
-DCONFIG_BT_MESH_TIME_MESH_HOP_UNCERTAINTY=30
-DCONFIG_BT_MESH_USES_TINYCRYPT
)

zephyr_ld_options(
${LINKERFLAGPREFIX},--allow-multiple-definition
)
12 changes: 12 additions & 0 deletions tests/subsys/bluetooth/mesh/time_model/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

# Ztest configuration
CONFIG_ZTEST=y
CONFIG_ZTEST_NEW_API=y
CONFIG_TEST_RANDOM_GENERATOR=y

CONFIG_NET_BUF=y
Loading
Loading