Merge branch 'feat/ble_mesh_provisioner_recv_hb_support' into 'master'

ble_mesh: stack: Provisioner supports receiving heartbeat

Closes BLEMESH-259

See merge request espressif/esp-idf!11244
This commit is contained in:
Island 2020-11-23 20:02:33 +08:00
commit 58f11c0c33
10 changed files with 536 additions and 4 deletions

View File

@ -195,6 +195,28 @@ if BLE_MESH
This option specifies how many application keys the Provisioner can have.
Indeed, this value decides the number of the application keys which can be added by a Provisioner.
config BLE_MESH_PROVISIONER_RECV_HB
bool "Support receiving Heartbeat messages"
default n
help
When this option is enabled, Provisioner can call specific functions to enable
or disable receiving Heartbeat messages and notify them to the application layer.
if BLE_MESH_PROVISIONER_RECV_HB
config BLE_MESH_PROVISIONER_RECV_HB_FILTER_SIZE
int "Maximum number of filter entries for receiving Heartbeat messages"
default 3
range 1 1000
help
This option specifies how many heartbeat filter entries Provisioner supports.
The heartbeat filter (acceptlist or rejectlist) entries are used to store a
list of SRC and DST which can be used to decide if a heartbeat message will
be processed and notified to the application layer by Provisioner.
Note: The filter is an empty rejectlist by default.
endif # BLE_MESH_PROVISIONER_RECV_HB
endif # BLE_MESH_PROVISIONER
# Virtual option enabled whenever Generic Provisioning layer is needed

View File

