Bluetooth: Mesh: Support for storing heartbeat publication persistently
Add support for storing the heartbeat publication persistently. The information is only stored as "publish indefinitely" or as "periodic publishing disabled" since we can't know for how long the node is powered off. The information is stored under the settings key bt/mesh/HBPub. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
efb68ca2da
commit
44bd56877b
6 changed files with 138 additions and 2 deletions
|
@ -30,7 +30,7 @@ struct bt_mesh_cfg_srv {
|
|||
u8_t default_ttl; /* Default TTL */
|
||||
|
||||
/* Heartbeat Publication */
|
||||
struct {
|
||||
struct bt_mesh_hb_pub {
|
||||
struct k_delayed_work timer;
|
||||
|
||||
u16_t dst;
|
||||
|
@ -42,7 +42,7 @@ struct bt_mesh_cfg_srv {
|
|||
} hb_pub;
|
||||
|
||||
/* Heartbeat Subscription */
|
||||
struct {
|
||||
struct bt_mesh_hb_sub {
|
||||
s64_t expiry;
|
||||
|
||||
u16_t src;
|
||||
|
|
|
@ -2902,6 +2902,10 @@ static void heartbeat_pub_set(struct bt_mesh_model *model,
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_hb_pub();
|
||||
}
|
||||
|
||||
hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
|
||||
|
||||
return;
|
||||
|
@ -3338,12 +3342,25 @@ u8_t *bt_mesh_label_uuid_get(u16_t addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void)
|
||||
{
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &conf->hb_pub;
|
||||
}
|
||||
|
||||
void bt_mesh_subnet_del(struct bt_mesh_subnet *sub)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (conf && conf->hb_pub.net_idx == sub->net_idx) {
|
||||
hb_pub_disable(conf);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_store_hb_pub();
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete any app keys bound to this NetKey index */
|
||||
|
|
|
@ -126,6 +126,8 @@ void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
|
|||
|
||||
u8_t *bt_mesh_label_uuid_get(u16_t addr);
|
||||
|
||||
struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
|
||||
|
||||
u8_t bt_mesh_net_transmit_get(void);
|
||||
u8_t bt_mesh_relay_get(void);
|
||||
u8_t bt_mesh_friend_get(void);
|
||||
|
|
|
@ -204,6 +204,7 @@ enum {
|
|||
BT_MESH_NET_PENDING,
|
||||
BT_MESH_IV_PENDING,
|
||||
BT_MESH_SEQ_PENDING,
|
||||
BT_MESH_HB_PUB_PENDING,
|
||||
BT_MESH_MOD_PENDING,
|
||||
|
||||
/* Don't touch - intentionally last */
|
||||
|
|
|
@ -58,6 +58,16 @@ struct seq_val {
|
|||
u8_t val[3];
|
||||
} __packed;
|
||||
|
||||
/* Heartbeat Publication storage */
|
||||
struct hb_pub_val {
|
||||
u16_t dst;
|
||||
u8_t period;
|
||||
u8_t ttl;
|
||||
u16_t feat;
|
||||
u16_t net_idx:12,
|
||||
indefinite:1;
|
||||
};
|
||||
|
||||
/* IV Index & IV Update storage */
|
||||
struct iv_val {
|
||||
u32_t iv_index;
|
||||
|
@ -419,6 +429,59 @@ static int app_key_set(int argc, char **argv, char *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hb_pub_set(int argc, char **argv, char *val)
|
||||
{
|
||||
struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
|
||||
struct hb_pub_val hb_val;
|
||||
int len, err;
|
||||
|
||||
BT_DBG("val %s", val ? val : "(null)");
|
||||
|
||||
if (!pub) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!val) {
|
||||
pub->dst = BT_MESH_ADDR_UNASSIGNED;
|
||||
pub->count = 0;
|
||||
pub->ttl = 0;
|
||||
pub->period = 0;
|
||||
pub->feat = 0;
|
||||
|
||||
BT_DBG("Cleared heartbeat publication");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = sizeof(hb_val);
|
||||
err = settings_bytes_from_str(val, &hb_val, &len);
|
||||
if (err) {
|
||||
BT_ERR("Failed to decode value %s (err %d)", val, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (len != sizeof(hb_val)) {
|
||||
BT_ERR("Unexpected value length (%d != %zu)", len,
|
||||
sizeof(hb_val));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pub->dst = hb_val.dst;
|
||||
pub->period = hb_val.period;
|
||||
pub->ttl = hb_val.ttl;
|
||||
pub->feat = hb_val.feat;
|
||||
pub->net_idx = hb_val.net_idx;
|
||||
|
||||
if (hb_val.indefinite) {
|
||||
pub->count = 0xffff;
|
||||
} else {
|
||||
pub->count = 0;
|
||||
}
|
||||
|
||||
BT_DBG("Restored heartbeat publication");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mod_set_bind(struct bt_mesh_model *mod, char *val)
|
||||
{
|
||||
int len, err, i;
|
||||
|
@ -578,6 +641,7 @@ const struct mesh_setting {
|
|||
{ "RPL", rpl_set },
|
||||
{ "NetKey", net_key_set },
|
||||
{ "AppKey", app_key_set },
|
||||
{ "HBPub", hb_pub_set },
|
||||
{ "s", sig_mod_set },
|
||||
{ "v", vnd_mod_set },
|
||||
};
|
||||
|
@ -653,6 +717,7 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
|
|||
|
||||
static int mesh_commit(void)
|
||||
{
|
||||
struct bt_mesh_hb_pub *hb_pub;
|
||||
int i;
|
||||
|
||||
BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
|
||||
|
@ -691,6 +756,13 @@ static int mesh_commit(void)
|
|||
|
||||
bt_mesh_model_foreach(commit_mod, NULL);
|
||||
|
||||
hb_pub = bt_mesh_hb_pub_get();
|
||||
if (hb_pub && hb_pub->dst != BT_MESH_ADDR_UNASSIGNED &&
|
||||
hb_pub->count && hb_pub->period) {
|
||||
BT_DBG("Starting heartbeat publication");
|
||||
k_work_submit(&hb_pub->timer.work);
|
||||
}
|
||||
|
||||
bt_mesh.valid = 1;
|
||||
|
||||
bt_mesh_net_start();
|
||||
|
@ -880,6 +952,40 @@ static void store_pending_rpl(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void store_pending_hb_pub(void)
|
||||
{
|
||||
char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))];
|
||||
struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
|
||||
struct hb_pub_val val;
|
||||
char *str;
|
||||
|
||||
if (!pub) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
|
||||
str = NULL;
|
||||
} else {
|
||||
val.indefinite = (pub->count = 0xffff);
|
||||
val.dst = pub->dst;
|
||||
val.period = pub->period;
|
||||
val.ttl = pub->ttl;
|
||||
val.feat = pub->feat;
|
||||
val.net_idx = pub->net_idx;
|
||||
|
||||
str = settings_str_from_bytes(&val, sizeof(val),
|
||||
buf, sizeof(buf));
|
||||
if (!str) {
|
||||
BT_ERR("Unable to encode hb pub as value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BT_DBG("Saving Heartbeat Publication as value %s",
|
||||
str ? str : "(null)");
|
||||
settings_save_one("bt/mesh/HBPub", str);
|
||||
}
|
||||
|
||||
static void clear_app_key(u16_t app_idx)
|
||||
{
|
||||
char path[20];
|
||||
|
@ -1163,6 +1269,10 @@ static void store_pending(struct k_work *work)
|
|||
store_pending_seq();
|
||||
}
|
||||
|
||||
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_HB_PUB_PENDING)) {
|
||||
store_pending_hb_pub();
|
||||
}
|
||||
|
||||
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_MOD_PENDING)) {
|
||||
bt_mesh_model_foreach(store_pending_mod, NULL);
|
||||
}
|
||||
|
@ -1255,6 +1365,11 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
|
|||
schedule_store(BT_MESH_KEYS_PENDING);
|
||||
}
|
||||
|
||||
void bt_mesh_store_hb_pub(void)
|
||||
{
|
||||
schedule_store(BT_MESH_HB_PUB_PENDING);
|
||||
}
|
||||
|
||||
void bt_mesh_clear_net(void)
|
||||
{
|
||||
schedule_store(BT_MESH_NET_PENDING);
|
||||
|
|
|
@ -10,6 +10,7 @@ void bt_mesh_store_seq(void);
|
|||
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_hb_pub(void);
|
||||
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_store_mod_pub(struct bt_mesh_model *mod);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue