mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
58f11c0c33
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user