@ -528,6 +528,76 @@ const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx)
{
return bt_mesh_provisioner_local_net_key_get(net_idx);
}
#if CONFIG_BLE_MESH_PROVISIONER_RECV_HB
esp_err_t esp_ble_mesh_provisioner_recv_heartbeat(bool enable)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_ENABLE_HEARTBEAT_RECV;
arg.enable_heartbeat_recv.enable = enable;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_type(uint8_t type)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (type > ESP_BLE_MESH_HEARTBEAT_FILTER_REJECTLIST) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE;
arg.set_heartbeat_filter_type.type = type;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, esp_ble_mesh_heartbeat_filter_info_t *info)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (op > ESP_BLE_MESH_HEARTBEAT_FILTER_REMOVE || info == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(info->hb_src) &&
!ESP_BLE_MESH_ADDR_IS_UNICAST(info->hb_dst) &&
!ESP_BLE_MESH_ADDR_IS_GROUP(info->hb_dst)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_INFO;
arg.set_heartbeat_filter_info.op = op;
arg.set_heartbeat_filter_info.hb_src = info->hb_src;
arg.set_heartbeat_filter_info.hb_dst = info->hb_dst;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if (CONFIG_BLE_MESH_FAST_PROV)

View File

@ -413,6 +413,66 @@ esp_err_t esp_ble_mesh_provisioner_update_local_net_key(const uint8_t net_key[16
*/
const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx);
/**
* @brief This function is called by Provisioner to enable or disable receiving
* heartbeat messages.
*
* @note If enabling receiving heartbeat message successfully, the filter will
* be an empty rejectlist by default, which means all heartbeat messages
* received by the Provisioner will be reported to the application layer.
*
* @param[in] enable: Enable or disable receiving heartbeat messages.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_recv_heartbeat(bool enable);
/**
* @brief This function is called by Provisioner to set the heartbeat filter type.
*
* @note 1. If the filter type is not the same with the current value, then all the
* filter entries will be cleaned.
* 2. If the previous type is rejectlist, and changed to acceptlist, then the
* filter will be an empty acceptlist, which means no heartbeat messages
* will be reported. Users need to add SRC or DST into the filter entry,
* then heartbeat messages from the SRC or to the DST will be reported.
*
* @param[in] type: Heartbeat filter type (acceptlist or rejectlist).
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_type(uint8_t type);
/**
* @brief This function is called by Provisioner to add or remove a heartbeat filter entry.
*
* @note 1. If the operation is "ADD", the "hb_src" can be set to the SRC (can only be a
* unicast address) of heartbeat messages, and the "hb_dst" can be set to the
* DST (unicast address or group address), at least one of them needs to be set.
* - If only one of them is set, the filter entry will only use the configured
* SRC or DST to filter heartbeat messages.
* - If both of them are set, the SRC and DST will both be used to decide if a
* heartbeat message will be handled.
* - If SRC or DST already exists in some filter entry, then the corresponding
* entry will be cleaned firstly, then a new entry will be allocated to store
* the information.
* 2. If the operation is "REMOVE", the "hb_src" can be set to the SRC (can only be
* a unicast address) of heartbeat messages, and the "hb_dst" can be set to the
* DST (unicast address or group address), at least one of them needs to be set.
* - The filter entry with the same SRC or DST will be removed.
*
* @param[in] op: Add or REMOVE
* @param[in] info: Heartbeat filter entry information, including:
* hb_src - Heartbeat source address;
* hb_dst - Heartbeat destination address;
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, esp_ble_mesh_heartbeat_filter_info_t *info);
/**
* @brief This function is called to get fast provisioning application key.
*

View File

@ -801,6 +801,20 @@ typedef struct {
uint8_t scan_rsp_data[31]; /*!< Scan response data */
} esp_ble_mesh_ble_adv_data_t;
/*!< Provisioner heartbeat filter type */
#define ESP_BLE_MESH_HEARTBEAT_FILTER_ACCEPTLIST 0x00
#define ESP_BLE_MESH_HEARTBEAT_FILTER_REJECTLIST 0x01
/*!< Provisioner heartbeat filter operation */
#define ESP_BLE_MESH_HEARTBEAT_FILTER_ADD 0x00
#define ESP_BLE_MESH_HEARTBEAT_FILTER_REMOVE 0x01
/** Context of Provisioner heartbeat filter information to be set */
typedef struct {
uint16_t hb_src; /*!< Heartbeat source address (unicast address) */
uint16_t hb_dst; /*!< Heartbeat destination address (unicast address or group address) */
} esp_ble_mesh_heartbeat_filter_info_t;
/*!< This enum value is the event of node/provisioner/fast provisioning */
typedef enum {
ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, /*!< Initialize BLE Mesh provisioning capabilities and internal data information completion event */
@ -852,6 +866,10 @@ typedef enum {
ESP_BLE_MESH_PROVISIONER_STORE_NODE_COMP_DATA_COMP_EVT, /*!< Provisioner store node composition data completion event */
ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_UUID_COMP_EVT, /*!< Provisioner delete node with uuid completion event */
ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_ADDR_COMP_EVT, /*!< Provisioner delete node with unicast address completion event */
ESP_BLE_MESH_PROVISIONER_ENABLE_HEARTBEAT_RECV_COMP_EVT, /*!< Provisioner start to receive heartbeat message completion event */
ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT, /*!< Provisioner set the heartbeat filter type completion event */
ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_INFO_COMP_EVT, /*!< Provisioner set the heartbeat filter information completion event */
ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT, /*!< Provisioner receive heartbeat message event */
ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT, /*!< Set fast provisioning information (e.g. unicast address range, net_idx, etc.) completion event */
ESP_BLE_MESH_SET_FAST_PROV_ACTION_COMP_EVT, /*!< Set fast provisioning action completion event */
ESP_BLE_MESH_HEARTBEAT_MESSAGE_RECV_EVT, /*!< Receive Heartbeat message event */
@ -1219,6 +1237,41 @@ typedef union {
int err_code; /*!< Indicate the result of deleting node with unicast address by the Provisioner */
uint16_t unicast_addr; /*!< Node unicast address */
} provisioner_delete_node_with_addr_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_ADDR_COMP_EVT */
/**
* @brief ESP_BLE_MESH_PROVISIONER_ENABLE_HEARTBEAT_RECV_COMP_EVT
*/
struct {
int err_code; /*!< Indicate the result of enabling/disabling to receive heartbeat messages by the Provisioner */
bool enable; /*!< Indicate enabling or disabling receiving heartbeat messages */
} provisioner_enable_heartbeat_recv_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_ENABLE_HEARTBEAT_RECV_COMP_EVT */
/**
* @brief ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT
*/
struct {
int err_code; /*!< Indicate the result of setting the heartbeat filter type by the Provisioner */
uint8_t type; /*!< Type of the filter used for receiving heartbeat messages */
} provisioner_set_heartbeat_filter_type_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT */
/**
* @brief ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_INFO_COMP_EVT
*/
struct {
int err_code; /*!< Indicate the result of setting the heartbeat filter address by the Provisioner */
uint8_t op; /*!< Operation (add, remove, clean) */
uint16_t hb_src; /*!< Heartbeat source address */
uint16_t hb_dst; /*!< Heartbeat destination address */
} provisioner_set_heartbeat_filter_info_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_INFO_COMP_EVT */
/**
* @brief ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT
*/
struct {
uint16_t hb_src; /*!< Heartbeat source address */
uint16_t hb_dst; /*!< Heartbeat destination address */
uint8_t init_ttl; /*!< Heartbeat InitTTL */
uint8_t rx_ttl; /*!< Heartbeat RxTTL */
uint8_t hops; /*!< Heartbeat hops (InitTTL - RxTTL + 1) */
uint16_t feature; /*!< Bit field of currently active features of the node */
int8_t rssi; /*!< RSSI of the heartbeat message */
} provisioner_recv_heartbeat; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT */
/**
* @brief ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT
*/

View File

@ -820,9 +820,29 @@ const esp_ble_mesh_node_t **btc_ble_mesh_provisioner_get_node_table_entry(void)
{
return (const esp_ble_mesh_node_t **)bt_mesh_provisioner_get_node_table_entry();
}
#if CONFIG_BLE_MESH_PROVISIONER_RECV_HB
static void btc_ble_mesh_provisioner_recv_heartbeat_cb(u16_t hb_src, u16_t hb_dst,
u8_t init_ttl, u8_t rx_ttl,
u8_t hops, u16_t feat, s8_t rssi)
{
esp_ble_mesh_prov_cb_param_t mesh_param = {0};
mesh_param.provisioner_recv_heartbeat.hb_src = hb_src;
mesh_param.provisioner_recv_heartbeat.hb_dst = hb_dst;
mesh_param.provisioner_recv_heartbeat.init_ttl = init_ttl;
mesh_param.provisioner_recv_heartbeat.rx_ttl = rx_ttl;
mesh_param.provisioner_recv_heartbeat.hops = hops;
mesh_param.provisioner_recv_heartbeat.feature = feat;
mesh_param.provisioner_recv_heartbeat.rssi = rssi;
btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
#endif /* CONFIG_BLE_MESH_PROVISIONER */
static void btc_ble_mesh_heartbeat_msg_recv_cb(u8_t hops, u16_t feature)
static void btc_ble_mesh_node_recv_heartbeat_cb(u8_t hops, u16_t feature)
{
esp_ble_mesh_prov_cb_param_t mesh_param = {0};
@ -1197,7 +1217,7 @@ static void btc_ble_mesh_model_op_set(esp_ble_mesh_model_t *model)
model->cb = (esp_ble_mesh_model_cbs_t *)&bt_mesh_cfg_srv_cb;
struct bt_mesh_cfg_srv *srv = (struct bt_mesh_cfg_srv *)model->user_data;
if (srv) {
srv->hb_sub.func = btc_ble_mesh_heartbeat_msg_recv_cb;
srv->hb_sub.func = btc_ble_mesh_node_recv_heartbeat_cb;
}
break;
}
@ -1997,6 +2017,31 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
param.provisioner_delete_node_with_addr_comp.err_code =
bt_mesh_provisioner_delete_node_with_node_addr(arg->delete_node_with_addr.unicast_addr);
break;
#if CONFIG_BLE_MESH_PROVISIONER_RECV_HB
case BTC_BLE_MESH_ACT_PROVISIONER_ENABLE_HEARTBEAT_RECV:
act = ESP_BLE_MESH_PROVISIONER_ENABLE_HEARTBEAT_RECV_COMP_EVT;
param.provisioner_enable_heartbeat_recv_comp.enable = arg->enable_heartbeat_recv.enable;
param.provisioner_enable_heartbeat_recv_comp.err_code =
bt_mesh_provisioner_recv_heartbeat(arg->enable_heartbeat_recv.enable ?
btc_ble_mesh_provisioner_recv_heartbeat_cb : NULL);
break;
case BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE:
act = ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT;
param.provisioner_set_heartbeat_filter_type_comp.type = arg->set_heartbeat_filter_type.type;
param.provisioner_set_heartbeat_filter_type_comp.err_code =
bt_mesh_provisioner_set_heartbeat_filter_type(arg->set_heartbeat_filter_type.type);
break;
case BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_INFO:
act = ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_INFO_COMP_EVT;
param.provisioner_set_heartbeat_filter_info_comp.op = arg->set_heartbeat_filter_info.op;
param.provisioner_set_heartbeat_filter_info_comp.hb_src = arg->set_heartbeat_filter_info.hb_src;
param.provisioner_set_heartbeat_filter_info_comp.hb_dst = arg->set_heartbeat_filter_info.hb_dst;
param.provisioner_set_heartbeat_filter_info_comp.err_code =
bt_mesh_provisioner_set_heartbeat_filter_info(arg->set_heartbeat_filter_info.op,
arg->set_heartbeat_filter_info.hb_src,
arg->set_heartbeat_filter_info.hb_dst);
break;
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if CONFIG_BLE_MESH_FAST_PROV
case BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO:

View File

@ -63,6 +63,9 @@ typedef enum {
BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA,
BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_UUID,
BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_ADDR,
BTC_BLE_MESH_ACT_PROVISIONER_ENABLE_HEARTBEAT_RECV,
BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE,
BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_INFO,
BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO,
BTC_BLE_MESH_ACT_SET_FAST_PROV_ACTION,
BTC_BLE_MESH_ACT_LPN_ENABLE,
@ -217,6 +220,17 @@ typedef union {
struct ble_mesh_provisioner_delete_node_with_addr_args {
uint16_t unicast_addr;
} delete_node_with_addr;
struct {
bool enable;
} enable_heartbeat_recv;
struct {
uint8_t type;
} set_heartbeat_filter_type;
struct {
uint8_t op;
uint16_t hb_src;
uint16_t hb_dst;
} set_heartbeat_filter_info;
struct ble_mesh_set_fast_prov_info_args {
uint16_t unicast_min;
uint16_t unicast_max;

View File

@ -1544,4 +1544,235 @@ int bt_mesh_provisioner_store_node_info(struct bt_mesh_node *node)
}
#endif /* CONFIG_BLE_MESH_TEST_AUTO_ENTER_NETWORK */
#if CONFIG_BLE_MESH_PROVISIONER_RECV_HB
#define HEARTBEAT_FILTER_ACCEPTLIST 0x00
#define HEARTBEAT_FILTER_REJECTLIST 0x01
#define HEARTBEAT_FILTER_ADD 0x00
#define HEARTBEAT_FILTER_REMOVE 0x01
#define HEARTBEAT_FILTER_WITH_SRC BIT(0)
#define HEARTBEAT_FILTER_WITH_DST BIT(1)
#define HEARTBEAT_FILTER_WITH_BOTH (BIT(1) | BIT(0))
static struct heartbeat_recv {
struct heartbeat_filter {
u8_t type; /* Indicate if using src or dst or both to filter heartbeat messages */
u16_t src; /* Heartbeat source address (unicast address) */
u16_t dst; /* Heartbeat destination address (unicast address or group address) */
} filter[CONFIG_BLE_MESH_PROVISIONER_RECV_HB_FILTER_SIZE];
u8_t type; /* Heartbeat filter type */
bt_mesh_heartbeat_recv_cb_t cb; /* Heartbeat receive callback */
} hb_rx;
int bt_mesh_provisioner_recv_heartbeat(bt_mesh_heartbeat_recv_cb_t cb)
{
memset(&hb_rx, 0, sizeof(hb_rx));
/* Start with an empty rejectlist, which means all heartbeat messages will be reported */
hb_rx.type = HEARTBEAT_FILTER_REJECTLIST;
hb_rx.cb = cb;
return 0;
}
int bt_mesh_provisioner_set_heartbeat_filter_type(u8_t type)
{
if (type > HEARTBEAT_FILTER_REJECTLIST) {
BT_ERR("Invalid heartbeat filter type 0x%02x", type);
return -EINVAL;
}
/* If the heartbeat filter type is different with previous one,
* clear the existing filter entries.
*/
if (hb_rx.type != type) {
memset(&hb_rx, 0, offsetof(struct heartbeat_recv, cb));
hb_rx.type = type;
}
return 0;
}
static inline u8_t get_filter_addr_type(u16_t src, u16_t dst)
{
if (BLE_MESH_ADDR_IS_UNICAST(src)) {
if (BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)) {
return HEARTBEAT_FILTER_WITH_BOTH;
} else {
return HEARTBEAT_FILTER_WITH_SRC;
}
} else {
return HEARTBEAT_FILTER_WITH_DST;
}
}
static int hb_filter_alloc(u16_t src, u16_t dst)
{
int i;
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (filter->src == BLE_MESH_ADDR_UNASSIGNED &&
filter->dst == BLE_MESH_ADDR_UNASSIGNED) {
filter->type = get_filter_addr_type(src, dst);
filter->src = src;
filter->dst = dst;
return 0;
}
}
BT_ERR("Heartbeat filter is full!");
return -ENOMEM;
}
static int hb_filter_add(u16_t src, u16_t dst)
{
int i;
if (!BLE_MESH_ADDR_IS_UNICAST(src) &&
!BLE_MESH_ADDR_IS_UNICAST(dst) && !BLE_MESH_ADDR_IS_GROUP(dst)) {
BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst);
return -EINVAL;
}
/* Check if filter entries with the same src or dst exist. */
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if ((BLE_MESH_ADDR_IS_UNICAST(src) && filter->src == src) ||
((BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)) &&
filter->dst == dst)) {
memset(filter, 0, sizeof(struct heartbeat_filter));
}
}
return hb_filter_alloc(src, dst);
}
static int hb_filter_remove(u16_t src, u16_t dst)
{
int i;
if (!BLE_MESH_ADDR_IS_UNICAST(src) &&
!BLE_MESH_ADDR_IS_UNICAST(dst) && !BLE_MESH_ADDR_IS_GROUP(dst)) {
BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst);
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if ((BLE_MESH_ADDR_IS_UNICAST(src) && filter->src == src) ||
((BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)) &&
filter->dst == dst)) {
memset(filter, 0, sizeof(struct heartbeat_filter));
}
}
return 0;
}
int bt_mesh_provisioner_set_heartbeat_filter_info(u8_t op, u16_t src, u16_t dst)
{
switch (op) {
case HEARTBEAT_FILTER_ADD:
return hb_filter_add(src, dst);
case HEARTBEAT_FILTER_REMOVE:
return hb_filter_remove(src, dst);
default:
BT_ERR("Invalid heartbeat filter opcode 0x%02x", op);
return -EINVAL;
}
}
static bool filter_with_rejectlist(struct heartbeat_filter *filter,
u16_t hb_src, u16_t hb_dst)
{
switch (filter->type) {
case HEARTBEAT_FILTER_WITH_SRC:
if (hb_src == filter->src) {
return true;
}
break;
case HEARTBEAT_FILTER_WITH_DST:
if (hb_dst == filter->dst) {
return true;
}
break;
case HEARTBEAT_FILTER_WITH_BOTH:
if (hb_src == filter->src && hb_dst == filter->dst) {
return true;
}
break;
default:
BT_WARN("Unknown filter addr type 0x%02x", filter->type);
break;
}
return false;
}
static bool filter_with_acceptlist(struct heartbeat_filter *filter,
u16_t hb_src, u16_t hb_dst)
{
switch (filter->type) {
case HEARTBEAT_FILTER_WITH_SRC:
if (hb_src == filter->src) {
return false;
}
break;
case HEARTBEAT_FILTER_WITH_DST:
if (hb_dst == filter->dst) {
return false;
}
break;
case HEARTBEAT_FILTER_WITH_BOTH:
if (hb_src == filter->src && hb_dst == filter->dst) {
return false;
}
break;
default:
BT_WARN("Unknown filter addr type 0x%02x", filter->type);
return false;
}
return true;
}
void bt_mesh_provisioner_heartbeat(u16_t hb_src, u16_t hb_dst,
u8_t init_ttl, u8_t rx_ttl,
u8_t hops, u16_t feat, s8_t rssi)
{
int i;
if (hb_rx.cb == NULL) {
BT_DBG("Receiving heartbeat is not enabled");
return;
}
for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) {
struct heartbeat_filter *filter = &hb_rx.filter[i];
if (hb_rx.type == HEARTBEAT_FILTER_REJECTLIST) {
if (filter_with_rejectlist(filter, hb_src, hb_dst)) {
BT_DBG("Filtered by rejectlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
return;
}
} else {
if (filter_with_acceptlist(filter, hb_src, hb_dst)) {
BT_DBG("Filtered by acceptlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst);
return;
}
}
}
if (hb_rx.cb) {
hb_rx.cb(hb_src, hb_dst, init_ttl, rx_ttl, hops, feat, rssi);
}
}
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
#endif /* CONFIG_BLE_MESH_PROVISIONER */

View File

@ -125,6 +125,20 @@ int bt_mesh_provisioner_local_net_key_del(u16_t net_idx, bool store);
int bt_mesh_provisioner_bind_local_model_app_idx(u16_t elem_addr, u16_t mod_id,
u16_t cid, u16_t app_idx);
typedef void (* bt_mesh_heartbeat_recv_cb_t)(u16_t hb_src, u16_t hb_dst,
u8_t init_ttl, u8_t rx_ttl,
u8_t hops, u16_t feat, s8_t rssi);
int bt_mesh_provisioner_recv_heartbeat(bt_mesh_heartbeat_recv_cb_t cb);
int bt_mesh_provisioner_set_heartbeat_filter_type(u8_t filter_type);
int bt_mesh_provisioner_set_heartbeat_filter_info(u8_t op, u16_t src, u16_t dst);
void bt_mesh_provisioner_heartbeat(u16_t hb_src, u16_t hb_dst,
u8_t init_ttl, u8_t rx_ttl,
u8_t hops, u16_t feat, s8_t rssi);
/* Provisioner print own element information */
int bt_mesh_print_local_composition_data(void);

View File

@ -966,7 +966,8 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx,
return -EINVAL;
}
if (rx->ctx.recv_dst != hb_sub_dst) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned() &&
rx->ctx.recv_dst != hb_sub_dst) {
BT_WARN("Ignoring heartbeat to non-subscribed destination");
return 0;
}
@ -980,7 +981,13 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx,
rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
(hops == 1U) ? "" : "s", feat);
bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
} else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER_RECV_HB) && bt_mesh_is_provisioner_en()) {
bt_mesh_provisioner_heartbeat(rx->ctx.addr, rx->ctx.recv_dst,
init_ttl, rx->ctx.recv_ttl,
hops, feat, rx->ctx.recv_rssi);
}
return 0;
}

View File

@ -0,0 +1,16 @@
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BTDM_MODEM_SLEEP=n
CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE=y
CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN=y
CONFIG_BT_BTU_TASK_STACK_SIZE=4512
CONFIG_BLE_MESH=y
CONFIG_BLE_MESH_PROVISIONER=y
CONFIG_BLE_MESH_PROVISIONER_RECV_HB=y
CONFIG_BLE_MESH_PB_GATT=y
CONFIG_BLE_MESH_SETTINGS=y
CONFIG_BLE_MESH_CFG_CLI=y
CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y