return true;
}
+static uint16_t __mesh_node_parse_key(json_object *jarray, int i)
+{
+ json_object *jkey;
+ int idx;
+
+ jkey = json_object_array_get_idx(jarray, i);
+ if (!jkey)
+ return MESH_KEY_IDX_INVALID;
+
+ if (!__mesh_get_int(jkey, "index", &idx))
+ return MESH_KEY_IDX_INVALID;
+
+ return (uint16_t)idx;
+}
+
static bool __mesh_write_int(json_object *jobj,
const char *keyword, int val)
{
return true;
}
+static bool __mesh_write_uint32_hex(json_object *jobj,
+ const char *desc, uint32_t val)
+{
+ json_object *jstring;
+ char buf[9];
+
+ snprintf(buf, 9, "%8.8x", val);
+ jstring = json_object_new_string(buf);
+ if (!jstring)
+ return false;
+
+ /* Overwrite old value if present */
+ json_object_object_del(jobj, desc);
+
+ json_object_object_add(jobj, desc, jstring);
+ return true;
+}
+
static bool __mesh_write_uint16_hex(json_object *jobj,
const char *desc, uint16_t value)
{
return true;
}
+static json_object *__mesh_init_model(uint16_t mod_id)
+{
+ json_object *jmod;
+
+ jmod = json_object_new_object();
+
+ if (!__mesh_write_uint16_hex(jmod, "modelId", mod_id)) {
+ json_object_put(jmod);
+ return NULL;
+ }
+
+ return jmod;
+}
+
+static json_object *__mesh_init_vendor_model(uint32_t mod_id)
+{
+ json_object *jmod;
+
+ jmod = json_object_new_object();
+
+ if (!__mesh_write_uint32_hex(jmod, "modelId", mod_id)) {
+ json_object_put(jmod);
+ return NULL;
+ }
+
+ return jmod;
+}
+
+static json_object *__mesh_init_elements(uint8_t num_els)
+{
+ json_object *jelements;
+ uint8_t i;
+
+ jelements = json_object_new_array();
+
+ for (i = 0; i < num_els; ++i) {
+ json_object *jelement, *jmods;
+
+ jelement = json_object_new_object();
+
+ __mesh_write_int(jelement, "index", i);
+ __mesh_write_uint16_hex(jelement, "location", MESH_DEFAULT_LOCATION);
+ jmods = json_object_new_array();
+ json_object_object_add(jelement, "models", jmods);
+
+ json_object_array_add(jelements, jelement);
+ }
+
+ return jelements;
+}
static bool __mesh_add_app_key(json_object *jobj,
uint16_t net_idx, uint16_t app_idx)
{
return true;
}
+static bool __mesh_get_token(json_object *jobj, uint8_t token[8])
+{
+ json_object *jval;
+ const char *str;
+
+ if (!json_object_object_get_ex(jobj, "token", &jval))
+ return false;
+
+ str = json_object_get_string(jval);
+ if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), token, 8))
+ return false;
+
+ return true;
+}
+
+static bool __mesh_get_uuid(json_object *jobj, uint8_t uuid[16])
+{
+ json_object *jval;
+ const char *str;
+
+ if (!json_object_object_get_ex(jobj, "uuid", &jval))
+ return false;
+
+ str = json_object_get_string(jval);
+ if (!_bt_mesh_util_convert_string_to_hex(str, strlen(str), uuid, 16))
+ return false;
+
+ return true;
+}
+
static bool __mesh_add_u8_8(json_object *jobj,
const char *desc, const uint8_t value[8])
{
g_free(cfg);
}
+#if 0
+bool _bt_mesh_cdb_load_keys(_bt_mesh_cdb_t* cfg)
+{
+ json_object *jarray, *jentry;
+ int net_idx, app_idx;
+ int i, key_cnt;
+ json_object *jobj = cfg->jcfg;
+
+ json_object_object_get_ex(jobj, "netKeys", &jarray);
+ if (!jarray ||
+ json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ key_cnt = json_object_array_length(jarray);
+ if (key_cnt < 0)
+ return false;
+
+ for (i = 0; i < key_cnt; ++i) {
+ int phase;
+
+ jentry = json_object_array_get_idx(jarray, i);
+
+ if (!__mesh_get_int(jentry, "index", &net_idx))
+ return false;
+
+ _bt_mesh_keys_add_net_key(cfg->uuid,
+ (uint16_t) net_idx);
+
+ if (!__mesh_get_int(jentry, "phase", &phase))
+ return false;
+
+ _bt_mesh_keys_set_net_key_phase(cfg,
+ net_idx, (uint8_t) phase, false);
+ }
+
+ json_object_object_get_ex(jobj, "appKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ key_cnt = json_object_array_length(jarray);
+ if (key_cnt < 0)
+ return false;
+
+ for (i = 0; i < key_cnt; ++i) {
+
+ jentry = json_object_array_get_idx(jarray, i);
+ if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
+ return false;
+
+ if (!__mesh_get_int(jentry, "index", &app_idx))
+ return false;
+
+ _bt_mesh_keys_add_app_key(cfg->uuid,
+ (uint16_t) net_idx, (uint16_t) app_idx);
+ }
+ return true;
+}
+#endif
+
bool _bt_mesh_conf_parse_data(void *cfg, int k)
{
_bt_mesh_cdb_t *conf = (_bt_mesh_cdb_t*) cfg;
return true;
}
+
+bool _bt_mesh_conf_fetch_vendor_specific_info(_bt_mesh_cdb_t *cfg,
+ uint16_t *cid, uint16_t *vid,
+ uint16_t *version, uint16_t *crpl,
+ int *relay, int *friend,
+ int *proxy, int *lpn)
+{
+ json_object *jcfg;
+ json_object *jnode;
+ json_object *jobj = NULL;
+ json_object *jobjfeature = NULL;
+ const char *str;
+
+ if (!cfg)
+ return false;
+
+ jcfg = cfg->jcfg;
+ if (!jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_uuid(jcfg, cfg->uuid);
+ if (jnode)
+ return false;
+
+ /* Get CRPL */
+ if (!json_object_object_get_ex(jnode, "crpl", &jobj))
+ return false;
+
+ str = json_object_get_string(jobj);
+ if (!str)
+ return false;
+ if (sscanf(str, "%04hx", crpl) != 1)
+ return false;
+
+ /* Get Company ID */
+ if (!json_object_object_get_ex(jnode, "cid", &jobj))
+ return false;
+
+ str = json_object_get_string(jobj);
+ if (!str)
+ return false;
+ if (sscanf(str, "%04hx", cid) != 1)
+ return false;
+
+ /* Get Vendor ID */
+ if (!json_object_object_get_ex(jnode, "pid", &jobj))
+ return false;
+
+ str = json_object_get_string(jobj);
+ if (!str)
+ return false;
+
+ if (sscanf(str, "%04hx", vid) != 1)
+ return false;
+
+ /* Get Version ID */
+ if (!json_object_object_get_ex(jnode, "vid", &jobj))
+ return false;
+
+ str = json_object_get_string(jobj);
+ if (!str)
+ return false;
+ if (sscanf(str, "%04hx", version) != 1)
+ return false;
+
+ jobj = json_object_object_get(jnode, "features");
+
+ if (jobj) {
+ if (json_object_object_get_ex(jobj, "relay", &jobjfeature)) {
+ str = json_object_get_string(jobj);
+ if (str)
+ sscanf(str, "%d", relay);
+ }
+
+ if (json_object_object_get_ex(jobj, "friend", &jobjfeature)) {
+ str = json_object_get_string(jobj);
+ if (str)
+ sscanf(str, "%d", friend);
+ }
+
+ if (json_object_object_get_ex(jobj, "proxy", &jobjfeature)) {
+ str = json_object_get_string(jobj);
+ if (str)
+ sscanf(str, "%d", proxy);
+ }
+ if (json_object_object_get_ex(jobj, "lowPower", &jobjfeature)) {
+ str = json_object_get_string(jobj);
+ if (str)
+ sscanf(str, "%d", lpn);
+ }
+ }
+ return true;
+}
+
+GSList *_bt_mesh_conf_load_group_info(_bt_mesh_cdb_t *cfg)
+{
+ json_object *jgroups;
+ GSList *groups = NULL;
+ int i, sz;
+
+ if (!cfg || !cfg->jcfg)
+ return NULL;
+
+ if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
+ jgroups = json_object_new_array();
+ if (!jgroups)
+ return NULL;
+
+ json_object_object_add(cfg->jcfg, "groups", jgroups);
+ }
+
+ sz = json_object_array_length(jgroups);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jgroup, *jval;
+ _bt_mesh_group_t *grp;
+ uint16_t addr, addr_len;
+ const char *str;
+
+ jgroup = json_object_array_get_idx(jgroups, i);
+ if (!jgroup)
+ continue;
+
+ if (!json_object_object_get_ex(jgroup, "name", &jval))
+ continue;
+
+ str = json_object_get_string(jval);
+ if (strlen(str) != 10)
+ continue;
+
+ if (sscanf(str + 6, "%04hx", &addr) != 1)
+ continue;
+ if (!json_object_object_get_ex(jgroup, "address", &jval))
+ continue;
+
+ str = json_object_get_string(jval);
+ addr_len = strlen(str);
+ if (addr_len != 4 && addr_len != 32)
+ continue;
+
+ if (addr_len == 32 && !MESH_IS_VIRTUAL(addr))
+ continue;
+
+ grp = g_malloc0(sizeof(_bt_mesh_group_t));
+
+ if (addr_len == 4)
+ sscanf(str, "%04hx", &grp->grp_addr);
+ else {
+ _bt_mesh_util_convert_string_to_hex(str,
+ 32, grp->label_uuid, 16);
+ grp->grp_addr = addr;
+ }
+
+ groups = g_slist_append(groups, grp);
+ }
+
+ return groups;
+}
+
+bool _bt_mesh_conf_insert_group_info(_bt_mesh_cdb_t *cfg,
+ _bt_mesh_group_t *grp)
+{
+ json_object *jgroup, *jgroups, *jval;
+ char buf[16];
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups))
+ return false;
+
+ jgroup = json_object_new_object();
+ if (!jgroup)
+ return false;
+
+ snprintf(buf, 11, "Group_%4.4x", grp->grp_addr);
+ jval = json_object_new_string(buf);
+ json_object_object_add(jgroup, "name", jval);
+
+ if (MESH_IS_VIRTUAL(grp->grp_addr)) {
+ if (!__mesh_add_u8_16(jgroup, "address", grp->label_uuid))
+ goto fail;
+ } else {
+ if (!__mesh_write_uint16_hex(jgroup, "address", grp->grp_addr))
+ goto fail;
+ }
+
+ json_object_array_add(jgroups, jgroup);
+
+ return __bt_mesh_save_configruation_file(cfg);
+
+fail:
+ json_object_put(jgroup);
+ return false;
+}
+
+bool _bt_mesh_conf_set_network_friendly_name(_bt_mesh_cdb_t *cfg,
+ const char *network_name)
+{
+ json_object *jcfg;
+
+ if (!cfg)
+ return false;
+ jcfg = cfg->jcfg;
+
+ if (!jcfg)
+ return false;
+
+ json_object_object_del(jcfg, "Network_Name");
+ __mesh_add_string(jcfg, "Network_Name", network_name);
+
+
+ BT_INFO("Mesh: CDB: Network New Name [%s]", network_name);
+ return __bt_mesh_save_configruation_file(cfg);
+}
+
+const char * _bt_mesh_conf_get_network_friendly_name(_bt_mesh_cdb_t *cfg)
+{
+ json_object *jcfg;
+ json_object *jobj = NULL;
+ const char *str;
+
+ if (!cfg)
+ return NULL;
+ jcfg = cfg->jcfg;
+
+ if (!jcfg)
+ return NULL;
+
+ /* Get Network Name */
+ if (!json_object_object_get_ex(jcfg, "Network_Name", &jobj))
+ return NULL;
+
+ str = json_object_get_string(jobj);
+ if (!str)
+ return NULL;
+
+ BT_INFO("Mesh: CDB: Network Name [%s]", str);
+ return str;
+}
+
+static bool __mesh_load_composition(_bt_mesh_cdb_t *cfg,
+ json_object *jnode, uint16_t unicast)
+{
+ json_object *jarray;
+ int i, ele_cnt;
+
+ if (!json_object_object_get_ex(jnode, "elements", &jarray))
+ return false;
+
+ if (json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ ele_cnt = json_object_array_length(jarray);
+
+ for (i = 0; i < ele_cnt; ++i) {
+ json_object *jentry, *jval, *jmods;
+ int32_t index;
+ int k, mod_cnt;
+
+ jentry = json_object_array_get_idx(jarray, i);
+ if (!json_object_object_get_ex(jentry, "index", &jval))
+ return false;
+
+ index = json_object_get_int(jval);
+ if (index > 0xff)
+ return false;
+
+ if (!json_object_object_get_ex(jentry, "models", &jmods))
+ return false;
+
+ mod_cnt = json_object_array_length(jmods);
+
+ for (k = 0; k < mod_cnt; ++k) {
+ json_object *jmod, *jid;
+ uint32_t mod_id, len;
+ const char *str;
+
+ jmod = json_object_array_get_idx(jmods, k);
+ if (!json_object_object_get_ex(jmod, "modelId", &jid))
+ return false;
+
+ str = json_object_get_string(jid);
+ len = strlen(str);
+
+ if (len != 4 && len != 8)
+ return false;
+
+ if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
+ return false;
+
+ if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
+ return false;
+
+ _bt_mesh_node_set_model(cfg->uuid,
+ unicast, index, mod_id, len == 8);
+ }
+ }
+
+ return true;
+}
+
+bool _bt_mesh_conf_set_node_comp_data(_bt_mesh_cdb_t *cfg,
+ uint16_t unicast, uint8_t *data, uint16_t len)
+{
+ uint16_t features;
+ int sz, i = 0;
+ json_object *jnode, *jobj, *jelements;
+ uint16_t crpl;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = __mesh_get_node_by_unicast(cfg, unicast);
+ if (!jnode)
+ return false;
+
+ /* skip page -- We only support Page Zero */
+ data++;
+ len--;
+
+ /* If "crpl" property is present, composition is already recorded */
+ if (json_object_object_get_ex(jnode, "crpl", &jobj))
+ return true;
+
+ if (!__mesh_write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
+ return false;
+
+ if (!__mesh_write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
+ return false;
+
+ if (!__mesh_write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
+ return false;
+
+ crpl = l_get_le16(&data[6]);
+
+ features = l_get_le16(&data[8]);
+ data += 10;
+ len -= 10;
+
+ jobj = json_object_object_get(jnode, "features");
+ if (!jobj) {
+ jobj = json_object_new_object();
+ json_object_object_add(jnode, "features", jobj);
+ }
+
+ if ((features & MESH_FEATURE_RELAY))
+ __mesh_write_int(jobj, "relay", 1);
+ else
+ __mesh_write_int(jobj, "relay", 0);
+
+ if ((features & MESH_FEATURE_FRIEND))
+ __mesh_write_int(jobj, "friend", 1);
+ else
+ __mesh_write_int(jobj, "friend", 0);
+
+ if ((features & MESH_FEATURE_PROXY))
+ __mesh_write_int(jobj, "proxy", 1);
+ else
+ __mesh_write_int(jobj, "proxy", 0);
+
+ if ((features & MESH_FEATURE_LPN))
+ __mesh_write_int(jobj, "lowPower", 1);
+ else
+ __mesh_write_int(jobj, "lowPower", 0);
+
+ jelements = json_object_object_get(jnode, "elements");
+ if (!jelements)
+ return false;
+
+ sz = json_object_array_length(jelements);
+
+ while (len) {
+ json_object *jentry, *jmods;
+ uint32_t mod_id;
+ uint8_t m, v;
+
+ /* Mismatch in the element count */
+ if (i >= sz)
+ return false;
+
+ jentry = json_object_array_get_idx(jelements, i);
+
+ __mesh_write_int(jentry, "index", i);
+
+ if (!__mesh_write_uint16_hex(jentry, "location", l_get_le16(data)))
+ return false;
+
+ data += 2;
+ len -= 2;
+
+ m = *data++;
+ v = *data++;
+ len -= 2;
+
+ jmods = json_object_object_get(jentry, "models");
+ if (!jmods) {
+ /* For backwards compatibility */
+ jmods = json_object_new_array();
+ json_object_object_add(jentry, "models", jmods);
+ }
+
+ while (len >= 2 && m--) {
+ mod_id = l_get_le16(data);
+
+ jobj = __mesh_init_model(mod_id);
+ if (!jobj)
+ goto fail;
+
+ json_object_array_add(jmods, jobj);
+ data += 2;
+ len -= 2;
+ }
+
+ while (len >= 4 && v--) {
+ jobj = json_object_new_object();
+ mod_id = l_get_le16(data + 2);
+ mod_id = l_get_le16(data) << 16 | mod_id;
+
+ jobj = __mesh_init_vendor_model(mod_id);
+ if (!jobj)
+ goto fail;
+
+ json_object_array_add(jmods, jobj);
+
+ data += 4;
+ len -= 4;
+ }
+
+ i++;
+ }
+
+ /* CRPL is written last. Will be used to check composition's presence */
+ if (!__mesh_write_uint16_hex(jnode, "crpl", crpl))
+ goto fail;
+
+ /* Initiate remote's composition from storage */
+ if (!__mesh_load_composition(cfg, jnode, unicast))
+ goto fail;
+
+ return __bt_mesh_save_configruation_file(cfg);
+
+fail:
+ /* Reset elements array */
+ json_object_object_del(jnode, "elements");
+ __mesh_init_elements(sz);
+
+ return false;
+}
+
+_bt_mesh_cdb_t* _bt_mesh_cdb_load(const char *file_name,
+ const char *token)
+{
+ char *token_str = NULL;
+ int fd;
+ char *str;
+ struct stat st;
+ ssize_t sz;
+ json_object *jcfg;
+ _bt_mesh_cdb_t *cfg;
+
+ fd = open(file_name, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ if (fstat(fd, &st) == -1) {
+ close(fd);
+ return NULL;
+ }
+
+ str = (char *) g_malloc0(st.st_size + 1);
+ if (!str) {
+ close(fd);
+ return NULL;
+ }
+
+ sz = read(fd, str, st.st_size);
+ if (sz != st.st_size) {
+ BT_ERR("Mesh: Failed to read configuration file [%s]", file_name);
+ return NULL;
+ }
+
+ jcfg = json_tokener_parse(str);
+
+ close(fd);
+ g_free(str);
+
+ if (!jcfg)
+ return NULL;
+ cfg = g_malloc0(sizeof(_bt_mesh_cdb_t));
+
+ cfg->jcfg = jcfg;
+ cfg->cfg_fname = g_strdup(file_name);
+
+ if (!__mesh_get_uuid(jcfg, cfg->uuid)) {
+ BT_ERR("Mesh: Configuration file missing UUID");
+ goto fail;
+ }
+
+ if (!__mesh_get_token(jcfg, cfg->token)) {
+ BT_ERR("Mesh: Configuration file missing token");
+ goto fail;
+ }
+
+ token_str = _bt_service_convert_hex_to_string((unsigned char*)cfg->token, 8);
+
+ /* Match CDB file tken with user's token */
+ if (g_strcmp0(token_str, token)) {
+ BT_INFO("Mesh: Token did not match! File token [%s] requested token [%s]",
+ cfg->token, token);
+ goto fail;
+ }
+ /* TODO: Load keys and remotes */
+ return cfg;
+fail:
+ _bt_mesh_conf_free(cfg);
+ return NULL;
+}
+
+bool _bt_mesh_cdb_load_nodes(_bt_mesh_cdb_t *cfg)
+{
+ json_object *jnodes;
+ int i, sz, node_count = 0;
+
+ json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes);
+ if (!jnodes || json_object_get_type(jnodes) != json_type_array)
+ return false;
+
+ sz = json_object_array_length(jnodes);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jnode, *jval, *jarray;
+ uint8_t uuid[16];
+ uint16_t unicast, key_idx;
+ const char *str;
+ int ele_cnt, key_cnt;
+ int j;
+
+ jnode = json_object_array_get_idx(jnodes, i);
+ if (!jnode)
+ continue;
+
+ if (!json_object_object_get_ex(jnode, "uuid", &jval))
+ continue;
+
+ str = json_object_get_string(jval);
+ if (strlen(str) != 32)
+ continue;
+
+ _bt_mesh_util_convert_string_to_hex(str, 32, uuid, 16);
+
+ if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
+ continue;
+
+ str = json_object_get_string(jval);
+ if (sscanf(str, "%04hx", &unicast) != 1)
+ continue;
+
+ json_object_object_get_ex(jnode, "elements", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ continue;
+
+ ele_cnt = json_object_array_length(jarray);
+
+ if (ele_cnt > MESH_MAX_ELE_COUNT)
+ continue;
+
+ json_object_object_get_ex(jnode, "netKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ continue;
+
+ key_cnt = json_object_array_length(jarray);
+ if (key_cnt < 0)
+ continue;
+
+ key_idx = __mesh_node_parse_key(jarray, 0);
+ if (key_idx == MESH_KEY_IDX_INVALID)
+ continue;
+
+ _bt_mesh_node_add_node(cfg->uuid, (const uint8_t *)uuid, unicast, ele_cnt,
+ key_idx);
+ for (j = 1; j < key_cnt; j++) {
+ key_idx = __mesh_node_parse_key(jarray, j);
+
+ if (key_idx != MESH_KEY_IDX_INVALID)
+ _bt_mesh_node_add_net_key(cfg->uuid, unicast, key_idx);
+ }
+
+ json_object_object_get_ex(jnode, "appKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ continue;
+
+ key_cnt = json_object_array_length(jarray);
+ for (j = 0; j < key_cnt; j++) {
+ key_idx = __mesh_node_parse_key(jarray, j);
+
+ if (key_idx != MESH_KEY_IDX_INVALID)
+ _bt_mesh_node_add_app_key(cfg->uuid, unicast, key_idx);
+ }
+
+ __mesh_load_composition(cfg, jnode, unicast);
+
+ node_count++;
+
+ /* TODO: Add the rest of the configuration */
+ }
+
+ if (node_count != sz)
+ BT_ERR("Mesh: CDB: The remote node configuration load is incomplete!");
+
+ return true;
+}
+
+bool _bt_mesh_conf_load_all_keys(_bt_mesh_cdb_t* cfg)
+{
+ json_object *jarray, *jentry;
+ int net_idx, app_idx;
+ int i, key_cnt;
+ json_object *jobj = cfg->jcfg;
+
+ json_object_object_get_ex(jobj, "netKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ key_cnt = json_object_array_length(jarray);
+ if (key_cnt < 0)
+ return false;
+
+ for (i = 0; i < key_cnt; ++i) {
+ int phase;
+
+ jentry = json_object_array_get_idx(jarray, i);
+
+ if (!__mesh_get_int(jentry, "index", &net_idx))
+ return false;
+
+ _bt_mesh_keys_add_net_key(cfg->uuid, (uint16_t) net_idx);
+
+ if (!__mesh_get_int(jentry, "phase", &phase))
+ return false;
+
+ _bt_mesh_keys_set_net_key_phase(cfg, net_idx, (uint8_t) phase, false);
+ }
+
+ json_object_object_get_ex(jobj, "appKeys", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ key_cnt = json_object_array_length(jarray);
+ if (key_cnt < 0)
+ return false;
+
+ for (i = 0; i < key_cnt; ++i) {
+
+ jentry = json_object_array_get_idx(jarray, i);
+ if (!__mesh_get_int(jentry, "boundNetKey", &net_idx))
+ return false;
+
+ if (!__mesh_get_int(jentry, "index", &app_idx))
+ return false;
+
+ _bt_mesh_keys_add_app_key(cfg->uuid, (uint16_t) net_idx, (uint16_t) app_idx);
+ }
+
+ return true;
+}