|
|
@@ -27,130 +27,112 @@
|
|
|
#include "foundation.h"
|
|
|
#include "mesh_common.h"
|
|
|
|
|
|
-#define HEALTH_TEST_STANDARD 0x00
|
|
|
+#include "btc_ble_mesh_health_model.h"
|
|
|
|
|
|
-/* Maximum message length is 384 in BLE Mesh. Here for health fault status,
|
|
|
- * due to 1 octet opcode and 4 octets TransMIC, 379 octets can be used to
|
|
|
- * store health fault status.
|
|
|
- */
|
|
|
-#define HEALTH_FAULT_MAX_LEN 379
|
|
|
+#define HEALTH_TEST_STANDARD 0x00
|
|
|
+
|
|
|
+#define HEALTH_NO_FAULT 0x00
|
|
|
|
|
|
/* Health Server context of the primary element */
|
|
|
struct bt_mesh_health_srv *health_srv;
|
|
|
|
|
|
-static void health_get_registered(struct bt_mesh_model *mod,
|
|
|
- u16_t company_id,
|
|
|
- struct net_buf_simple *msg)
|
|
|
-{
|
|
|
- struct bt_mesh_health_srv *srv = mod->user_data;
|
|
|
- u8_t *test_id;
|
|
|
-
|
|
|
- BT_DBG("Company ID 0x%04x", company_id);
|
|
|
-
|
|
|
- if (!srv) {
|
|
|
- BT_ERR("%s, No Health Server context provided", __func__);
|
|
|
- return;
|
|
|
- }
|
|
|
+/**
|
|
|
+ * When an Element receives a Health Fault Get, or a Health Fault Test, or
|
|
|
+ * a Health Fault Test Unacknowledged, or a Health Fault Clear, or a Health
|
|
|
+ * Fault Clear Unacknowledged message that is not successfully processed
|
|
|
+ * (i.e. the Company ID field that does not identify any Health Fault state
|
|
|
+ * present in the node), it shall ignore the message.
|
|
|
+ * The Health Fault state is identified by Company ID and may be present in
|
|
|
+ * the node for more than one Company ID.
|
|
|
+ */
|
|
|
|
|
|
- bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS);
|
|
|
+static u8_t health_get_curr_fault_count(struct bt_mesh_model *model)
|
|
|
+{
|
|
|
+ struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
+ u8_t count = 0;
|
|
|
+ size_t i;
|
|
|
|
|
|
- test_id = net_buf_simple_add(msg, 1);
|
|
|
- net_buf_simple_add_le16(msg, company_id);
|
|
|
-
|
|
|
- if (srv->cb && srv->cb->fault_get_reg) {
|
|
|
- u8_t fault_count = net_buf_simple_tailroom(msg) - 4;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = srv->cb->fault_get_reg(mod, company_id, test_id,
|
|
|
- net_buf_simple_tail(msg),
|
|
|
- &fault_count);
|
|
|
- if (err) {
|
|
|
- BT_ERR("%s, Failed to get faults (err %d)", __func__, err);
|
|
|
- *test_id = HEALTH_TEST_STANDARD;
|
|
|
- } else {
|
|
|
- net_buf_simple_add(msg, fault_count);
|
|
|
+ for (i = 0U; i < ARRAY_SIZE(srv->test.curr_faults); i++) {
|
|
|
+ if (srv->test.curr_faults[i] != HEALTH_NO_FAULT) {
|
|
|
+ count++;
|
|
|
}
|
|
|
- } else {
|
|
|
- BT_WARN("No callback for getting faults");
|
|
|
- *test_id = HEALTH_TEST_STANDARD;
|
|
|
}
|
|
|
+
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
-static size_t health_get_current(struct bt_mesh_model *mod,
|
|
|
- struct net_buf_simple *msg)
|
|
|
+static void health_get_fault_value(struct bt_mesh_model *model,
|
|
|
+ struct net_buf_simple *msg,
|
|
|
+ bool current)
|
|
|
{
|
|
|
- struct bt_mesh_health_srv *srv = mod->user_data;
|
|
|
- const struct bt_mesh_comp *comp;
|
|
|
- u8_t *test_id, *company_ptr;
|
|
|
- u16_t company_id;
|
|
|
- u8_t fault_count;
|
|
|
- int err;
|
|
|
+ struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
+ size_t array_size;
|
|
|
+ size_t i;
|
|
|
|
|
|
- if (!srv) {
|
|
|
- BT_ERR("%s, No Health Server context provided", __func__);
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ array_size = current ? ARRAY_SIZE(srv->test.curr_faults) : ARRAY_SIZE(srv->test.reg_faults);
|
|
|
|
|
|
- bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS);
|
|
|
+ for (i = 0U; i < array_size; i++) {
|
|
|
+ if (net_buf_simple_tailroom(msg) == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- test_id = net_buf_simple_add(msg, 1);
|
|
|
- company_ptr = net_buf_simple_add(msg, sizeof(company_id));
|
|
|
- comp = bt_mesh_comp_get();
|
|
|
-
|
|
|
- if (srv->cb && srv->cb->fault_get_cur) {
|
|
|
- fault_count = net_buf_simple_tailroom(msg);
|
|
|
- err = srv->cb->fault_get_cur(mod, test_id, &company_id,
|
|
|
- net_buf_simple_tail(msg),
|
|
|
- &fault_count);
|
|
|
- if (err) {
|
|
|
- BT_ERR("%s, Failed to get faults (err %d)", __func__, err);
|
|
|
- sys_put_le16(comp->cid, company_ptr);
|
|
|
- *test_id = HEALTH_TEST_STANDARD;
|
|
|
- fault_count = 0U;
|
|
|
- } else {
|
|
|
- sys_put_le16(company_id, company_ptr);
|
|
|
- net_buf_simple_add(msg, fault_count);
|
|
|
+ u8_t fault = current ? srv->test.curr_faults[i] : srv->test.reg_faults[i];
|
|
|
+ if (fault != HEALTH_NO_FAULT) {
|
|
|
+ net_buf_simple_add_u8(msg, fault);
|
|
|
}
|
|
|
- } else {
|
|
|
- BT_WARN("No callback for getting faults");
|
|
|
- sys_put_le16(comp->cid, company_ptr);
|
|
|
- *test_id = HEALTH_TEST_STANDARD;
|
|
|
- fault_count = 0U;
|
|
|
}
|
|
|
-
|
|
|
- return fault_count;
|
|
|
}
|
|
|
|
|
|
-static void health_fault_get(struct bt_mesh_model *model,
|
|
|
- struct bt_mesh_msg_ctx *ctx,
|
|
|
- struct net_buf_simple *buf)
|
|
|
+static bool health_is_test_id_exist(struct bt_mesh_model *model, u8_t test_id)
|
|
|
{
|
|
|
- struct net_buf_simple *sdu = NULL;
|
|
|
- u16_t company_id;
|
|
|
+ struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
+ u8_t i;
|
|
|
|
|
|
- company_id = net_buf_simple_pull_le16(buf);
|
|
|
+ for (i = 0U; i < srv->test.id_count; i++) {
|
|
|
+ if (srv->test.test_ids[i] == test_id) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- BT_DBG("company_id 0x%04x", company_id);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static int health_send_fault_status(struct bt_mesh_model *model,
|
|
|
+ struct bt_mesh_msg_ctx *ctx)
|
|
|
+{
|
|
|
+ struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
+ struct net_buf_simple *msg = NULL;
|
|
|
+ int err;
|
|
|
|
|
|
- sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, HEALTH_FAULT_MAX_LEN));
|
|
|
- if (!sdu) {
|
|
|
+ msg = bt_mesh_alloc_buf(4 + ARRAY_SIZE(srv->test.reg_faults) + 4);
|
|
|
+ if (!msg) {
|
|
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
|
|
- return;
|
|
|
+ return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- health_get_registered(model, company_id, sdu);
|
|
|
+ bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS);
|
|
|
+ net_buf_simple_add_u8(msg, srv->test.prev_test_id);
|
|
|
+ net_buf_simple_add_le16(msg, srv->test.company_id);
|
|
|
+ if (ctx->recv_op != OP_HEALTH_FAULT_CLEAR) {
|
|
|
+ /**
|
|
|
+ * For Health Fault Clear, the FaultArray field in Health Fault Status
|
|
|
+ * shall be empty.
|
|
|
+ */
|
|
|
+ health_get_fault_value(model, msg, false);
|
|
|
+ }
|
|
|
|
|
|
- if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
|
|
- BT_ERR("%s, Unable to send Health Current Status", __func__);
|
|
|
+ err = bt_mesh_model_send(model, ctx, msg, NULL, NULL);
|
|
|
+ if (err) {
|
|
|
+ BT_ERR("%s, Failed to send Health Fault Status response", __func__);
|
|
|
}
|
|
|
|
|
|
- bt_mesh_free_buf(sdu);
|
|
|
- return;
|
|
|
+ bt_mesh_free_buf(msg);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
-static void health_fault_clear_unrel(struct bt_mesh_model *model,
|
|
|
- struct bt_mesh_msg_ctx *ctx,
|
|
|
- struct net_buf_simple *buf)
|
|
|
+static void health_fault_get(struct bt_mesh_model *model,
|
|
|
+ struct bt_mesh_msg_ctx *ctx,
|
|
|
+ struct net_buf_simple *buf)
|
|
|
{
|
|
|
struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
u16_t company_id;
|
|
|
@@ -161,12 +143,14 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model,
|
|
|
}
|
|
|
|
|
|
company_id = net_buf_simple_pull_le16(buf);
|
|
|
+ if (company_id != srv->test.company_id) {
|
|
|
+ BT_ERR("%s, Unknown Company ID 0x%04x", __func__, company_id);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
BT_DBG("company_id 0x%04x", company_id);
|
|
|
|
|
|
- if (srv->cb && srv->cb->fault_clear) {
|
|
|
- srv->cb->fault_clear(model, company_id);
|
|
|
- }
|
|
|
+ health_send_fault_status(model, ctx);
|
|
|
}
|
|
|
|
|
|
static void health_fault_clear(struct bt_mesh_model *model,
|
|
|
@@ -174,7 +158,6 @@ static void health_fault_clear(struct bt_mesh_model *model,
|
|
|
struct net_buf_simple *buf)
|
|
|
{
|
|
|
struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
- struct net_buf_simple *sdu = NULL;
|
|
|
u16_t company_id;
|
|
|
|
|
|
if (!srv) {
|
|
|
@@ -183,49 +166,21 @@ static void health_fault_clear(struct bt_mesh_model *model,
|
|
|
}
|
|
|
|
|
|
company_id = net_buf_simple_pull_le16(buf);
|
|
|
-
|
|
|
- BT_DBG("company_id 0x%04x", company_id);
|
|
|
-
|
|
|
- if (srv->cb && srv->cb->fault_clear) {
|
|
|
- srv->cb->fault_clear(model, company_id);
|
|
|
- }
|
|
|
-
|
|
|
- sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, HEALTH_FAULT_MAX_LEN));
|
|
|
- if (!sdu) {
|
|
|
- BT_ERR("%s, Failed to allocate memory", __func__);
|
|
|
+ if (company_id != srv->test.company_id) {
|
|
|
+ BT_ERR("%s, Unknown Company ID 0x%04x", __func__, company_id);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- health_get_registered(model, company_id, sdu);
|
|
|
-
|
|
|
- if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
|
|
- BT_ERR("%s, Unable to send Health Current Status", __func__);
|
|
|
- }
|
|
|
+ BT_DBG("company_id 0x%04x", company_id);
|
|
|
|
|
|
- bt_mesh_free_buf(sdu);
|
|
|
- return;
|
|
|
-}
|
|
|
+ memset(srv->test.reg_faults, HEALTH_NO_FAULT, ARRAY_SIZE(srv->test.reg_faults));
|
|
|
|
|
|
-static void health_fault_test_unrel(struct bt_mesh_model *model,
|
|
|
- struct bt_mesh_msg_ctx *ctx,
|
|
|
- struct net_buf_simple *buf)
|
|
|
-{
|
|
|
- struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
- u16_t company_id;
|
|
|
- u8_t test_id;
|
|
|
-
|
|
|
- if (!srv) {
|
|
|
- BT_ERR("%s, No Health Server context provided", __func__);
|
|
|
- return;
|
|
|
+ if (srv->cb.fault_clear) {
|
|
|
+ srv->cb.fault_clear(model, company_id);
|
|
|
}
|
|
|
|
|
|
- test_id = net_buf_simple_pull_u8(buf);
|
|
|
- company_id = net_buf_simple_pull_le16(buf);
|
|
|
-
|
|
|
- BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
|
|
|
-
|
|
|
- if (srv->cb && srv->cb->fault_test) {
|
|
|
- srv->cb->fault_test(model, test_id, company_id);
|
|
|
+ if (ctx->recv_op == OP_HEALTH_FAULT_CLEAR) {
|
|
|
+ health_send_fault_status(model, ctx);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -234,7 +189,6 @@ static void health_fault_test(struct bt_mesh_model *model,
|
|
|
struct net_buf_simple *buf)
|
|
|
{
|
|
|
struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
- struct net_buf_simple *sdu = NULL;
|
|
|
u16_t company_id;
|
|
|
u8_t test_id;
|
|
|
|
|
|
@@ -246,34 +200,28 @@ static void health_fault_test(struct bt_mesh_model *model,
|
|
|
}
|
|
|
|
|
|
test_id = net_buf_simple_pull_u8(buf);
|
|
|
- company_id = net_buf_simple_pull_le16(buf);
|
|
|
-
|
|
|
- BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
|
|
|
-
|
|
|
- if (srv->cb && srv->cb->fault_test) {
|
|
|
- int err;
|
|
|
-
|
|
|
- err = srv->cb->fault_test(model, test_id, company_id);
|
|
|
- if (err) {
|
|
|
- BT_WARN("Running fault test failed with err %d", err);
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (health_is_test_id_exist(model, test_id) == false) {
|
|
|
+ BT_ERR("%s, Unknown Test ID 0x%02x", __func__, test_id);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, HEALTH_FAULT_MAX_LEN));
|
|
|
- if (!sdu) {
|
|
|
- BT_ERR("%s, Failed to allocate memory", __func__);
|
|
|
+ company_id = net_buf_simple_pull_le16(buf);
|
|
|
+ if (company_id != srv->test.company_id) {
|
|
|
+ BT_ERR("%s, Unknown Company ID 0x%04x", __func__, company_id);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- health_get_registered(model, company_id, sdu);
|
|
|
+ BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
|
|
|
+
|
|
|
+ srv->test.prev_test_id = test_id;
|
|
|
|
|
|
- if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
|
|
- BT_ERR("%s, Unable to send Health Current Status", __func__);
|
|
|
+ if (srv->cb.fault_test) {
|
|
|
+ srv->cb.fault_test(model, test_id, company_id);
|
|
|
}
|
|
|
|
|
|
- bt_mesh_free_buf(sdu);
|
|
|
- return;
|
|
|
+ if (ctx->recv_op == OP_HEALTH_FAULT_TEST) {
|
|
|
+ health_send_fault_status(model, ctx);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void send_attention_status(struct bt_mesh_model *model,
|
|
|
@@ -293,7 +241,6 @@ static void send_attention_status(struct bt_mesh_model *model,
|
|
|
BT_DBG("%u second%s", time, (time == 1U) ? "" : "s");
|
|
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_ATTENTION_STATUS);
|
|
|
-
|
|
|
net_buf_simple_add_u8(&msg, time);
|
|
|
|
|
|
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
|
|
|
@@ -310,9 +257,9 @@ static void attention_get(struct bt_mesh_model *model,
|
|
|
send_attention_status(model, ctx);
|
|
|
}
|
|
|
|
|
|
-static void attention_set_unrel(struct bt_mesh_model *model,
|
|
|
- struct bt_mesh_msg_ctx *ctx,
|
|
|
- struct net_buf_simple *buf)
|
|
|
+static void health_set_attention(struct bt_mesh_model *model,
|
|
|
+ struct bt_mesh_msg_ctx *ctx,
|
|
|
+ struct net_buf_simple *buf)
|
|
|
{
|
|
|
u8_t time;
|
|
|
|
|
|
@@ -329,9 +276,11 @@ static void attention_set(struct bt_mesh_model *model,
|
|
|
{
|
|
|
BT_DBG("%s", __func__);
|
|
|
|
|
|
- attention_set_unrel(model, ctx, buf);
|
|
|
+ health_set_attention(model, ctx, buf);
|
|
|
|
|
|
- send_attention_status(model, ctx);
|
|
|
+ if (ctx->recv_op == OP_ATTENTION_SET) {
|
|
|
+ send_attention_status(model, ctx);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void send_health_period_status(struct bt_mesh_model *model,
|
|
|
@@ -341,7 +290,6 @@ static void send_health_period_status(struct bt_mesh_model *model,
|
|
|
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
|
|
|
|
|
|
bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_STATUS);
|
|
|
-
|
|
|
net_buf_simple_add_u8(&msg, model->pub->period_div);
|
|
|
|
|
|
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
|
|
|
@@ -358,9 +306,9 @@ static void health_period_get(struct bt_mesh_model *model,
|
|
|
send_health_period_status(model, ctx);
|
|
|
}
|
|
|
|
|
|
-static void health_period_set_unrel(struct bt_mesh_model *model,
|
|
|
- struct bt_mesh_msg_ctx *ctx,
|
|
|
- struct net_buf_simple *buf)
|
|
|
+static void health_set_period(struct bt_mesh_model *model,
|
|
|
+ struct bt_mesh_msg_ctx *ctx,
|
|
|
+ struct net_buf_simple *buf)
|
|
|
{
|
|
|
u8_t period;
|
|
|
|
|
|
@@ -381,34 +329,64 @@ static void health_period_set(struct bt_mesh_model *model,
|
|
|
{
|
|
|
BT_DBG("%s", __func__);
|
|
|
|
|
|
- health_period_set_unrel(model, ctx, buf);
|
|
|
+ health_set_period(model, ctx, buf);
|
|
|
|
|
|
- send_health_period_status(model, ctx);
|
|
|
+ if (ctx->recv_op == OP_HEALTH_PERIOD_SET) {
|
|
|
+ send_health_period_status(model, ctx);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const struct bt_mesh_model_op bt_mesh_health_srv_op[] = {
|
|
|
- { OP_HEALTH_FAULT_GET, 2, health_fault_get },
|
|
|
+ { OP_HEALTH_FAULT_GET, 2, health_fault_get },
|
|
|
{ OP_HEALTH_FAULT_CLEAR, 2, health_fault_clear },
|
|
|
- { OP_HEALTH_FAULT_CLEAR_UNREL, 2, health_fault_clear_unrel },
|
|
|
- { OP_HEALTH_FAULT_TEST, 3, health_fault_test },
|
|
|
- { OP_HEALTH_FAULT_TEST_UNREL, 3, health_fault_test_unrel },
|
|
|
- { OP_HEALTH_PERIOD_GET, 0, health_period_get },
|
|
|
- { OP_HEALTH_PERIOD_SET, 1, health_period_set },
|
|
|
- { OP_HEALTH_PERIOD_SET_UNREL, 1, health_period_set_unrel },
|
|
|
- { OP_ATTENTION_GET, 0, attention_get },
|
|
|
- { OP_ATTENTION_SET, 1, attention_set },
|
|
|
- { OP_ATTENTION_SET_UNREL, 1, attention_set_unrel },
|
|
|
+ { OP_HEALTH_FAULT_CLEAR_UNREL, 2, health_fault_clear },
|
|
|
+ { OP_HEALTH_FAULT_TEST, 3, health_fault_test },
|
|
|
+ { OP_HEALTH_FAULT_TEST_UNREL, 3, health_fault_test },
|
|
|
+ { OP_HEALTH_PERIOD_GET, 0, health_period_get },
|
|
|
+ { OP_HEALTH_PERIOD_SET, 1, health_period_set },
|
|
|
+ { OP_HEALTH_PERIOD_SET_UNREL, 1, health_period_set },
|
|
|
+ { OP_ATTENTION_GET, 0, attention_get },
|
|
|
+ { OP_ATTENTION_SET, 1, attention_set },
|
|
|
+ { OP_ATTENTION_SET_UNREL, 1, attention_set },
|
|
|
BLE_MESH_MODEL_OP_END,
|
|
|
};
|
|
|
|
|
|
-static int health_pub_update(struct bt_mesh_model *mod)
|
|
|
+static size_t health_get_current(struct bt_mesh_model *model,
|
|
|
+ struct net_buf_simple *msg)
|
|
|
+{
|
|
|
+ struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
+
|
|
|
+ if (!srv) {
|
|
|
+ BT_ERR("%s, No Health Server context provided", __func__);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msg->size < 4) {
|
|
|
+ BT_ERR("%s, Too small health publication msg size %d", __func__, msg->size);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS);
|
|
|
+ net_buf_simple_add_u8(msg, srv->test.prev_test_id);
|
|
|
+ net_buf_simple_add_le16(msg, srv->test.company_id);
|
|
|
+ health_get_fault_value(model, msg, true);
|
|
|
+
|
|
|
+ return health_get_curr_fault_count(model);
|
|
|
+}
|
|
|
+
|
|
|
+static int health_pub_update(struct bt_mesh_model *model)
|
|
|
{
|
|
|
- struct bt_mesh_model_pub *pub = mod->pub;
|
|
|
+ struct bt_mesh_model_pub *pub = model->pub;
|
|
|
size_t count;
|
|
|
|
|
|
BT_DBG("%s", __func__);
|
|
|
|
|
|
- count = health_get_current(mod, pub->msg);
|
|
|
+ if (!pub || !pub->msg) {
|
|
|
+ BT_ERR("%s, Invalid health publication context", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ count = health_get_current(model, pub->msg);
|
|
|
if (count) {
|
|
|
pub->fast_period = 1U;
|
|
|
} else {
|
|
|
@@ -420,29 +398,29 @@ static int health_pub_update(struct bt_mesh_model *mod)
|
|
|
|
|
|
int bt_mesh_fault_update(struct bt_mesh_elem *elem)
|
|
|
{
|
|
|
- struct bt_mesh_model *mod;
|
|
|
+ struct bt_mesh_model *model;
|
|
|
|
|
|
- mod = bt_mesh_model_find(elem, BLE_MESH_MODEL_ID_HEALTH_SRV);
|
|
|
- if (!mod) {
|
|
|
+ model = bt_mesh_model_find(elem, BLE_MESH_MODEL_ID_HEALTH_SRV);
|
|
|
+ if (!model) {
|
|
|
BT_ERR("%s, Health Server does not exist", __func__);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- if (!mod->pub) {
|
|
|
+ if (!model->pub) {
|
|
|
BT_ERR("%s, Health Server has no publication support", __func__);
|
|
|
- return -EIO;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
/* Let periodic publishing, if enabled, take care of sending the
|
|
|
* Health Current Status.
|
|
|
*/
|
|
|
- if (bt_mesh_model_pub_period_get(mod)) {
|
|
|
+ if (bt_mesh_model_pub_period_get(model)) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- health_pub_update(mod);
|
|
|
+ health_pub_update(model);
|
|
|
|
|
|
- return bt_mesh_model_publish(mod);
|
|
|
+ return bt_mesh_model_publish(model);
|
|
|
}
|
|
|
|
|
|
static void attention_off(struct k_work *work)
|
|
|
@@ -457,17 +435,23 @@ static void attention_off(struct k_work *work)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (srv->cb && srv->cb->attn_off) {
|
|
|
- srv->cb->attn_off(srv->model);
|
|
|
+ if (srv->cb.attn_off) {
|
|
|
+ srv->cb.attn_off(srv->model);
|
|
|
}
|
|
|
+ srv->attn_timer_start = false;
|
|
|
}
|
|
|
|
|
|
int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary)
|
|
|
{
|
|
|
struct bt_mesh_health_srv *srv = model->user_data;
|
|
|
|
|
|
+ /* Health Server Model shall be supported by a primary element and may be
|
|
|
+ * supported by any secondary elements.
|
|
|
+ */
|
|
|
+
|
|
|
if (!srv) {
|
|
|
if (!primary) {
|
|
|
+ /* If Health Server is in the secondary element with NULL user_data. */
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -475,6 +459,11 @@ int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ if (srv->test.id_count == 0 || !srv->test.test_ids) {
|
|
|
+ BT_ERR("%s, No Health Test ID provided", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
if (!model->pub) {
|
|
|
BT_ERR("%s, Health Server has no publication support", __func__);
|
|
|
return -EINVAL;
|
|
|
@@ -485,6 +474,10 @@ int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary)
|
|
|
k_delayed_work_init(&srv->attn_timer, attention_off);
|
|
|
|
|
|
srv->model = model;
|
|
|
+ srv->attn_timer_start = false;
|
|
|
+
|
|
|
+ memset(srv->test.curr_faults, HEALTH_NO_FAULT, ARRAY_SIZE(srv->test.curr_faults));
|
|
|
+ memset(srv->test.reg_faults, HEALTH_NO_FAULT, ARRAY_SIZE(srv->test.reg_faults));
|
|
|
|
|
|
if (primary) {
|
|
|
health_srv = srv;
|
|
|
@@ -514,16 +507,20 @@ void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
|
|
|
}
|
|
|
|
|
|
if (time) {
|
|
|
- if (srv->cb && srv->cb->attn_on) {
|
|
|
- srv->cb->attn_on(model);
|
|
|
+ if (srv->cb.attn_on) {
|
|
|
+ srv->cb.attn_on(model, time);
|
|
|
}
|
|
|
|
|
|
k_delayed_work_submit(&srv->attn_timer, time * 1000U);
|
|
|
+ srv->attn_timer_start = true;
|
|
|
} else {
|
|
|
k_delayed_work_cancel(&srv->attn_timer);
|
|
|
|
|
|
- if (srv->cb && srv->cb->attn_off) {
|
|
|
- srv->cb->attn_off(model);
|
|
|
+ if (srv->attn_timer_start == true) {
|
|
|
+ if (srv->cb.attn_off) {
|
|
|
+ srv->cb.attn_off(model);
|
|
|
+ }
|
|
|
+ srv->attn_timer_start = false;
|
|
|
}
|
|
|
}
|
|
|
}
|