From cd40f3ad52c3f88d267531b88b99cb9999044b11 Mon Sep 17 00:00:00 2001 From: lly Date: Tue, 14 Apr 2020 10:17:52 +0800 Subject: [PATCH] ble_mesh: Local model (un)subscribes group address --- components/bt/CMakeLists.txt | 1 + .../esp_ble_mesh_local_data_operation_api.c | 51 ++++++++ .../esp_ble_mesh_local_data_operation_api.h | 32 +++++ .../bt/esp_ble_mesh/api/esp_ble_mesh_defs.h | 22 ++++ .../bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 25 ++++ .../btc/include/btc_ble_mesh_prov.h | 14 ++ .../esp_ble_mesh/mesh_core/local_operation.c | 121 ++++++++++++++++++ .../esp_ble_mesh/mesh_core/local_operation.h | 29 +++++ 8 files changed, 295 insertions(+) create mode 100644 components/bt/esp_ble_mesh/mesh_core/local_operation.c create mode 100644 components/bt/esp_ble_mesh/mesh_core/local_operation.h diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 3d689b3f7..120754e0d 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -348,6 +348,7 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/mesh_core/friend.c" "esp_ble_mesh/mesh_core/health_cli.c" "esp_ble_mesh/mesh_core/health_srv.c" + "esp_ble_mesh/mesh_core/local_operation.c" "esp_ble_mesh/mesh_core/lpn.c" "esp_ble_mesh/mesh_core/main.c" "esp_ble_mesh/mesh_core/net.c" diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_local_data_operation_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_local_data_operation_api.c index 95a8039ff..943c91bff 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_local_data_operation_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_local_data_operation_api.c @@ -75,3 +75,54 @@ const esp_ble_mesh_comp_t *esp_ble_mesh_get_composition_data(void) return btc_ble_mesh_comp_get(); } +esp_err_t esp_ble_mesh_model_subscribe_group_addr(uint16_t element_addr, uint16_t company_id, + uint16_t model_id, uint16_t group_addr) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr) || + !ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) { + 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_MODEL_SUBSCRIBE_GROUP_ADDR; + + arg.model_sub_group_addr.element_addr = element_addr; + arg.model_sub_group_addr.company_id = company_id; + arg.model_sub_group_addr.model_id = model_id; + arg.model_sub_group_addr.group_addr = group_addr; + + 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_model_unsubscribe_group_addr(uint16_t element_addr, uint16_t company_id, + uint16_t model_id, uint16_t group_addr) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr) || + !ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) { + 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_MODEL_UNSUBSCRIBE_GROUP_ADDR; + + arg.model_unsub_group_addr.element_addr = element_addr; + arg.model_unsub_group_addr.company_id = company_id; + arg.model_unsub_group_addr.model_id = model_id; + arg.model_unsub_group_addr.group_addr = group_addr; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h index df8e2428a..0cd702e69 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h @@ -108,6 +108,38 @@ esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *ele */ const esp_ble_mesh_comp_t *esp_ble_mesh_get_composition_data(void); +/** + * @brief A local model of node or Provisioner subscribes a group address. + * + * @note This function shall not be invoked before node is provisioned or Provisioner is enabled. + * + * @param[in] element_addr: Unicast address of the element to which the model belongs. + * @param[in] company_id: A 16-bit company identifier. + * @param[in] model_id: A 16-bit model identifier. + * @param[in] group_addr: The group address to be subscribed. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_model_subscribe_group_addr(uint16_t element_addr, uint16_t company_id, + uint16_t model_id, uint16_t group_addr); + +/** + * @brief A local model of node or Provisioner unsubscribes a group address. + * + * @note This function shall not be invoked before node is provisioned or Provisioner is enabled. + * + * @param[in] element_addr: Unicast address of the element to which the model belongs. + * @param[in] company_id: A 16-bit company identifier. + * @param[in] model_id: A 16-bit model identifier. + * @param[in] group_addr: The subscribed group address. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_model_unsubscribe_group_addr(uint16_t element_addr, uint16_t company_id, + uint16_t model_id, uint16_t group_addr); + #ifdef __cplusplus } #endif diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index 27c823a18..59a2bee29 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -847,6 +847,8 @@ typedef enum { ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT, /*!< Proxy Client remove filter address completion event */ ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT, /*!< Start BLE advertising completion event */ ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT, /*!< Stop BLE advertising completion event */ + ESP_BLE_MESH_MODEL_SUBSCRIBE_GROUP_ADDR_COMP_EVT, /*!< Local model subscribes group address completion event */ + ESP_BLE_MESH_MODEL_UNSUBSCRIBE_GROUP_ADDR_COMP_EVT, /*!< Local model unsubscribes group address completion event */ ESP_BLE_MESH_DEINIT_MESH_COMP_EVT, /*!< De-initialize BLE Mesh stack completion event */ ESP_BLE_MESH_PROV_EVT_MAX, } esp_ble_mesh_prov_cb_event_t; @@ -1329,6 +1331,26 @@ typedef union { int err_code; /*!< Indicate the result of stopping BLE advertising */ uint8_t index; /*!< Index of the BLE advertising */ } stop_ble_advertising_comp; /*!< Event parameter of ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_MODEL_SUBSCRIBE_GROUP_ADDR_COMP_EVT + */ + struct ble_mesh_model_sub_group_addr_comp_param { + int err_code; /*!< Indicate the result of local model subscribing group address */ + uint16_t element_addr; /*!< Element address */ + uint16_t company_id; /*!< Company ID */ + uint16_t model_id; /*!< Model ID */ + uint16_t group_addr; /*!< Group Address */ + } model_sub_group_addr_comp; /*!< Event parameters of ESP_BLE_MESH_MODEL_SUBSCRIBE_GROUP_ADDR_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_MODEL_UNSUBSCRIBE_GROUP_ADDR_COMP_EVT + */ + struct ble_mesh_model_unsub_group_addr_comp_param { + int err_code; /*!< Indicate the result of local model unsubscribing group address */ + uint16_t element_addr; /*!< Element address */ + uint16_t company_id; /*!< Company ID */ + uint16_t model_id; /*!< Model ID */ + uint16_t group_addr; /*!< Group Address */ + } model_unsub_group_addr_comp; /*!< Event parameters of ESP_BLE_MESH_MODEL_UNSUBSCRIBE_GROUP_ADDR_COMP_EVT */ /** * @brief ESP_BLE_MESH_DEINIT_MESH_COMP_EVT */ diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index d4c063011..f0d4ea066 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -44,6 +44,7 @@ #include "time_scene_client.h" #include "client_common.h" #include "state_binding.h" +#include "local_operation.h" #include "esp_ble_mesh_common_api.h" #include "esp_ble_mesh_provisioning_api.h" @@ -1898,6 +1899,30 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) bt_mesh_stop_ble_advertising(arg->stop_ble_advertising.index); break; #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + case BTC_BLE_MESH_ACT_MODEL_SUBSCRIBE_GROUP_ADDR: + act = ESP_BLE_MESH_MODEL_SUBSCRIBE_GROUP_ADDR_COMP_EVT; + param.model_sub_group_addr_comp.element_addr = arg->model_sub_group_addr.element_addr; + param.model_sub_group_addr_comp.company_id = arg->model_sub_group_addr.company_id; + param.model_sub_group_addr_comp.model_id = arg->model_sub_group_addr.model_id; + param.model_sub_group_addr_comp.group_addr = arg->model_sub_group_addr.group_addr; + param.model_sub_group_addr_comp.err_code = + bt_mesh_model_subscribe_group_addr(arg->model_sub_group_addr.element_addr, + arg->model_sub_group_addr.company_id, + arg->model_sub_group_addr.model_id, + arg->model_sub_group_addr.group_addr); + break; + case BTC_BLE_MESH_ACT_MODEL_UNSUBSCRIBE_GROUP_ADDR: + act = ESP_BLE_MESH_MODEL_UNSUBSCRIBE_GROUP_ADDR_COMP_EVT; + param.model_unsub_group_addr_comp.element_addr = arg->model_unsub_group_addr.element_addr; + param.model_unsub_group_addr_comp.company_id = arg->model_unsub_group_addr.company_id; + param.model_unsub_group_addr_comp.model_id = arg->model_unsub_group_addr.model_id; + param.model_unsub_group_addr_comp.group_addr = arg->model_unsub_group_addr.group_addr; + param.model_unsub_group_addr_comp.err_code = + bt_mesh_model_unsubscribe_group_addr(arg->model_unsub_group_addr.element_addr, + arg->model_unsub_group_addr.company_id, + arg->model_unsub_group_addr.model_id, + arg->model_unsub_group_addr.group_addr); + break; case BTC_BLE_MESH_ACT_DEINIT_MESH: act = ESP_BLE_MESH_DEINIT_MESH_COMP_EVT; param.deinit_mesh_comp.err_code = bt_mesh_deinit((struct bt_mesh_deinit_param *)&arg->mesh_deinit.param); diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h index 62f52ccee..e56425f15 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h @@ -70,6 +70,8 @@ typedef enum { BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR, BTC_BLE_MESH_ACT_START_BLE_ADVERTISING, BTC_BLE_MESH_ACT_STOP_BLE_ADVERTISING, + BTC_BLE_MESH_ACT_MODEL_SUBSCRIBE_GROUP_ADDR, + BTC_BLE_MESH_ACT_MODEL_UNSUBSCRIBE_GROUP_ADDR, BTC_BLE_MESH_ACT_DEINIT_MESH, } btc_ble_mesh_prov_act_t; @@ -249,6 +251,18 @@ typedef union { struct ble_mesh_stop_ble_advertising_args { uint8_t index; } stop_ble_advertising; + struct ble_mesh_model_sub_group_addr_args { + uint16_t element_addr; + uint16_t company_id; + uint16_t model_id; + uint16_t group_addr; + } model_sub_group_addr; + struct ble_mesh_model_unsub_group_addr_args { + uint16_t element_addr; + uint16_t company_id; + uint16_t model_id; + uint16_t group_addr; + } model_unsub_group_addr; struct ble_mesh_deinit_args { esp_ble_mesh_deinit_param_t param; } mesh_deinit; diff --git a/components/bt/esp_ble_mesh/mesh_core/local_operation.c b/components/bt/esp_ble_mesh/mesh_core/local_operation.c new file mode 100644 index 000000000..9e2ab3f5e --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_core/local_operation.c @@ -0,0 +1,121 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Additional Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "mesh.h" +#include "lpn.h" +#include "crypto.h" +#include "access.h" +#include "foundation.h" +#include "transport.h" +#include "mesh_main.h" +#include "settings.h" + +static struct bt_mesh_model *find_model(u16_t elem_addr, u16_t cid, u16_t mod_id) +{ + struct bt_mesh_elem *elem = NULL; + + if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { + BT_ERR("%s, Not a unicast address 0x%04x", __func__, elem_addr); + return NULL; + } + + elem = bt_mesh_elem_find(elem_addr); + if (elem == NULL) { + BT_ERR("%s, No element found, addr 0x%04x", __func__, elem_addr); + return NULL; + } + + if (cid == BLE_MESH_CID_NVAL) { + return bt_mesh_model_find(elem, mod_id); + } else { + return bt_mesh_model_find_vnd(elem, cid, mod_id); + } +} + +int bt_mesh_model_subscribe_group_addr(u16_t elem_addr, u16_t cid, + u16_t mod_id, u16_t group_addr) +{ + struct bt_mesh_model *model = NULL; + int i; + + model = find_model(elem_addr, cid, mod_id); + if (model == NULL) { + BT_ERR("Subscribe, model not found, cid 0x%04x, mod_id 0x%04x", cid, mod_id); + return -ENODEV; + } + + if (!BLE_MESH_ADDR_IS_GROUP(group_addr)) { + BT_ERR("Subscribe, not a group address 0x%04x", group_addr); + return -EINVAL; + } + + if (bt_mesh_model_find_group(model, group_addr)) { + BT_INFO("Group address 0x%04x already exists", group_addr); + return 0; + } + + for (i = 0; i < ARRAY_SIZE(model->groups); i++) { + if (model->groups[i] == BLE_MESH_ADDR_UNASSIGNED) { + model->groups[i] = group_addr; + + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { + bt_mesh_store_mod_sub(model); + } + + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { + bt_mesh_lpn_group_add(group_addr); + } + + BT_INFO("Subscribe group address 0x%04x", group_addr); + return 0; + } + } + + BT_ERR("Subscribe, model sub is full!"); + return -ENOMEM; +} + +int bt_mesh_model_unsubscribe_group_addr(u16_t elem_addr, u16_t cid, + u16_t mod_id, u16_t group_addr) +{ + struct bt_mesh_model *model = NULL; + u16_t *match = NULL; + + model = find_model(elem_addr, cid, mod_id); + if (model == NULL) { + BT_ERR("Unsubscribe, model not found, cid 0x%04x, mod_id 0x%04x", cid, mod_id); + return -ENODEV; + } + + if (!BLE_MESH_ADDR_IS_GROUP(group_addr)) { + BT_ERR("Unsubscribe, not a group address 0x%04x", group_addr); + return -EINVAL; + } + + match = bt_mesh_model_find_group(model, group_addr); + if (match == NULL) { + BT_WARN("Group address 0x%04x not exists", group_addr); + return -EEXIST; + } + + *match = BLE_MESH_ADDR_UNASSIGNED; + + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { + bt_mesh_store_mod_sub(model); + } + + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { + bt_mesh_lpn_group_del(&group_addr, 1); + } + + BT_INFO("Unsubscribe group address 0x%04x", group_addr); + return 0; +} diff --git a/components/bt/esp_ble_mesh/mesh_core/local_operation.h b/components/bt/esp_ble_mesh/mesh_core/local_operation.h new file mode 100644 index 000000000..3c51ec502 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_core/local_operation.h @@ -0,0 +1,29 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Additional Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _LOCAL_OPERATION_H_ +#define _LOCAL_OPERATION_H_ + +#include "mesh_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int bt_mesh_model_subscribe_group_addr(u16_t elem_addr, u16_t mod_id, + u16_t cid, u16_t group_addr); + +int bt_mesh_model_unsubscribe_group_addr(u16_t elem_addr, u16_t cid, + u16_t mod_id, u16_t group_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* _LOCAL_OPERATION_H_ */