From 54daae954e0462bc6aabff966f468d07c37494de Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Thu, 10 Aug 2023 11:40:37 +0200 Subject: [PATCH] Bluetooth: Mesh: alternate location publishing The Location model shall support model publication. When configured for publication, the Generic Location Server shall publish Generic Location Global Status messages if the server knows its global location or shall publish Generic Location Local Status messages if the server knows its local location. If configured for periodic publications, and both global and local locations are known, the Generic Location Server shall alternate between publishing its local and global locations in consecutive publish periods. Signed-off-by: Aleksandr Khromykh --- include/bluetooth/mesh/gen_loc_srv.h | 11 ++++- subsys/bluetooth/mesh/gen_loc_srv.c | 73 ++++++++++++++++------------ 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/include/bluetooth/mesh/gen_loc_srv.h b/include/bluetooth/mesh/gen_loc_srv.h index 7633e7dd2d6b..4ac571ff335a 100644 --- a/include/bluetooth/mesh/gen_loc_srv.h +++ b/include/bluetooth/mesh/gen_loc_srv.h @@ -131,8 +131,15 @@ struct bt_mesh_loc_srv { BT_MESH_MODEL_BUF_LEN(BT_MESH_LOC_OP_GLOBAL_STATUS, BT_MESH_LOC_MSG_LEN_GLOBAL_STATUS))]; - /** Current opcode being published. */ - uint16_t pub_op; + /** Location publishing state. */ + struct { + /** Global location is available for publishing. */ + uint8_t is_global_available: 1; + /** Local location is available for publishing. */ + uint8_t is_local_available: 1; + /** The last published location over periodic publication. */ + uint8_t was_last_local: 1; + } pub_state; /** Pointer to a handler structure. */ const struct bt_mesh_loc_srv_handlers *const handlers; }; diff --git a/subsys/bluetooth/mesh/gen_loc_srv.c b/subsys/bluetooth/mesh/gen_loc_srv.c index 9a2467a07e70..42d0d76c215d 100644 --- a/subsys/bluetooth/mesh/gen_loc_srv.c +++ b/subsys/bluetooth/mesh/gen_loc_srv.c @@ -24,11 +24,6 @@ .is_mobile = false, .time_delta = 0, .precision_mm = 4096000, \ } -static bool pub_in_progress(struct bt_mesh_loc_srv *srv) -{ - return k_work_delayable_is_pending(&srv->pub.timer); -} - /* Global location */ static void rsp_global(struct bt_mesh_model *model, @@ -64,6 +59,7 @@ static int global_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct bt_mesh_loc_global global; bt_mesh_loc_global_decode(buf, &global); + srv->pub_state.is_global_available = 1; srv->handlers->global_set(srv, ctx, &global); @@ -71,10 +67,7 @@ static int global_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, rsp_global(model, ctx, &global); } - if (!pub_in_progress(srv) || - srv->pub_op != BT_MESH_LOC_OP_GLOBAL_STATUS) { - (void)bt_mesh_loc_srv_global_pub(srv, NULL, &global); - } + (void)bt_mesh_loc_srv_global_pub(srv, NULL, &global); return 0; } @@ -128,6 +121,7 @@ static int local_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct bt_mesh_loc_local local; bt_mesh_loc_local_decode(buf, &local); + srv->pub_state.is_local_available = 1; srv->handlers->local_set(srv, ctx, &local); @@ -135,10 +129,7 @@ static int local_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, rsp_local(model, ctx, &local); } - if (!pub_in_progress(srv) || - srv->pub_op != BT_MESH_LOC_OP_LOCAL_STATUS) { - (void)bt_mesh_loc_srv_local_pub(srv, NULL, &local); - } + (void)bt_mesh_loc_srv_local_pub(srv, NULL, &local); return 0; } @@ -194,30 +185,50 @@ const struct bt_mesh_model_op _bt_mesh_loc_setup_srv_op[] = { BT_MESH_MODEL_OP_END }; -static int update_handler(struct bt_mesh_model *model) +static void global_update_handler(struct bt_mesh_loc_srv *srv) { - struct bt_mesh_loc_srv *srv = model->user_data; + struct bt_mesh_loc_global loc = LOC_GLOBAL_DEFAULT; - if (srv->pub_op == BT_MESH_LOC_OP_GLOBAL_STATUS) { - struct bt_mesh_loc_global loc = LOC_GLOBAL_DEFAULT; + srv->pub_state.was_last_local = 0; + srv->handlers->global_get(srv, NULL, &loc); - srv->handlers->global_get(srv, NULL, &loc); + bt_mesh_model_msg_init(srv->pub.msg, BT_MESH_LOC_OP_GLOBAL_STATUS); + bt_mesh_loc_global_encode(srv->pub.msg, &loc); +} - bt_mesh_model_msg_init(srv->pub.msg, - BT_MESH_LOC_OP_GLOBAL_STATUS); - bt_mesh_loc_global_encode(srv->pub.msg, &loc); - } else if (srv->pub_op == BT_MESH_LOC_OP_LOCAL_STATUS) { - struct bt_mesh_loc_local loc = LOC_LOCAL_DEFAULT; +static void local_update_handler(struct bt_mesh_loc_srv *srv) +{ + struct bt_mesh_loc_local loc = LOC_LOCAL_DEFAULT; - srv->handlers->local_get(srv, NULL, &loc); + srv->pub_state.was_last_local = 1; + srv->handlers->local_get(srv, NULL, &loc); - bt_mesh_model_msg_init(srv->pub.msg, - BT_MESH_LOC_OP_LOCAL_STATUS); - bt_mesh_loc_local_encode(srv->pub.msg, &loc); - } else { + bt_mesh_model_msg_init(srv->pub.msg, BT_MESH_LOC_OP_LOCAL_STATUS); + bt_mesh_loc_local_encode(srv->pub.msg, &loc); +} + +static int update_handler(struct bt_mesh_model *model) +{ + struct bt_mesh_loc_srv *srv = model->user_data; + + if (!srv->pub_state.is_local_available && !srv->pub_state.is_global_available) { return -EINVAL; } + if (!srv->pub_state.was_last_local) { + if (!!srv->pub_state.is_local_available) { + local_update_handler(srv); + } else { + global_update_handler(srv); + } + } else { + if (!!srv->pub_state.is_global_available) { + global_update_handler(srv); + } else { + local_update_handler(srv); + } + } + return 0; } @@ -225,6 +236,7 @@ static int bt_mesh_loc_srv_init(struct bt_mesh_model *model) { struct bt_mesh_loc_srv *srv = model->user_data; + memset(&srv->pub_state, 0, sizeof(srv->pub_state)); srv->model = model; srv->pub.msg = &srv->pub_buf; srv->pub.update = update_handler; @@ -236,6 +248,9 @@ static int bt_mesh_loc_srv_init(struct bt_mesh_model *model) static void bt_mesh_loc_srv_reset(struct bt_mesh_model *model) { + struct bt_mesh_loc_srv *srv = model->user_data; + + memset(&srv->pub_state, 0, sizeof(srv->pub_state)); net_buf_simple_reset(model->pub->msg); } @@ -253,7 +268,6 @@ int bt_mesh_loc_srv_global_pub(struct bt_mesh_loc_srv *srv, bt_mesh_model_msg_init(&msg, BT_MESH_LOC_OP_GLOBAL_STATUS); bt_mesh_loc_global_encode(&msg, global); - srv->pub_op = BT_MESH_LOC_OP_GLOBAL_STATUS; return bt_mesh_msg_send(srv->model, ctx, &msg); } @@ -267,7 +281,6 @@ int bt_mesh_loc_srv_local_pub(struct bt_mesh_loc_srv *srv, bt_mesh_model_msg_init(&msg, BT_MESH_LOC_OP_LOCAL_STATUS); bt_mesh_loc_local_encode(&msg, local); - srv->pub_op = BT_MESH_LOC_OP_LOCAL_STATUS; return bt_mesh_msg_send(srv->model, ctx, &msg); }