mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ble_mesh: Provisioner supports receiving heartbeat
This commit is contained in:
parent
b6cb812499
commit
b6bcdad3db
@ -1755,6 +1755,17 @@ 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_HB_FILTER_SIZE
|
||||
int "Maximum number of filter entries for receiving heartbeat by Provisioner"
|
||||
default 3
|
||||
range 1 1000
|
||||
help
|
||||
This option specifies how many heartbeat filter entries Provisioner supports.
|
||||
The entries of heartbeat filter (whitelist or blacklist) are used to store a
|
||||
list of addresses which can be used to decide which heartbeat will be processed
|
||||
and notified to the application layer by Provisioner. And in default, the filter
|
||||
is blacklist and empty.
|
||||
|
||||
endif # BLE_MESH_PROVISIONER
|
||||
|
||||
# Virtual option enabled whenever Generic Provisioning layer is needed
|
||||
|
@ -719,6 +719,69 @@ uint8_t esp_ble_mesh_provisioner_get_free_settings_user_id_count(void)
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
|
||||
|
||||
esp_err_t esp_ble_mesh_provisioner_start_recv_heartbeat(void)
|
||||
{
|
||||
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_START_RECV_HEARTBEAT;
|
||||
|
||||
return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_type(uint8_t filter_type)
|
||||
{
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (filter_type > ESP_BLE_MESH_PROVISIONER_HB_FILTER_BLACKLIST) {
|
||||
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.filter_type = filter_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_flag, esp_ble_mesh_provisioner_hb_filter_info_t *info)
|
||||
{
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (op_flag > ESP_BLE_MESH_PROVISIONER_HB_FILTER_CLEAN || 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_flag = op_flag;
|
||||
arg.set_heartbeat_filter_info.hb_src = info->hb_src;
|
||||
arg.set_heartbeat_filter_info.hb_dst = info->hb_dst;
|
||||
arg.set_heartbeat_filter_info.expiry = info->expiry;
|
||||
|
||||
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 */
|
||||
|
||||
#if (CONFIG_BLE_MESH_FAST_PROV)
|
||||
|
@ -601,6 +601,81 @@ uint8_t esp_ble_mesh_provisioner_get_settings_index(const char *user_id);
|
||||
*/
|
||||
uint8_t esp_ble_mesh_provisioner_get_free_settings_user_id_count(void);
|
||||
|
||||
/**
|
||||
* @brief This function is called by Provisioner to start receiving and processing
|
||||
* heartbeat messages.
|
||||
*
|
||||
* @note If starting receiving heartbeat message successfully, the filter will be
|
||||
* an empty blacklist, which means all the heartbeat messages received by
|
||||
* Provisioner will be processed and reported to the application layer.
|
||||
*
|
||||
* @return ESP_OK on success or error code otherwise.
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_provisioner_start_recv_heartbeat(void);
|
||||
|
||||
/**
|
||||
* @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
|
||||
* addresses in the filter will be cleared.
|
||||
* 2. If the previous type is blacklist, and changed to whitelist, then the
|
||||
* filter will be an empty whitelist, which means no heartbeat messages will
|
||||
* be reported. And users need to add source addresses into the filter, then
|
||||
* heartbeat messages from these addresses will be reported.
|
||||
*
|
||||
* @param[in] filter_type: Heartbeat filter type (whitelist or blacklist).
|
||||
*
|
||||
* @return ESP_OK on success or error code otherwise.
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_type(uint8_t filter_type);
|
||||
|
||||
/**
|
||||
* @brief This function is called by Provisioner to add, remove or clean the corresponding
|
||||
* information from the heartbeat filter.
|
||||
*
|
||||
* @note 1. If the op_flag is "add", the hb_src can be set to the source address (can only
|
||||
* be a unicast address) of heartbeat messages, and the hb_dst can be set to the
|
||||
* destination address (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 source
|
||||
* address or destination address to filter heartbeat messages. If both of them are
|
||||
* set, then the source address and destination address will both be used to decide
|
||||
* if a heartbeat message can be reported.
|
||||
* And when the filter is whitelist, users can use the expiry (in seconds) to decide
|
||||
* how long the filter entry can be used to filter heartbeat messages. If the expiry
|
||||
* is set to 0, then the corresponding filter entry will be valid indefinitely. Only
|
||||
* when the filter entry is removed, cleaned or the filter_type is changed (whitelist
|
||||
* to blacklist), then the filter entry will be invalid.
|
||||
* If part of the filter information already exists, then the corresponding filter
|
||||
* entry will be updated. For example, if the source address already exists, and users
|
||||
* try to add a filter entry with the same source address. In this situation, the
|
||||
* existed filter entry will be updated. The same for the destination address.
|
||||
* And if the source address and destination address are both set, then all the filter
|
||||
* entries which contain any of the two addresses will be cleaned. After this, a new
|
||||
* filter entry will be allocated to store the filter information.
|
||||
* 2. If the op_flag is "remove", the hb_src can be set to the source address (can only
|
||||
* be a unicast address) of heartbeat messages, and the hb_dst can be set to the
|
||||
* destination address (unicast address or group address), at least one of them needs
|
||||
* to be set. If only one of the two addresses is set, then the filter entry with the
|
||||
* same source address or destination address will be removed. And if both of them are
|
||||
* set, then only the filter entry with the same source address and destination address
|
||||
* will be removed. User don't need to set the expiry parameter.
|
||||
* 3. If the op_flag is "clean", then Provisioner will remove all the information from
|
||||
* each heartbeat filter entry, users don't need to set the parameter info.
|
||||
*
|
||||
* @param[in] op_flag: Add, remove or clean
|
||||
* @param[in] info: Pointer to heartbeat filter entry information, the information includes:
|
||||
hb_src - Heartbeat source address;
|
||||
hb_dst - Heartbeat destination address;
|
||||
expiry - Period (in seconds) for receiving heartbeat messages
|
||||
*
|
||||
* @return ESP_OK on success or error code otherwise.
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_info(uint8_t op_flag, esp_ble_mesh_provisioner_hb_filter_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief This function is called to get fast provisioning application key.
|
||||
*
|
||||
|
@ -702,6 +702,7 @@ typedef struct {
|
||||
char name[ESP_BLE_MESH_NODE_NAME_MAX_LEN]; /*!< Node name */
|
||||
uint16_t comp_length; /*!< Length of Composition Data */
|
||||
uint8_t *comp_data; /*!< Value of Composition Data */
|
||||
uint32_t last_hb; /*!< Time (in seconds) when the last heartbeat is received */
|
||||
} __attribute__((packed)) esp_ble_mesh_node_t;
|
||||
|
||||
/** Context of fast provisioning which need to be set. */
|
||||
@ -731,6 +732,22 @@ typedef enum {
|
||||
PROXY_FILTER_BLACKLIST,
|
||||
} esp_ble_mesh_proxy_filter_type_t;
|
||||
|
||||
/*!< Provisioner heartbeat filter type */
|
||||
#define ESP_BLE_MESH_PROVISIONER_HB_FILTER_WHITELIST 0x0
|
||||
#define ESP_BLE_MESH_PROVISIONER_HB_FILTER_BLACKLIST 0x1
|
||||
|
||||
/*!< Provisioner heartbeat filter operation */
|
||||
#define ESP_BLE_MESH_PROVISIONER_HB_FILTER_ADD 0x0
|
||||
#define ESP_BLE_MESH_PROVISIONER_HB_FILTER_REMOVE 0x1
|
||||
#define ESP_BLE_MESH_PROVISIONER_HB_FILTER_CLEAN 0x2
|
||||
|
||||
/** 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) */
|
||||
uint32_t expiry; /*!< Expiry (in seconds) for the whitelist filter entry */
|
||||
} esp_ble_mesh_provisioner_hb_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 */
|
||||
@ -789,6 +806,10 @@ typedef enum {
|
||||
ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID_COMP_EVT, /*!< Provisioner release settings with user_id completion event */
|
||||
ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT, /*!< Provisioner delete settings with index completion event */
|
||||
ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID_COMP_EVT, /*!< Provisioner delete settings with user_id completion event */
|
||||
ESP_BLE_MESH_PROVISIONER_START_RECV_HEARTBEAT_COMP_EVT, /*!< Provisioner start to receive Heartbeat message completion event */
|
||||
ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT, /*!< Provisioner set the filter type of receiving heartbeat message completion event */
|
||||
ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_INFO_COMP_EVT, /*!< Provisioner set the filter information of receiving heartbeat message completion event */
|
||||
ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT, /*!< Provisioner receives 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 */
|
||||
@ -1195,6 +1216,41 @@ typedef union {
|
||||
int err_code; /*!< Indicate the result of deleting settings with user_id by the Provisioner */
|
||||
uint8_t index; /*!< Index of Provisioner settings */
|
||||
} provisioner_delete_settings_with_user_id_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID_COMP_EVT */
|
||||
/**
|
||||
* @brief ESP_BLE_MESH_PROVISIONER_START_RECV_HEARTBEAT_COMP_EVT
|
||||
*/
|
||||
struct ble_mesh_provisioner_start_recv_heartbeat_comp_param {
|
||||
int err_code; /*!< Indicate the result of starting to receive heartbeat messages by the Provisioner */
|
||||
} provisioner_start_recv_heartbeat_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_START_RECV_HEARTBEAT_COMP_EVT */
|
||||
/**
|
||||
* @brief ESP_BLE_MESH_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE_COMP_EVT
|
||||
*/
|
||||
struct ble_mesh_provisioner_set_heartbeat_filter_type_comp_param {
|
||||
int err_code; /*!< Indicate the result of setting the heartbeat filter type by the Provisioner */
|
||||
uint8_t filter_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 ble_mesh_provisioner_set_heartbeat_filter_info_comp_param {
|
||||
int err_code; /*!< Indicate the result of setting the heartbeat filter address by the Provisioner */
|
||||
uint8_t op_flag; /*!< Operation (add, remove, clean) */
|
||||
uint16_t hb_src; /*!< Heartbeat source address */
|
||||
uint16_t hb_dst; /*!< Heartbeat destination address */
|
||||
uint32_t expiry; /*!< Expiry of the source 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 ble_mesh_provisioner_recv_heartbeat_msg_param {
|
||||
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 */
|
||||
uint32_t count; /*!< Number of received heartbeat messages */
|
||||
} provisioner_recv_heartbeat_msg; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT */
|
||||
/**
|
||||
* @brief ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT
|
||||
*/
|
||||
|
@ -804,9 +804,28 @@ uint8_t btc_ble_mesh_provisioner_get_free_settings_user_id_count(void)
|
||||
return bt_mesh_provisioner_get_free_settings_user_id_count();
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
|
||||
|
||||
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, u32_t count)
|
||||
{
|
||||
esp_ble_mesh_prov_cb_param_t mesh_param = {0};
|
||||
|
||||
BT_DBG("%s", __func__);
|
||||
|
||||
mesh_param.provisioner_recv_heartbeat_msg.hb_src = hb_src;
|
||||
mesh_param.provisioner_recv_heartbeat_msg.hb_dst = hb_dst;
|
||||
mesh_param.provisioner_recv_heartbeat_msg.init_ttl = init_ttl;
|
||||
mesh_param.provisioner_recv_heartbeat_msg.rx_ttl = rx_ttl;
|
||||
mesh_param.provisioner_recv_heartbeat_msg.hops = hops;
|
||||
mesh_param.provisioner_recv_heartbeat_msg.feature = feat;
|
||||
mesh_param.provisioner_recv_heartbeat_msg.count = count;
|
||||
|
||||
btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_RECV_HEARTBEAT_MESSAGE_EVT);
|
||||
return;
|
||||
}
|
||||
#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};
|
||||
|
||||
@ -1106,7 +1125,7 @@ static void btc_ble_mesh_model_op_add(esp_ble_mesh_model_t *model)
|
||||
model->op = (esp_ble_mesh_model_op_t *)bt_mesh_cfg_srv_op;
|
||||
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;
|
||||
}
|
||||
@ -1871,6 +1890,28 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
|
||||
¶m.provisioner_delete_settings_with_user_id_comp.index);
|
||||
break;
|
||||
#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
|
||||
case BTC_BLE_MESH_ACT_PROVISIONER_START_RECV_HEARTBEAT:
|
||||
act = ESP_BLE_MESH_PROVISIONER_START_RECV_HEARTBEAT_COMP_EVT;
|
||||
param.provisioner_start_recv_heartbeat_comp.err_code =
|
||||
bt_mesh_provisioner_start_recv_heartbeat(btc_ble_mesh_provisioner_recv_heartbeat_cb);
|
||||
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.filter_type = arg->set_heartbeat_filter_type.filter_type;
|
||||
param.provisioner_set_heartbeat_filter_type_comp.err_code =
|
||||
bt_mesh_provisioner_set_heartbeat_filter_type(arg->set_heartbeat_filter_type.filter_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_flag = arg->set_heartbeat_filter_info.op_flag;
|
||||
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.expiry = arg->set_heartbeat_filter_info.expiry;
|
||||
param.provisioner_set_heartbeat_filter_info_comp.err_code =
|
||||
bt_mesh_provisioner_set_heartbeat_filter_info(arg->set_heartbeat_filter_info.op_flag,
|
||||
arg->set_heartbeat_filter_info.hb_src, arg->set_heartbeat_filter_info.hb_dst,
|
||||
arg->set_heartbeat_filter_info.expiry);
|
||||
break;
|
||||
#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_RELEASE_SETTINGS_WITH_USER_ID,
|
||||
BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX,
|
||||
BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID,
|
||||
BTC_BLE_MESH_ACT_PROVISIONER_START_RECV_HEARTBEAT,
|
||||
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,
|
||||
@ -229,6 +232,15 @@ typedef union {
|
||||
struct ble_mesh_provisioner_delete_settings_with_user_id_args {
|
||||
char user_id[ESP_BLE_MESH_SETTINGS_USER_ID_SIZE + 1];
|
||||
} delete_settings_with_user_id;
|
||||
struct ble_mesh_provisioner_set_heartbeat_filter_type_args {
|
||||
uint8_t filter_type;
|
||||
} set_heartbeat_filter_type;
|
||||
struct ble_mesh_provisioner_set_heartbeat_filter_info_args {
|
||||
uint8_t op_flag;
|
||||
uint16_t hb_src;
|
||||
uint16_t hb_dst;
|
||||
uint32_t expiry;
|
||||
} set_heartbeat_filter_info;
|
||||
struct ble_mesh_set_fast_prov_info_args {
|
||||
uint16_t unicast_min;
|
||||
uint16_t unicast_max;
|
||||
|
@ -34,6 +34,34 @@ static bt_mesh_mutex_t provisioner_lock;
|
||||
static u16_t all_node_count;
|
||||
static u16_t prov_node_count;
|
||||
|
||||
#define PROVISIONER_HB_FILTER_WHITELIST 0x0
|
||||
#define PROVISIONER_HB_FILTER_BLACKLIST 0x1
|
||||
|
||||
#define PROVISIONER_HB_FILTER_ADD 0x0
|
||||
#define PROVISIONER_HB_FILTER_REMOVE 0x1
|
||||
#define PROVISIONER_HB_FILTER_CLEAN 0x2
|
||||
|
||||
#define PROVISIONER_HB_FILTER_WITH_SRC BIT(0)
|
||||
#define PROVISIONER_HB_FILTER_WITH_DST BIT(1)
|
||||
#define PROVISIONER_HB_FILTER_WITH_BOTH (BIT(1) | BIT(0))
|
||||
|
||||
#define PROVISIONER_HB_RECV_MAX_COUNT 0xFFFFFFFF
|
||||
|
||||
static struct bt_mesh_provisioner_hb {
|
||||
struct provisioner_hb_rx {
|
||||
struct hb_rx_filter {
|
||||
u16_t src; /* Heartbeat source address, only unicast address */
|
||||
u16_t dst; /* Heartbeat destination address, unicast address or group address */
|
||||
s64_t expiry; /* In milliseconds, 0 means no expiry will be used */
|
||||
u32_t count; /* Number of received heartbeat messages when using whitelist */
|
||||
} filter[CONFIG_BLE_MESH_PROVISIONER_HB_FILTER_SIZE];
|
||||
u8_t filter_type; /* Heartbeat rx filter type */
|
||||
u32_t count; /* Number of received heartbeat messages when using blacklist */
|
||||
void (*func)(u16_t hb_src, u16_t hb_dst, u8_t init_ttl,
|
||||
u8_t rx_ttl, u8_t hops, u16_t feat, u32_t count);
|
||||
} rx;
|
||||
} provisioner_hb;
|
||||
|
||||
static int provisioner_remove_node(u16_t index, bool erase);
|
||||
|
||||
static void bt_mesh_provisioner_mutex_new(void)
|
||||
@ -224,6 +252,7 @@ int bt_mesh_provisioner_deinit(bool erase)
|
||||
bt_mesh_provisioner_release_netkey(erase);
|
||||
bt_mesh_provisioner_release_appkey(erase);
|
||||
bt_mesh_provisioner_release_node(erase);
|
||||
memset(&provisioner_hb.rx, 0, sizeof(provisioner_hb.rx));
|
||||
bt_mesh_provisioner_mutex_free();
|
||||
return 0;
|
||||
}
|
||||
@ -338,6 +367,7 @@ static int provisioner_store_node(struct bt_mesh_node *node, bool prov, bool sto
|
||||
}
|
||||
|
||||
memcpy(mesh_nodes[i], node, sizeof(struct bt_mesh_node));
|
||||
node->last_hb = k_uptime_get_32() / 1000;
|
||||
provisioner_node_count_inc(prov);
|
||||
if (index) {
|
||||
*index = i;
|
||||
@ -1537,6 +1567,314 @@ int bt_mesh_provisioner_bind_local_model_app_idx(u16_t elem_addr, u16_t mod_id,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int bt_mesh_provisioner_start_recv_heartbeat(void (*cb)(u16_t hb_src, u16_t hb_dst, u8_t init_ttl,
|
||||
u8_t rx_ttl, u8_t hops, u16_t feat, u32_t count)
|
||||
)
|
||||
{
|
||||
if (cb == NULL) {
|
||||
BT_ERR("%s, Invalid heartbeat callback", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&provisioner_hb.rx, 0, sizeof(provisioner_hb.rx));
|
||||
|
||||
/* Start with an empty blacklist, which means all heartbeat messages will be reported */
|
||||
provisioner_hb.rx.filter_type = PROVISIONER_HB_FILTER_BLACKLIST;
|
||||
provisioner_hb.rx.func = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_provisioner_set_heartbeat_filter_type(u8_t filter_type)
|
||||
{
|
||||
if (filter_type > PROVISIONER_HB_FILTER_BLACKLIST) {
|
||||
BT_ERR("%s, Invalid filter type 0x%02x", __func__, filter_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (provisioner_hb.rx.filter_type != filter_type) {
|
||||
memset(&provisioner_hb.rx, 0, offsetof(struct provisioner_hb_rx, func));
|
||||
}
|
||||
|
||||
provisioner_hb.rx.filter_type = filter_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8_t hb_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 PROVISIONER_HB_FILTER_WITH_BOTH;
|
||||
} else {
|
||||
return PROVISIONER_HB_FILTER_WITH_SRC;
|
||||
}
|
||||
} else {
|
||||
return PROVISIONER_HB_FILTER_WITH_DST;
|
||||
}
|
||||
}
|
||||
|
||||
static int hb_filter_alloc(u16_t src, u16_t dst, u32_t expiry)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
struct hb_rx_filter *filter = &provisioner_hb.rx.filter[i];
|
||||
if (filter->src == BLE_MESH_ADDR_UNASSIGNED &&
|
||||
filter->dst == BLE_MESH_ADDR_UNASSIGNED) {
|
||||
filter->src = src;
|
||||
filter->dst = dst;
|
||||
filter->expiry = expiry ? (k_uptime_get() + K_SECONDS(expiry)) : expiry;
|
||||
filter->count = 0U;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
BT_ERR("%s, Heartbeat filter is full, src 0x%04x, dst 0x%04x", __func__, src, dst);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void hb_filter_free(struct hb_rx_filter *filter)
|
||||
{
|
||||
filter->src = BLE_MESH_ADDR_UNASSIGNED;
|
||||
filter->dst = BLE_MESH_ADDR_UNASSIGNED;
|
||||
filter->expiry = 0;
|
||||
filter->count = 0U;
|
||||
}
|
||||
|
||||
static int hb_filter_add(u16_t src, u16_t dst, u32_t expiry)
|
||||
{
|
||||
struct hb_rx_filter *filter = NULL;
|
||||
u8_t type = 0U;
|
||||
int i;
|
||||
|
||||
if (!BLE_MESH_ADDR_IS_UNICAST(src) &&
|
||||
!BLE_MESH_ADDR_IS_UNICAST(dst) && !BLE_MESH_ADDR_IS_GROUP(dst)) {
|
||||
BT_ERR("%s, Invalid filter address, src 0x%04x, dst 0x%04x", __func__, src, dst);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
type = hb_filter_addr_type(src, dst);
|
||||
|
||||
switch (type) {
|
||||
case PROVISIONER_HB_FILTER_WITH_SRC: {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
if (src == filter->src) {
|
||||
filter->dst = dst;
|
||||
filter->expiry = expiry ? (k_uptime_get() + K_SECONDS(expiry)) : expiry;
|
||||
filter->count = 0U;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return hb_filter_alloc(src, dst, expiry);
|
||||
}
|
||||
case PROVISIONER_HB_FILTER_WITH_DST: {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
if (dst == filter->dst) {
|
||||
filter->src = src;
|
||||
filter->expiry = expiry ? (k_uptime_get() + K_SECONDS(expiry)) : expiry;
|
||||
filter->count = 0U;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return hb_filter_alloc(src, dst, expiry);
|
||||
}
|
||||
case PROVISIONER_HB_FILTER_WITH_BOTH: {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
/* Clear already existed src and dst in the filter */
|
||||
if (src == filter->src || dst == filter->dst) {
|
||||
filter->src = BLE_MESH_ADDR_UNASSIGNED;
|
||||
filter->dst = BLE_MESH_ADDR_UNASSIGNED;
|
||||
filter->expiry = 0;
|
||||
filter->count = 0U;
|
||||
}
|
||||
}
|
||||
return hb_filter_alloc(src, dst, expiry);
|
||||
}
|
||||
default:
|
||||
BT_ERR("%s, Unknown filter addr type 0x%02x", __func__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int hb_filter_remove(u16_t src, u16_t dst)
|
||||
{
|
||||
struct hb_rx_filter *filter = NULL;
|
||||
u8_t type = 0U;
|
||||
int i;
|
||||
|
||||
if (!BLE_MESH_ADDR_IS_UNICAST(src) &&
|
||||
!BLE_MESH_ADDR_IS_UNICAST(dst) && !BLE_MESH_ADDR_IS_GROUP(dst)) {
|
||||
BT_ERR("%s, Invalid filter address, src 0x%04x, dst 0x%04x", __func__, src, dst);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
type = hb_filter_addr_type(src, dst);
|
||||
|
||||
switch (type) {
|
||||
case PROVISIONER_HB_FILTER_WITH_SRC: {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
if (src == filter->src && dst == BLE_MESH_ADDR_UNASSIGNED) {
|
||||
hb_filter_free(filter);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case PROVISIONER_HB_FILTER_WITH_DST: {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
if (src == BLE_MESH_ADDR_UNASSIGNED && dst == filter->dst) {
|
||||
hb_filter_free(filter);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case PROVISIONER_HB_FILTER_WITH_BOTH: {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
if (src == filter->src && dst == filter->dst) {
|
||||
hb_filter_free(filter);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
BT_ERR("%s, Unknown filter addr type 0x%02x", __func__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_provisioner_set_heartbeat_filter_info(u8_t op_flag, u16_t src, u16_t dst, u32_t expiry)
|
||||
{
|
||||
switch (op_flag) {
|
||||
case PROVISIONER_HB_FILTER_ADD:
|
||||
return hb_filter_add(src, dst, expiry);
|
||||
case PROVISIONER_HB_FILTER_REMOVE:
|
||||
return hb_filter_remove(src, dst);
|
||||
case PROVISIONER_HB_FILTER_CLEAN:
|
||||
memset(&provisioner_hb.rx, 0, offsetof(struct provisioner_hb_rx, filter_type));
|
||||
return 0;
|
||||
default:
|
||||
BT_ERR("%s, Invalid operation flag 0x%02x", __func__, op_flag);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_provisioner_heartbeat(u16_t src, u16_t dst, u8_t init_ttl,
|
||||
u8_t rx_ttl, u8_t hops, u16_t feat)
|
||||
{
|
||||
struct hb_rx_filter *filter = NULL;
|
||||
struct bt_mesh_node *node = NULL;
|
||||
bool ignore = true;
|
||||
u32_t count = 0U;
|
||||
u8_t type = 0U;
|
||||
int i;
|
||||
|
||||
if (provisioner_hb.rx.func == NULL) {
|
||||
BT_DBG("Receiving heartbeat is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (provisioner_hb.rx.filter_type == PROVISIONER_HB_FILTER_BLACKLIST) {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
if (src == filter->src || dst == filter->dst) {
|
||||
type = hb_filter_addr_type(filter->src, filter->dst);
|
||||
switch (type) {
|
||||
case PROVISIONER_HB_FILTER_WITH_SRC:
|
||||
if (src == filter->src) {
|
||||
BT_INFO("Heartbeat filtered by backlist with src 0x%04x", src);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case PROVISIONER_HB_FILTER_WITH_DST:
|
||||
if (dst == filter->dst) {
|
||||
BT_INFO("Heartbeat filtered by backlist with dst 0x%04x", dst);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case PROVISIONER_HB_FILTER_WITH_BOTH:
|
||||
if (src == filter->src && dst == filter->dst) {
|
||||
BT_INFO("Heartbeat filtered by backlist with src 0x%04x, dst 0x%04x", src, dst);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s, Unknown filter addr type 0x%02x", __func__, type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (provisioner_hb.rx.count < PROVISIONER_HB_RECV_MAX_COUNT) {
|
||||
provisioner_hb.rx.count++;
|
||||
}
|
||||
|
||||
count = provisioner_hb.rx.count;
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(provisioner_hb.rx.filter); i++) {
|
||||
filter = &provisioner_hb.rx.filter[i];
|
||||
if (src == filter->src || dst == filter->dst) {
|
||||
type = hb_filter_addr_type(filter->src, filter->dst);
|
||||
switch (type) {
|
||||
case PROVISIONER_HB_FILTER_WITH_SRC:
|
||||
if (src == filter->src) {
|
||||
ignore = false;
|
||||
}
|
||||
break;
|
||||
case PROVISIONER_HB_FILTER_WITH_DST:
|
||||
if (dst == filter->dst) {
|
||||
ignore = false;
|
||||
}
|
||||
break;
|
||||
case PROVISIONER_HB_FILTER_WITH_BOTH:
|
||||
if (src == filter->src && dst == filter->dst) {
|
||||
ignore = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BT_ERR("%s, Unknown filter addr type 0x%02x", __func__, type);
|
||||
return;
|
||||
}
|
||||
if (ignore == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore == true) {
|
||||
BT_INFO("Heartbeat filtered by whitelist, src 0x%04x, dst 0x%04x", src, dst);
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter->expiry && k_uptime_get() > filter->expiry) {
|
||||
BT_INFO("Period for heartbeat from 0x%04x expired", src);
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter->count < PROVISIONER_HB_RECV_MAX_COUNT) {
|
||||
filter->count++;
|
||||
}
|
||||
|
||||
count = filter->count;
|
||||
}
|
||||
|
||||
node = bt_mesh_provisioner_get_node_with_addr(src);
|
||||
if (node) {
|
||||
node->last_hb = k_uptime_get_32() / 1000;
|
||||
}
|
||||
|
||||
BT_INFO("src 0x%04x, dst 0x%04x, init_ttl %u, rx_ttl %u, hops %u, feat 0x%04x, count %u",
|
||||
src, dst, init_ttl, rx_ttl, hops, feat, count);
|
||||
|
||||
if (provisioner_hb.rx.func) {
|
||||
provisioner_hb.rx.func(src, dst, init_ttl, rx_ttl, hops, feat, count);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_print_local_composition_data(void)
|
||||
{
|
||||
const struct bt_mesh_comp *comp = NULL;
|
||||
|
@ -41,6 +41,7 @@ struct bt_mesh_node {
|
||||
char name[BLE_MESH_NODE_NAME_SIZE]; /* Node name */
|
||||
u16_t comp_length; /* Length of Composition Data */
|
||||
u8_t *comp_data; /* Value of Composition Data */
|
||||
u32_t last_hb; /* Time (in seconds) when the last heartbeat is received */
|
||||
} __packed;
|
||||
|
||||
int bt_mesh_provisioner_init(void);
|
||||
@ -122,6 +123,18 @@ int bt_mesh_provisioner_local_net_key_delete(u16_t net_idx);
|
||||
int bt_mesh_provisioner_bind_local_model_app_idx(u16_t elem_addr, u16_t mod_id,
|
||||
u16_t cid, u16_t app_idx);
|
||||
|
||||
int bt_mesh_provisioner_start_recv_heartbeat(void (*cb)(u16_t src, u16_t dst, u8_t init_ttl,
|
||||
u8_t rx_ttl, u8_t hops, u16_t feat,
|
||||
u32_t count)
|
||||
);
|
||||
|
||||
int bt_mesh_provisioner_set_heartbeat_filter_type(u8_t filter_type);
|
||||
|
||||
int bt_mesh_provisioner_set_heartbeat_filter_info(u8_t op_flag, u16_t src, u16_t dst, u32_t expiry);
|
||||
|
||||
void bt_mesh_provisioner_heartbeat(u16_t src, u16_t dst, u8_t init_ttl,
|
||||
u8_t rx_ttl, u8_t hops, u16_t feat);
|
||||
|
||||
/* Provisioner print own element information */
|
||||
int bt_mesh_print_local_composition_data(void);
|
||||
|
||||
|
@ -885,7 +885,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;
|
||||
}
|
||||
@ -899,7 +900,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);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) &&
|
||||
bt_mesh_is_provisioner_en() && !bt_mesh_is_provisioned()) {
|
||||
bt_mesh_provisioner_heartbeat(
|
||||
rx->ctx.addr, rx->ctx.recv_dst, init_ttl, rx->ctx.recv_ttl, hops, feat);
|
||||
} else {
|
||||
bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user