Bluetooth: Mesh: Support for storing model subscriptions persistently
Add support for storing the subscribed group addresses for each model persistently. The addresses are stored under the settings key bt/mesh/s/<mod id>/sub for SIG models and bt/mesh/v/<mod id>/sub for vendor models. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
c3d5a0da62
commit
dde2db5626
4 changed files with 119 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
|||
/* bt_mesh_model.flags */
|
||||
enum {
|
||||
BT_MESH_MOD_BIND_PENDING = BIT(0),
|
||||
BT_MESH_MOD_SUB_PENDING = BIT(1),
|
||||
};
|
||||
|
||||
void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count);
|
||||
|
|
|
@ -1377,6 +1377,10 @@ static void mod_sub_add(struct bt_mesh_model *model,
|
|||
} else {
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
|
@ -1437,6 +1441,10 @@ static void mod_sub_del(struct bt_mesh_model *model,
|
|||
match = bt_mesh_model_find_group(mod, sub_addr);
|
||||
if (match) {
|
||||
*match = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
}
|
||||
|
||||
send_status:
|
||||
|
@ -1491,6 +1499,10 @@ static void mod_sub_overwrite(struct bt_mesh_model *model,
|
|||
mod->groups[0] = sub_addr;
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
|
@ -1541,6 +1553,10 @@ static void mod_sub_del_all(struct bt_mesh_model *model,
|
|||
|
||||
mod_sub_list_clear(mod);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
send_status:
|
||||
|
@ -1716,6 +1732,10 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
|
|||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1773,6 +1793,11 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
|
|||
match = bt_mesh_model_find_group(mod, sub_addr);
|
||||
if (match) {
|
||||
*match = BT_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
} else {
|
||||
status = STATUS_CANNOT_REMOVE;
|
||||
|
@ -1828,6 +1853,10 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model,
|
|||
if (status == STATUS_SUCCESS) {
|
||||
mod->groups[0] = sub_addr;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
bt_mesh_lpn_group_add(sub_addr);
|
||||
}
|
||||
|
@ -3135,6 +3164,22 @@ int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
||||
bool vnd, bool primary, void *user_data)
|
||||
{
|
||||
/* Clear model state that isn't otherwise cleared. E.g. AppKey
|
||||
* binding and model publication is cleared as a consequence
|
||||
* of removing all app keys, however model subscription clearing
|
||||
* must be taken care of here.
|
||||
*/
|
||||
|
||||
mod_sub_list_clear(mod);
|
||||
|
||||
if (IS_ENABLED(BT_SETTINGS)) {
|
||||
bt_mesh_store_mod_sub(mod);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_cfg_reset(void)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = conf;
|
||||
|
@ -3161,6 +3206,8 @@ void bt_mesh_cfg_reset(void)
|
|||
}
|
||||
}
|
||||
|
||||
bt_mesh_model_foreach(mod_reset, NULL);
|
||||
|
||||
memset(labels, 0, sizeof(labels));
|
||||
}
|
||||
|
||||
|
|
|
@ -434,6 +434,30 @@ static int mod_set_bind(struct bt_mesh_model *mod, char *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mod_set_sub(struct bt_mesh_model *mod, char *val)
|
||||
{
|
||||
int len, err;
|
||||
|
||||
/* Start with empty array regardless of cleared or set value */
|
||||
memset(mod->groups, 0, sizeof(mod->groups));
|
||||
|
||||
if (!val) {
|
||||
BT_DBG("Cleared subscriptions for model");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = sizeof(mod->groups);
|
||||
err = settings_bytes_from_str(val, mod->groups, &len);
|
||||
if (err) {
|
||||
BT_ERR("Failed to decode value %s (err %d)", val, err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_DBG("Decoded %u subscribed group addresses for model",
|
||||
len / sizeof(mod->groups[0]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mod_set(bool vnd, int argc, char **argv, char *val)
|
||||
{
|
||||
struct bt_mesh_model *mod;
|
||||
|
@ -463,6 +487,10 @@ static int mod_set(bool vnd, int argc, char **argv, char *val)
|
|||
return mod_set_bind(mod, val);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "sub")) {
|
||||
return mod_set_sub(mod, val);
|
||||
}
|
||||
|
||||
BT_WARN("Unknown module key %s", argv[1]);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -934,6 +962,37 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
|
|||
settings_save_one(path, val);
|
||||
}
|
||||
|
||||
static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
|
||||
{
|
||||
u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
|
||||
char buf[BT_SETTINGS_SIZE(sizeof(groups))];
|
||||
char path[20];
|
||||
int i, count;
|
||||
char *val;
|
||||
|
||||
for (i = 0, count = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
||||
if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
|
||||
groups[count++] = mod->groups[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (count) {
|
||||
val = settings_str_from_bytes(groups, count * sizeof(groups[0]),
|
||||
buf, sizeof(buf));
|
||||
if (!val) {
|
||||
BT_ERR("Unable to encode model subscription as value");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
val = NULL;
|
||||
}
|
||||
|
||||
encode_mod_path(mod, vnd, "sub", path, sizeof(path));
|
||||
|
||||
BT_DBG("Saving %s as %s", path, val ? val : "(null)");
|
||||
settings_save_one(path, val);
|
||||
}
|
||||
|
||||
static void store_pending_mod(struct bt_mesh_model *mod,
|
||||
struct bt_mesh_elem *elem, bool vnd,
|
||||
bool primary, void *user_data)
|
||||
|
@ -946,6 +1005,11 @@ static void store_pending_mod(struct bt_mesh_model *mod,
|
|||
mod->flags &= ~BT_MESH_MOD_BIND_PENDING;
|
||||
store_pending_mod_bind(mod, vnd);
|
||||
}
|
||||
|
||||
if (mod->flags & BT_MESH_MOD_SUB_PENDING) {
|
||||
mod->flags &= ~BT_MESH_MOD_SUB_PENDING;
|
||||
store_pending_mod_sub(mod, vnd);
|
||||
}
|
||||
}
|
||||
|
||||
static void store_pending(struct k_work *work)
|
||||
|
@ -1145,6 +1209,12 @@ void bt_mesh_store_mod_bind(struct bt_mesh_model *mod)
|
|||
schedule_store(BT_MESH_MOD_PENDING);
|
||||
}
|
||||
|
||||
void bt_mesh_store_mod_sub(struct bt_mesh_model *mod)
|
||||
{
|
||||
mod->flags |= BT_MESH_MOD_SUB_PENDING;
|
||||
schedule_store(BT_MESH_MOD_PENDING);
|
||||
}
|
||||
|
||||
void bt_mesh_settings_init(void)
|
||||
{
|
||||
k_delayed_work_init(&pending_store, store_pending);
|
||||
|
|
|
@ -11,6 +11,7 @@ void bt_mesh_store_rpl(struct bt_mesh_rpl *rpl);
|
|||
void bt_mesh_store_subnet(struct bt_mesh_subnet *sub);
|
||||
void bt_mesh_store_app_key(struct bt_mesh_app_key *key);
|
||||
void bt_mesh_store_mod_bind(struct bt_mesh_model *mod);
|
||||
void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
|
||||
|
||||
void bt_mesh_clear_net(void);
|
||||
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue