diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index b4d0e94324..067a299602 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -341,6 +341,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 5d86dda5a6..666e117b64 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 @@ -77,3 +77,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 a1b0ff00de..0ffeec0fa4 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 @@ -104,4 +104,36 @@ 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); + #endif /* _ESP_BLE_MESH_LOCAL_DATA_OPERATION_API_H_ */ 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 540a3f666c..5b93995068 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 @@ -830,6 +830,8 @@ typedef enum { ESP_BLE_MESH_PROXY_CLIENT_SET_FILTER_TYPE_COMP_EVT, /*!< Proxy Client set filter type completion event */ ESP_BLE_MESH_PROXY_CLIENT_ADD_FILTER_ADDR_COMP_EVT, /*!< Proxy Client add filter address completion event */ ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT, /*!< Proxy Client remove filter address 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; @@ -1409,6 +1411,26 @@ typedef union { uint8_t conn_handle; /*!< Proxy connection handle */ uint16_t net_idx; /*!< Corresponding NetKey Index */ } proxy_client_remove_filter_addr_comp; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_MODEL_SUBSCRIBE_GROUP_ADDR_COMP_EVT + */ + struct { + 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 { + 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 680120dbef..72067d7956 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 @@ -38,6 +38,7 @@ #include "client_common.h" #include "state_binding.h" #include "settings.h" +#include "local_operation.h" #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_config_model.h" @@ -2014,6 +2015,30 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) break; } #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + 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 761e0fc035..f86577ebde 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 @@ -77,6 +77,8 @@ typedef enum { BTC_BLE_MESH_ACT_PROXY_CLIENT_SET_FILTER_TYPE, BTC_BLE_MESH_ACT_PROXY_CLIENT_ADD_FILTER_ADDR, BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR, + 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; @@ -290,6 +292,18 @@ typedef union { uint16_t addr_num; uint16_t *addr; } proxy_client_remove_filter_addr; + struct { + uint16_t element_addr; + uint16_t company_id; + uint16_t model_id; + uint16_t group_addr; + } model_sub_group_addr; + struct { + 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 0000000000..8439b89784 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_core/local_operation.c @@ -0,0 +1,123 @@ +/* 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" + +#define CID_NVAL 0xffff + +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 == 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 0000000000..3c51ec5021 --- /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_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/settings.c b/components/bt/esp_ble_mesh/mesh_core/settings.c index 9054986229..5706e70455 100644 --- a/components/bt/esp_ble_mesh/mesh_core/settings.c +++ b/components/bt/esp_ble_mesh/mesh_core/settings.c @@ -643,6 +643,10 @@ static int model_set_bind(bool vnd, struct bt_mesh_model *model, u16_t model_key return -EIO; } + if (exist == true) { + BT_INFO("Restored Model Bound AppKey, index %s", bt_hex(model->keys, sizeof(model->keys))); + } + return 0; } @@ -665,6 +669,10 @@ static int model_set_sub(bool vnd, struct bt_mesh_model *model, u16_t model_key) return -EIO; } + if (exist == true) { + BT_INFO("Restored Model Subscription, address %s", bt_hex(model->groups, sizeof(model->groups))); + } + return 0; }