From 7e8f9afee524241e161af47749150c84ed7ee80c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 22 Nov 2017 18:16:42 +0200 Subject: [PATCH] Bluetooth: Mesh: Add support for Health Period messages Add support for sending Health Period messages, as well as commands to use these new APIs from the shell. Signed-off-by: Johan Hedberg --- include/bluetooth/mesh/health_cli.h | 6 ++ subsys/bluetooth/host/mesh/health_cli.c | 115 ++++++++++++++++++++++++ subsys/bluetooth/host/mesh/shell.c | 61 +++++++++++++ 3 files changed, 182 insertions(+) diff --git a/include/bluetooth/mesh/health_cli.h b/include/bluetooth/mesh/health_cli.h index 113718ebfc2..41c5e9656e4 100644 --- a/include/bluetooth/mesh/health_cli.h +++ b/include/bluetooth/mesh/health_cli.h @@ -50,6 +50,12 @@ int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx, u16_t cid, u8_t test_id, u8_t *faults, size_t *fault_count); +int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx, + u8_t *divisor); + +int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx, + u8_t divisor, u8_t *updated_divisor); + s32_t bt_mesh_health_cli_timeout_get(void); void bt_mesh_health_cli_timeout_set(s32_t timeout); diff --git a/subsys/bluetooth/host/mesh/health_cli.c b/subsys/bluetooth/host/mesh/health_cli.c index 8c146484508..02c5a9c7d44 100644 --- a/subsys/bluetooth/host/mesh/health_cli.c +++ b/subsys/bluetooth/host/mesh/health_cli.c @@ -107,9 +107,36 @@ static void health_current_status(struct bt_mesh_model *model, cli->current_status(cli, ctx->addr, test_id, cid, buf->data, buf->len); } +struct health_period_param { + u8_t *divisor; +}; + +static void health_period_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct health_period_param *param; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, + bt_hex(buf->data, buf->len)); + + if (health_cli->op_pending != OP_HEALTH_PERIOD_STATUS) { + BT_WARN("Unexpected Health Period Status message"); + return; + } + + param = health_cli->op_param; + + *param->divisor = net_buf_simple_pull_u8(buf); + + k_sem_give(&health_cli->op_sync); +} + const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { { OP_HEALTH_FAULT_STATUS, 3, health_fault_status }, { OP_HEALTH_CURRENT_STATUS, 3, health_current_status }, + { OP_HEALTH_PERIOD_STATUS, 1, health_period_status }, BT_MESH_MODEL_OP_END, }; @@ -128,6 +155,94 @@ static int check_cli(void) return 0; } +int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx, + u8_t *divisor) +{ + struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 0 + 4); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = app_idx, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct health_period_param param = { + .divisor = divisor, + }; + int err; + + err = check_cli(); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_GET); + + err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + return err; + } + + health_cli->op_param = ¶m; + health_cli->op_pending = OP_HEALTH_PERIOD_STATUS; + + err = k_sem_take(&health_cli->op_sync, msg_timeout); + + health_cli->op_pending = 0; + health_cli->op_param = NULL; + + return err; +} + +int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx, + u8_t divisor, u8_t *updated_divisor) +{ + struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 1 + 4); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = app_idx, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct health_period_param param = { + .divisor = updated_divisor, + }; + int err; + + err = check_cli(); + if (err) { + return err; + } + + if (updated_divisor) { + bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_SET); + } else { + bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_SET_UNREL); + } + + net_buf_simple_add_u8(msg, divisor); + + err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + return err; + } + + if (!updated_divisor) { + return 0; + } + + health_cli->op_param = ¶m; + health_cli->op_pending = OP_HEALTH_PERIOD_STATUS; + + err = k_sem_take(&health_cli->op_sync, msg_timeout); + + health_cli->op_pending = 0; + health_cli->op_param = NULL; + + return err; +} + int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx, u16_t cid, u8_t test_id, u8_t *faults, size_t *fault_count) diff --git a/subsys/bluetooth/host/mesh/shell.c b/subsys/bluetooth/host/mesh/shell.c index d7597bda738..75632fcfef1 100644 --- a/subsys/bluetooth/host/mesh/shell.c +++ b/subsys/bluetooth/host/mesh/shell.c @@ -1339,6 +1339,64 @@ static int cmd_fault_test_unack(int argc, char *argv[]) return 0; } +static int cmd_period_get(int argc, char *argv[]) +{ + u8_t divisor; + int err; + + err = bt_mesh_health_period_get(net.net_idx, net.dst, net.app_idx, + &divisor); + if (err) { + printk("Failed to send Health Period Get (err %d)\n", err); + } else { + printk("Health FastPeriodDivisor: %u\n", divisor); + } + + return 0; +} + +static int cmd_period_set(int argc, char *argv[]) +{ + u8_t divisor, updated_divisor; + int err; + + if (argc < 2) { + return -EINVAL; + } + + divisor = strtoul(argv[1], NULL, 0); + + err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx, + divisor, &updated_divisor); + if (err) { + printk("Failed to send Health Period Set (err %d)\n", err); + } else { + printk("Health FastPeriodDivisor: %u\n", updated_divisor); + } + + return 0; +} + +static int cmd_period_set_unack(int argc, char *argv[]) +{ + u8_t divisor; + int err; + + if (argc < 2) { + return -EINVAL; + } + + divisor = strtoul(argv[1], NULL, 0); + + err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx, + divisor, NULL); + if (err) { + printk("Failed to send Health Period Set (err %d)\n", err); + } + + return 0; +} + static int cmd_add_fault(int argc, char *argv[]) { u8_t fault_id; @@ -1460,6 +1518,9 @@ static const struct shell_cmd mesh_commands[] = { { "fault-clear-unack", cmd_fault_clear_unack, "Company ID>" }, { "fault-test", cmd_fault_test, " " }, { "fault-test-unack", cmd_fault_test_unack, " " }, + { "period-get", cmd_period_get, "" }, + { "period-set", cmd_period_set, "" }, + { "period-set-unack", cmd_period_set_unack, "" }, /* Health Server Model Operations */ { "add-fault", cmd_add_fault, "" },