Update remote node's model binding after a successful completion of "bind" or "unbind" commands. --- tools/mesh/cfgcli.c | 14 +++- tools/mesh/mesh-db.c | 166 ++++++++++++++++++++++++++++++++++++++++++- tools/mesh/mesh-db.h | 4 +- 3 files changed, 178 insertions(+), 6 deletions(-) diff --git a/tools/mesh/cfgcli.c b/tools/mesh/cfgcli.c index 485d13b5a..c3241a9b7 100644 --- a/tools/mesh/cfgcli.c +++ b/tools/mesh/cfgcli.c @@ -340,7 +340,7 @@ static void print_pub(uint16_t ele_addr, uint32_t mod_id, bt_shell_printf("\tModel: %8.8x\n", mod_id); else bt_shell_printf("\tModel: %4.4x\n", - (uint16_t) (mod_id & 0xffff)); + (uint16_t) (mod_id & ~VENDOR_ID_MASK)); bt_shell_printf("\tApp Key Idx: %u (0x%3.3x)\n", pub->app_idx, pub->app_idx); @@ -552,10 +552,20 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data, bt_shell_printf("Element Addr\t%4.4x\n", addr); - print_mod_id(data + 5, len == 9, ""); + mod_id = print_mod_id(data + 5, len == 9, ""); bt_shell_printf("AppIdx\t\t%u (0x%3.3x)\n ", app_idx, app_idx); + if (data[0] != MESH_STATUS_SUCCESS || !cmd) + break; + + if (cmd->opcode == OP_MODEL_APP_BIND) + mesh_db_node_model_bind(src, addr, len == 9, mod_id, + app_idx); + else + mesh_db_node_model_unbind(src, addr, len == 9, mod_id, + app_idx); + break; case OP_NODE_IDENTITY_STATUS: diff --git a/tools/mesh/mesh-db.c b/tools/mesh/mesh-db.c index f0e0aeb71..da5817acf 100644 --- a/tools/mesh/mesh-db.c +++ b/tools/mesh/mesh-db.c @@ -658,6 +658,162 @@ bool mesh_db_node_ttl_set(uint16_t unicast, uint8_t ttl) return save_config(); } +static json_object *get_element(uint16_t unicast, uint16_t ele_addr) +{ + json_object *jnode, *jarray; + int i, ele_cnt; + + jnode = get_node_by_unicast(unicast); + if (!jnode) + return false; + + if (!json_object_object_get_ex(jnode, "elements", &jarray)) + return NULL; + + if (!jarray || json_object_get_type(jarray) != json_type_array) + return NULL; + + ele_cnt = json_object_array_length(jarray); + + for (i = 0; i < ele_cnt; ++i) { + json_object *jentry, *jval; + int32_t index; + + jentry = json_object_array_get_idx(jarray, i); + if (!json_object_object_get_ex(jentry, "index", &jval)) + return NULL; + + index = json_object_get_int(jval); + if (index > 0xff) + return NULL; + + if (ele_addr == unicast + index) + return jentry; + } + + return NULL; +} + +static json_object *get_model(uint16_t unicast, uint16_t ele_addr, + uint32_t mod_id, bool vendor) +{ + json_object *jelement, *jarray; + int i, sz; + + jelement = get_element(unicast, ele_addr); + if (!jelement) + return false; + + if (!json_object_object_get_ex(jelement, "models", &jarray)) + return NULL; + + if (!jarray || json_object_get_type(jarray) != json_type_array) + return NULL; + + if (!vendor) + mod_id = mod_id & ~VENDOR_ID_MASK; + + sz = json_object_array_length(jarray); + + for (i = 0; i < sz; ++i) { + json_object *jentry, *jval; + uint32_t id, len; + const char *str; + + jentry = json_object_array_get_idx(jarray, i); + if (!json_object_object_get_ex(jentry, "modelId", + &jval)) + return NULL; + + str = json_object_get_string(jval); + len = strlen(str); + if (len != 4 && len != 8) + return NULL; + + if ((len == 4 && vendor) || (len == 8 && !vendor)) + continue; + + if (sscanf(str, "%08x", &id) != 1) + return NULL; + + if (id == mod_id) + return jentry; + } + + return NULL; +} + +static void jarray_int_del(json_object *jarray, int val) +{ + int i, sz = json_object_array_length(jarray); + + for (i = 0; i < sz; ++i) { + json_object *jentry; + + jentry = json_object_array_get_idx(jarray, i); + + if (val == json_object_get_int(jentry)) { + json_object_array_del_idx(jarray, i, 1); + return; + } + } +} + +static bool update_model_int_array(uint16_t unicast, uint16_t ele_addr, + bool vendor, uint32_t mod_id, + int val, const char *keyword, bool add) +{ + json_object *jarray, *jmod, *jvalue; + + if (!cfg || !cfg->jcfg) + return false; + + jmod = get_model(unicast, ele_addr, mod_id, vendor); + if (!jmod) + return false; + + if (!json_object_object_get_ex(jmod, keyword, &jarray)) + return false; + + if (!jarray || json_object_get_type(jarray) != json_type_array) + return false; + + jarray_int_del(jarray, val); + + if (!add) + return true; + + jvalue = json_object_new_int(val); + if (!jvalue) + return false; + + json_object_array_add(jarray, jvalue); + + return save_config(); +} + +bool mesh_db_node_model_bind(uint16_t unicast, uint16_t ele_addr, bool vendor, + uint32_t mod_id, uint16_t app_idx) +{ + char buf[5]; + + snprintf(buf, 5, "%4.4x", app_idx); + + return update_model_int_array(unicast, ele_addr, vendor, mod_id, + (int) app_idx, "bind", true); +} + +bool mesh_db_node_model_unbind(uint16_t unicast, uint16_t ele_addr, bool vendor, + uint32_t mod_id, uint16_t app_idx) +{ + char buf[5]; + + snprintf(buf, 5, "%4.4x", app_idx); + + return update_model_int_array(unicast, ele_addr, vendor, mod_id, + (int) app_idx, "bind", false); +} + static void jarray_key_del(json_object *jarray, int16_t idx) { int i, sz = json_object_array_length(jarray); @@ -1172,7 +1328,7 @@ bool mesh_db_del_node(uint16_t unicast) static json_object *init_model(uint16_t mod_id) { - json_object *jmod; + json_object *jmod, *jarray; jmod = json_object_new_object(); @@ -1181,12 +1337,15 @@ static json_object *init_model(uint16_t mod_id) return NULL; } + jarray = json_object_new_array(); + json_object_object_add(jmod, "bind", jarray); + return jmod; } static json_object *init_vendor_model(uint32_t mod_id) { - json_object *jmod; + json_object *jmod, *jarray; jmod = json_object_new_object(); @@ -1195,6 +1354,9 @@ static json_object *init_vendor_model(uint32_t mod_id) return NULL; } + jarray = json_object_new_array(); + json_object_object_add(jmod, "bind", jarray); + return jmod; } diff --git a/tools/mesh/mesh-db.h b/tools/mesh/mesh-db.h index c1bcb3ae6..c3ee81457 100644 --- a/tools/mesh/mesh-db.h +++ b/tools/mesh/mesh-db.h @@ -44,9 +44,9 @@ bool mesh_db_node_app_key_del(uint16_t unicast, uint16_t idx); bool mesh_db_node_app_key_update(uint16_t unicast, uint16_t idx, bool updated); bool mesh_db_node_ttl_set(uint16_t unicast, uint8_t ttl); bool mesh_db_node_write_mode(uint16_t unicast, const char *keyword, int value); -bool mesh_db_node_model_binding_add(uint16_t unicast, uint8_t ele, bool vendor, +bool mesh_db_node_model_bind(uint16_t unicast, uint16_t ele_addr, bool vendor, uint32_t mod_id, uint16_t app_idx); -bool mesh_db_node_model_binding_del(uint16_t unicast, uint8_t ele, bool vendor, +bool mesh_db_node_model_unbind(uint16_t unicast, uint16_t ele_addr, bool vendor, uint32_t mod_id, uint16_t app_idx); struct l_queue *mesh_db_load_groups(void); bool mesh_db_add_group(struct mesh_group *grp); -- 2.31.1