diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 506575708..ed65333c9 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -298,12 +298,14 @@ if(CONFIG_BT_ENABLED) if(CONFIG_BLE_MESH) list(APPEND include_dirs + "esp_ble_mesh/mesh_common/include" "esp_ble_mesh/mesh_core" "esp_ble_mesh/mesh_core/include" - "esp_ble_mesh/mesh_core/settings" + "esp_ble_mesh/mesh_core/storage" "esp_ble_mesh/btc/include" "esp_ble_mesh/mesh_models/common/include" "esp_ble_mesh/mesh_models/client/include" + "esp_ble_mesh/mesh_models/server/include" "esp_ble_mesh/api/core/include" "esp_ble_mesh/api/models/include" "esp_ble_mesh/api") @@ -327,7 +329,13 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/btc/btc_ble_mesh_prov.c" "esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c" "esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c" - "esp_ble_mesh/mesh_core/settings/settings_nvs.c" + "esp_ble_mesh/mesh_common/mesh_aes_encrypt.c" + "esp_ble_mesh/mesh_common/mesh_atomic.c" + "esp_ble_mesh/mesh_common/mesh_buf.c" + "esp_ble_mesh/mesh_common/mesh_common.c" + "esp_ble_mesh/mesh_common/mesh_kernel.c" + "esp_ble_mesh/mesh_common/mesh_util.c" + "esp_ble_mesh/mesh_core/storage/settings_nvs.c" "esp_ble_mesh/mesh_core/access.c" "esp_ble_mesh/mesh_core/adv.c" "esp_ble_mesh/mesh_core/beacon.c" @@ -338,28 +346,30 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/mesh_core/health_cli.c" "esp_ble_mesh/mesh_core/health_srv.c" "esp_ble_mesh/mesh_core/lpn.c" - "esp_ble_mesh/mesh_core/mesh_aes_encrypt.c" - "esp_ble_mesh/mesh_core/mesh_atomic.c" - "esp_ble_mesh/mesh_core/mesh_buf.c" - "esp_ble_mesh/mesh_core/mesh_kernel.c" - "esp_ble_mesh/mesh_core/mesh_main.c" - "esp_ble_mesh/mesh_core/mesh_util.c" + "esp_ble_mesh/mesh_core/main.c" "esp_ble_mesh/mesh_core/net.c" "esp_ble_mesh/mesh_core/prov.c" "esp_ble_mesh/mesh_core/provisioner_beacon.c" "esp_ble_mesh/mesh_core/provisioner_main.c" "esp_ble_mesh/mesh_core/provisioner_prov.c" - "esp_ble_mesh/mesh_core/provisioner_proxy.c" - "esp_ble_mesh/mesh_core/proxy.c" + "esp_ble_mesh/mesh_core/proxy_client.c" + "esp_ble_mesh/mesh_core/proxy_server.c" "esp_ble_mesh/mesh_core/settings.c" "esp_ble_mesh/mesh_core/test.c" "esp_ble_mesh/mesh_core/transport.c" - "esp_ble_mesh/mesh_models/common/mesh_common.c" "esp_ble_mesh/mesh_models/client/client_common.c" "esp_ble_mesh/mesh_models/client/generic_client.c" "esp_ble_mesh/mesh_models/client/lighting_client.c" "esp_ble_mesh/mesh_models/client/sensor_client.c" - "esp_ble_mesh/mesh_models/client/time_scene_client.c") + "esp_ble_mesh/mesh_models/client/time_scene_client.c" + "esp_ble_mesh/mesh_models/server/device_property.c" + "esp_ble_mesh/mesh_models/server/generic_server.c" + "esp_ble_mesh/mesh_models/server/lighting_server.c" + "esp_ble_mesh/mesh_models/server/sensor_server.c" + "esp_ble_mesh/mesh_models/server/server_common.c" + "esp_ble_mesh/mesh_models/server/state_binding.c" + "esp_ble_mesh/mesh_models/server/state_transition.c" + "esp_ble_mesh/mesh_models/server/time_scene_server.c") endif() if(CONFIG_BT_NIMBLE_ENABLED) diff --git a/components/bt/common/btc/core/btc_task.c b/components/bt/common/btc/core/btc_task.c index d6c4bac87..6064d32d3 100644 --- a/components/bt/common/btc/core/btc_task.c +++ b/components/bt/common/btc/core/btc_task.c @@ -126,6 +126,10 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { [BTC_PID_LIGHTING_CLIENT] = {btc_ble_mesh_lighting_client_call_handler, btc_ble_mesh_lighting_client_cb_handler }, [BTC_PID_SENSOR_CLIENT] = {btc_ble_mesh_sensor_client_call_handler, btc_ble_mesh_sensor_client_cb_handler }, [BTC_PID_TIME_SCENE_CLIENT] = {btc_ble_mesh_time_scene_client_call_handler, btc_ble_mesh_time_scene_client_cb_handler}, + [BTC_PID_GENERIC_SERVER] = {NULL, btc_ble_mesh_generic_server_cb_handler }, + [BTC_PID_LIGHTING_SERVER] = {NULL, btc_ble_mesh_lighting_server_cb_handler }, + [BTC_PID_SENSOR_SERVER] = {NULL, btc_ble_mesh_sensor_server_cb_handler }, + [BTC_PID_TIME_SCENE_SERVER] = {NULL, btc_ble_mesh_time_scene_server_cb_handler}, #endif /* #if CONFIG_BLE_MESH */ }; diff --git a/components/bt/common/btc/include/btc/btc_task.h b/components/bt/common/btc/include/btc/btc_task.h index 45512d729..c1b2196a9 100644 --- a/components/bt/common/btc/include/btc/btc_task.h +++ b/components/bt/common/btc/include/btc/btc_task.h @@ -78,6 +78,10 @@ typedef enum { BTC_PID_LIGHTING_CLIENT, BTC_PID_SENSOR_CLIENT, BTC_PID_TIME_SCENE_CLIENT, + BTC_PID_GENERIC_SERVER, + BTC_PID_LIGHTING_SERVER, + BTC_PID_SENSOR_SERVER, + BTC_PID_TIME_SCENE_SERVER, #endif /* CONFIG_BLE_MESH */ BTC_PID_NUM, } btc_pid_t; //btc profile id diff --git a/components/bt/component.mk b/components/bt/component.mk index ed542dcc4..7d716f6d4 100644 --- a/components/bt/component.mk +++ b/components/bt/component.mk @@ -137,22 +137,25 @@ endif endif ifdef CONFIG_BLE_MESH -COMPONENT_ADD_INCLUDEDIRS += esp_ble_mesh/mesh_core \ +COMPONENT_ADD_INCLUDEDIRS += esp_ble_mesh/mesh_common/include \ + esp_ble_mesh/mesh_core \ esp_ble_mesh/mesh_core/include \ - esp_ble_mesh/mesh_core/settings \ + esp_ble_mesh/mesh_core/storage \ esp_ble_mesh/btc/include \ esp_ble_mesh/mesh_models/common/include \ esp_ble_mesh/mesh_models/client/include \ + esp_ble_mesh/mesh_models/server/include \ esp_ble_mesh/api/core/include \ esp_ble_mesh/api/models/include \ esp_ble_mesh/api -COMPONENT_SRCDIRS += esp_ble_mesh/mesh_core \ - esp_ble_mesh/mesh_core/settings \ - esp_ble_mesh/btc \ - esp_ble_mesh/mesh_models/common \ - esp_ble_mesh/mesh_models/client \ - esp_ble_mesh/api/core \ +COMPONENT_SRCDIRS += esp_ble_mesh/mesh_common \ + esp_ble_mesh/mesh_core \ + esp_ble_mesh/mesh_core/storage \ + esp_ble_mesh/btc \ + esp_ble_mesh/mesh_models/client \ + esp_ble_mesh/mesh_models/server \ + esp_ble_mesh/api/core \ esp_ble_mesh/api/models endif diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index e85be747e..44d7fec6b 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -60,7 +60,7 @@ if BLE_MESH config BLE_MESH_MAX_STORED_NODES int "Maximum number of nodes whose information can be stored" default 20 - range 1 1000 + range BLE_MESH_MAX_PROV_NODES 1000 help This option specifies the maximum number of nodes whose information can be stored by a Provisioner in its upper layer. @@ -71,7 +71,7 @@ if BLE_MESH config BLE_MESH_MAX_PROV_NODES int "Maximum number of devices that can be provisioned by Provisioner" default 20 - range 1 100 + range 1 1000 help This option specifies how many devices can be provisioned by a Provisioner. This value indicates the maximum number of unprovisioned devices which can be @@ -158,17 +158,28 @@ if BLE_MESH Enable this option to support BLE Mesh Proxy protocol used by PB-GATT and other proxy pdu transmission. - config BLE_MESH_GATT_PROXY - bool "BLE Mesh GATT Proxy Service" + config BLE_MESH_GATT_PROXY_SERVER + bool "BLE Mesh GATT Proxy Server" select BLE_MESH_PROXY + depends on BLE_MESH_NODE + default y help This option enables support for Mesh GATT Proxy Service, i.e. the ability to act as a proxy between a Mesh GATT Client and a Mesh network. This option should be enabled if a node is going to be a Proxy Server. + config BLE_MESH_GATT_PROXY_CLIENT + bool "BLE Mesh GATT Proxy Client" + select BLE_MESH_PROXY + default n + help + This option enables support for Mesh GATT Proxy Client. The Proxy Client + can use the GATT bearer to send mesh messages to a node that supports the + advertising bearer. + config BLE_MESH_NODE_ID_TIMEOUT int "Node Identity advertising timeout" - depends on BLE_MESH_GATT_PROXY + depends on BLE_MESH_GATT_PROXY_SERVER range 1 60 default 60 help @@ -185,7 +196,7 @@ if BLE_MESH config BLE_MESH_PROXY_FILTER_SIZE int "Maximum number of filter entries per Proxy Client" default 1 - default 3 if BLE_MESH_GATT_PROXY + default 3 if BLE_MESH_GATT_PROXY_SERVER range 1 32767 help This option specifies how many Proxy Filter entries the local node supports. @@ -416,14 +427,39 @@ if BLE_MESH config BLE_MESH_RELAY bool "Relay support" + depends on BLE_MESH_NODE + default y help Support for acting as a Mesh Relay Node. Enabling this option will allow a node to support the Relay feature, and the Relay feature can still be enabled or disabled by proper configuration messages. Disabling this option will let a node not support the Relay feature. + if BLE_MESH_RELAY + + config BLE_MESH_RELAY_ADV_BUF + bool "Use separate advertising buffers for relay packets" + default n + help + When selected, self-send packets will be put in a high-priority + queue and relay packets will be put in a low-priority queue. + + if BLE_MESH_RELAY_ADV_BUF + + config BLE_MESH_RELAY_ADV_BUF_COUNT + int "Number of advertising buffers for relay packets" + default 60 + range 6 256 + help + Number of advertising buffers for relay packets available. + + endif # BLE_MESH_RELAY_ADV_BUF + + endif # BLE_MESH_RELAY + config BLE_MESH_LOW_POWER bool "Support for Low Power features" + depends on BLE_MESH_NODE help Enable this option to operate as a Low Power Node. If low power consumption is required by a node, this option should be enabled. And once the node @@ -434,7 +470,7 @@ if BLE_MESH config BLE_MESH_LPN_ESTABLISHMENT bool "Perform Friendship establishment using low power" - default y + default n help Perform the Friendship establishment using low power with the help of a reduced scan duty cycle. The downside of this is that the node may miss @@ -446,7 +482,7 @@ if BLE_MESH config BLE_MESH_LPN_AUTO bool "Automatically start looking for Friend nodes once provisioned" - default y + default n help Once provisioned, automatically enable LPN functionality and start looking for Friend nodes. If this option is disabled LPN mode needs to be manually @@ -465,8 +501,8 @@ if BLE_MESH before starting to look for Friend nodes. config BLE_MESH_LPN_RETRY_TIMEOUT - int "Retry timeout for Friend Requests" - default 8 + int "Retry timeout for Friend requests" + default 6 range 1 3600 help Time in seconds between Friend Requests, if a previous Friend Request did @@ -555,6 +591,7 @@ if BLE_MESH config BLE_MESH_FRIEND bool "Support for acting as a Friend Node" + depends on BLE_MESH_NODE help Enable this option to be able to act as a Friend Node. @@ -689,16 +726,6 @@ if BLE_MESH endmenu #BLE Mesh NET BUF DEBUG LOG LEVEL - config BLE_MESH_IRQ_LOCK - bool "Used the IRQ lock instead of task lock" - help - To improve the real-time requirements of bt controller in BLE Mesh, - task lock is used to replace IRQ lock. - With this option enabled, interrupt lock instead of the mutex will - be used and the BLE Mesh stack will try to change interrupt level to - protect some critical situations. Users need to ensure that this option - is disabled so mutex will be used in the bottom layer. - config BLE_MESH_CLIENT_MSG_TIMEOUT int "Timeout(ms) for client message response" range 100 1200000 diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_low_power_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_low_power_api.c index 07301c837..df4053b1c 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_low_power_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_low_power_api.c @@ -15,10 +15,51 @@ #include #include "btc/btc_task.h" -#include "btc/btc_manage.h" #include "esp_err.h" #include "btc_ble_mesh_prov.h" #include "esp_ble_mesh_defs.h" +esp_err_t esp_ble_mesh_lpn_enable(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_LPN_ENABLE; + + return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_lpn_disable(bool force) +{ + 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_LPN_DISABLE; + + arg.lpn_disable.force = force; + + 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_lpn_poll(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_LPN_POLL; + + return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c index e8e3153b3..2878a35de 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c @@ -25,13 +25,13 @@ #define ESP_BLE_MESH_TX_SDU_MAX ((CONFIG_BLE_MESH_ADV_BUF_COUNT - 3) * 12) -static esp_err_t ble_mesh_send_msg(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint32_t opcode, - btc_ble_mesh_model_act_t act, - uint16_t length, uint8_t *data, - int32_t msg_timeout, bool need_rsp, - esp_ble_mesh_dev_role_t device_role) +static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model, + esp_ble_mesh_msg_ctx_t *ctx, + uint32_t opcode, + btc_ble_mesh_model_act_t act, + uint16_t length, uint8_t *data, + int32_t msg_timeout, bool need_rsp, + esp_ble_mesh_dev_role_t device_role) { btc_ble_mesh_model_args_t arg = {0}; uint8_t op_len = 0, mic_len = 0; @@ -41,7 +41,13 @@ static esp_err_t ble_mesh_send_msg(esp_ble_mesh_model_t *model, ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + if (ctx && ctx->addr == ESP_BLE_MESH_ADDR_UNASSIGNED) { + LOG_ERROR("%s, Invalid destination address 0x0000", __func__); + return ESP_ERR_INVALID_ARG; + } + if (device_role > ROLE_FAST_PROV) { + LOG_ERROR("%s, Invalid device role 0x%02x", __func__, device_role); return ESP_ERR_INVALID_ARG; } @@ -106,7 +112,7 @@ static esp_err_t ble_mesh_send_msg(esp_ble_mesh_model_t *model, arg.model_send.msg_timeout = msg_timeout; } - status = (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_prov_arg_deep_copy) + status = (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_model_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); osi_free(msg_data); @@ -165,8 +171,8 @@ esp_err_t esp_ble_mesh_server_model_send_msg(esp_ble_mesh_model_t *model, if (!model || !ctx) { return ESP_ERR_INVALID_ARG; } - return ble_mesh_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_SERVER_MODEL_SEND, - length, data, 0, false, ROLE_NODE); + return ble_mesh_model_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_SERVER_MODEL_SEND, + length, data, 0, false, ROLE_NODE); } esp_err_t esp_ble_mesh_client_model_send_msg(esp_ble_mesh_model_t *model, @@ -177,8 +183,8 @@ esp_err_t esp_ble_mesh_client_model_send_msg(esp_ble_mesh_model_t *model, if (!model || !ctx) { return ESP_ERR_INVALID_ARG; } - return ble_mesh_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND, - length, data, msg_timeout, need_rsp, device_role); + return ble_mesh_model_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND, + length, data, msg_timeout, need_rsp, device_role); } esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcode, @@ -188,8 +194,33 @@ esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcod if (!model || !model->pub || !model->pub->msg) { return ESP_ERR_INVALID_ARG; } - return ble_mesh_send_msg(model, NULL, opcode, BTC_BLE_MESH_ACT_MODEL_PUBLISH, - length, data, 0, false, device_role); + return ble_mesh_model_send_msg(model, NULL, opcode, BTC_BLE_MESH_ACT_MODEL_PUBLISH, + length, data, 0, false, device_role); +} + +esp_err_t esp_ble_mesh_server_model_update_state(esp_ble_mesh_model_t *model, + esp_ble_mesh_server_state_type_t type, + esp_ble_mesh_server_state_value_t *value) +{ + btc_ble_mesh_model_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!model || !value || type >= ESP_BLE_MESH_SERVER_MODEL_STATE_MAX) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + arg.model_update_state.model = model; + arg.model_update_state.type = type; + arg.model_update_state.value = value; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_MODEL; + msg.act = BTC_BLE_MESH_ACT_SERVER_MODEL_UPDATE_STATE; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_model_arg_deep_copy) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } esp_err_t esp_ble_mesh_node_local_reset(void) diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_provisioning_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_provisioning_api.c index b9501eb49..80f96ed05 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_provisioning_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_provisioning_api.c @@ -70,7 +70,7 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers) } esp_err_t esp_ble_mesh_node_set_oob_pub_key(uint8_t pub_key_x[32], uint8_t pub_key_y[32], - uint8_t private_key[32]) + uint8_t private_key[32]) { btc_ble_mesh_prov_args_t arg = {0}; btc_msg_t msg = {0}; @@ -157,7 +157,7 @@ esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name) #if (CONFIG_BLE_MESH_PROVISIONER) esp_err_t esp_ble_mesh_provisioner_read_oob_pub_key(uint8_t link_idx, uint8_t pub_key_x[32], - uint8_t pub_key_y[32]) + uint8_t pub_key_y[32]) { btc_ble_mesh_prov_args_t arg = {0}; btc_msg_t msg = {0}; diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_proxy_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_proxy_api.c index 950220da3..b64f789f0 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_proxy_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_proxy_api.c @@ -61,3 +61,117 @@ esp_err_t esp_ble_mesh_proxy_gatt_disable(void) return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_ble_mesh_proxy_client_connect(esp_ble_mesh_bd_addr_t addr, + esp_ble_mesh_addr_type_t addr_type, uint16_t net_idx) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!addr || addr_type > ESP_BLE_MESH_ADDR_TYPE_RANDOM) { + 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_PROXY_CLIENT_CONNECT; + + memcpy(arg.proxy_client_connect.addr, addr, BD_ADDR_LEN); + arg.proxy_client_connect.addr_type = addr_type; + arg.proxy_client_connect.net_idx = net_idx; + + 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_proxy_client_disconnect(uint8_t conn_handle) +{ + 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_PROXY_CLIENT_DISCONNECT; + + arg.proxy_client_disconnect.conn_handle = conn_handle; + + 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_proxy_client_set_filter_type(uint8_t conn_handle, + uint16_t net_idx, esp_ble_mesh_proxy_filter_type_t filter_type) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (filter_type > PROXY_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_PROXY_CLIENT_SET_FILTER_TYPE; + + arg.proxy_client_set_filter_type.conn_handle = conn_handle; + arg.proxy_client_set_filter_type.net_idx = net_idx; + arg.proxy_client_set_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_proxy_client_add_filter_addr(uint8_t conn_handle, + uint16_t net_idx, uint16_t *addr, uint16_t addr_num) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!addr || addr_num == 0) { + 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_PROXY_CLIENT_ADD_FILTER_ADDR; + + arg.proxy_client_add_filter_addr.conn_handle = conn_handle; + arg.proxy_client_add_filter_addr.net_idx = net_idx; + arg.proxy_client_add_filter_addr.addr_num = addr_num; + arg.proxy_client_add_filter_addr.addr = addr; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), btc_ble_mesh_prov_arg_deep_copy) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_proxy_client_remove_filter_addr(uint8_t conn_handle, + uint16_t net_idx, uint16_t *addr, uint16_t addr_num) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!addr || addr_num == 0) { + 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_PROXY_CLIENT_REMOVE_FILTER_ADDR; + + arg.proxy_client_remove_filter_addr.conn_handle = conn_handle; + arg.proxy_client_remove_filter_addr.net_idx = net_idx; + arg.proxy_client_remove_filter_addr.addr_num = addr_num; + arg.proxy_client_remove_filter_addr.addr = addr; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), btc_ble_mesh_prov_arg_deep_copy) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h index 48238c5eb..c579b2e05 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h @@ -17,4 +17,45 @@ #include "esp_ble_mesh_defs.h" +/** + * @brief Enable BLE Mesh device LPN functionality. + * + * @note This API enables LPN functionality. Once called, the proper + * Friend Request will be sent. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_lpn_enable(void); + +/** + * @brief Disable BLE Mesh device LPN functionality. + * + * @param[in] force: when disabling LPN functionality, use this flag to indicate + * whether directly clear corresponding information or just + * send friend clear to disable it if friendship has already + * been established. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_lpn_disable(bool force); + +/** + * @brief LPN tries to poll messages from the Friend Node. + * + * @note The Friend Poll message is sent by a Low Power node to ask the Friend + * node to send a message that it has stored for the Low Power node. + * Users can call this API to send Friend Poll message manually. If this + * API is not invoked, the bottom layer of the Low Power node will send + * Friend Poll before the PollTimeout timer expires. + * If the corresponding Friend Update is received and MD is set to 0, + * which means there are no messages for the Low Power node, then the + * Low Power node will stop scanning. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_lpn_poll(void); + #endif /* _ESP_BLE_MESH_LOW_POWER_API_H_ */ diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h index ae51b6081..ecf160d5d 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h @@ -134,6 +134,25 @@ esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcod uint16_t length, uint8_t *data, esp_ble_mesh_dev_role_t device_role); +/** + * @brief Update a server model state value. If the model publication + * state is set properly (e.g. publish address is set to a valid + * address), it will publish corresponding status message. + * + * @note Currently this API is used to update bound state value, not + * for all server model states. + * + * @param[in] model: Server model which is going to update the state. + * @param[in] type: Server model state type. + * @param[in] value: Server model state value. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_server_model_update_state(esp_ble_mesh_model_t *model, + esp_ble_mesh_server_state_type_t type, + esp_ble_mesh_server_state_value_t *value); + /** * @brief Reset the provisioning procedure of the local BLE Mesh node. * diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h index b947ac664..34dc38ce7 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h @@ -72,7 +72,7 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers); * @return ESP_OK on success or error code otherwise. */ esp_err_t esp_ble_mesh_node_set_oob_pub_key(uint8_t pub_key_x[32], uint8_t pub_key_y[32], - uint8_t private_key[32]); + uint8_t private_key[32]); /** * @brief Provide provisioning input OOB number. @@ -124,7 +124,7 @@ esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name); * @return ESP_OK on success or error code otherwise. */ esp_err_t esp_ble_mesh_provisioner_read_oob_pub_key(uint8_t link_idx, uint8_t pub_key_x[32], - uint8_t pub_key_y[32]); + uint8_t pub_key_y[32]); /** * @brief Provide provisioning input OOB string. diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_proxy_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_proxy_api.h index cb67b96a0..216a597ff 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_proxy_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_proxy_api.h @@ -49,5 +49,70 @@ esp_err_t esp_ble_mesh_proxy_gatt_enable(void); */ esp_err_t esp_ble_mesh_proxy_gatt_disable(void); +/** + * @brief Proxy Client creates a connection with the Proxy Server. + * + * @param[in] addr: Device address of the Proxy Server. + * @param[in] addr_type: Device address type(public or static random). + * @param[in] net_idx: NetKey Index related with Network ID in the Mesh Proxy + * advertising packet. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_proxy_client_connect(esp_ble_mesh_bd_addr_t addr, + esp_ble_mesh_addr_type_t addr_type, uint16_t net_idx); + +/** + * @brief Proxy Client terminates a connection with the Proxy Server. + * + * @param[in] conn_handle: Proxy connection handle. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_proxy_client_disconnect(uint8_t conn_handle); + +/** + * @brief Proxy Client sets the filter type of the Proxy Server. + * + * @param[in] conn_handle: Proxy connection handle. + * @param[in] net_idx: Corresponding NetKey Index. + * @param[in] filter_type: whitelist or blacklist. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_proxy_client_set_filter_type(uint8_t conn_handle, + uint16_t net_idx, esp_ble_mesh_proxy_filter_type_t filter_type); + +/** + * @brief Proxy Client adds address to the Proxy Server filter list. + * + * @param[in] conn_handle: Proxy connection handle. + * @param[in] net_idx: Corresponding NetKey Index. + * @param[in] addr: Pointer to the filter address. + * @param[in] addr_num: Number of the filter address. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle, + uint16_t net_idx, uint16_t *addr, uint16_t addr_num); + +/** + * @brief Proxy Client removes address from the Proxy Server filter list. + * + * @param[in] conn_handle: Proxy connection handle. + * @param[in] net_idx: Corresponding NetKey Index. + * @param[in] addr: Pointer to the filter address. + * @param[in] addr_num: Number of the filter address. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_proxy_client_remove_filter_addr(uint8_t conn_handle, + uint16_t net_idx, uint16_t *addr, uint16_t addr_num); + #endif /* _ESP_BLE_MESH_PROXY_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 1e6bfbc76..d59c29eb6 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 @@ -22,7 +22,7 @@ #include "mesh_main.h" #include "mesh.h" -#include "proxy.h" +#include "proxy_server.h" #include "foundation.h" #include "provisioner_main.h" @@ -109,499 +109,6 @@ typedef uint8_t esp_ble_mesh_octet8_t[ESP_BLE_MESH_OCTET8_LEN]; #define ESP_BLE_MESH_INVALID_NODE_INDEX (-1) -/*!< Foundation Models */ -#define ESP_BLE_MESH_MODEL_ID_CONFIG_SRV BLE_MESH_MODEL_ID_CFG_SRV -#define ESP_BLE_MESH_MODEL_ID_CONFIG_CLI BLE_MESH_MODEL_ID_CFG_CLI -#define ESP_BLE_MESH_MODEL_ID_HEALTH_SRV BLE_MESH_MODEL_ID_HEALTH_SRV -#define ESP_BLE_MESH_MODEL_ID_HEALTH_CLI BLE_MESH_MODEL_ID_HEALTH_CLI - -/*!< Models from the Mesh Model Specification */ -#define ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV BLE_MESH_MODEL_ID_GEN_ONOFF_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI BLE_MESH_MODEL_ID_GEN_ONOFF_CLI -#define ESP_BLE_MESH_MODEL_ID_GEN_LEVEL_SRV BLE_MESH_MODEL_ID_GEN_LEVEL_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_LEVEL_CLI BLE_MESH_MODEL_ID_GEN_LEVEL_CLI -#define ESP_BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI -#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI -#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI -#define ESP_BLE_MESH_MODEL_ID_GEN_BATTERY_SRV BLE_MESH_MODEL_ID_GEN_BATTERY_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_BATTERY_CLI BLE_MESH_MODEL_ID_GEN_BATTERY_CLI -#define ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_SRV BLE_MESH_MODEL_ID_GEN_LOCATION_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_CLI BLE_MESH_MODEL_ID_GEN_LOCATION_CLI -#define ESP_BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV -#define ESP_BLE_MESH_MODEL_ID_GEN_PROP_CLI BLE_MESH_MODEL_ID_GEN_PROP_CLI -#define ESP_BLE_MESH_MODEL_ID_SENSOR_SRV BLE_MESH_MODEL_ID_SENSOR_SRV -#define ESP_BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_SENSOR_CLI BLE_MESH_MODEL_ID_SENSOR_CLI -#define ESP_BLE_MESH_MODEL_ID_TIME_SRV BLE_MESH_MODEL_ID_TIME_SRV -#define ESP_BLE_MESH_MODEL_ID_TIME_SETUP_SRV BLE_MESH_MODEL_ID_TIME_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_TIME_CLI BLE_MESH_MODEL_ID_TIME_CLI -#define ESP_BLE_MESH_MODEL_ID_SCENE_SRV BLE_MESH_MODEL_ID_SCENE_SRV -#define ESP_BLE_MESH_MODEL_ID_SCENE_SETUP_SRV BLE_MESH_MODEL_ID_SCENE_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_SCENE_CLI BLE_MESH_MODEL_ID_SCENE_CLI -#define ESP_BLE_MESH_MODEL_ID_SCHEDULER_SRV BLE_MESH_MODEL_ID_SCHEDULER_SRV -#define ESP_BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_SCHEDULER_CLI BLE_MESH_MODEL_ID_SCHEDULER_CLI -#define ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI -#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SRV BLE_MESH_MODEL_ID_LIGHT_CTL_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_CLI BLE_MESH_MODEL_ID_LIGHT_CTL_CLI -#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_CLI BLE_MESH_MODEL_ID_LIGHT_HSL_CLI -#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_SRV BLE_MESH_MODEL_ID_LIGHT_XYL_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_CLI BLE_MESH_MODEL_ID_LIGHT_XYL_CLI -#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SRV BLE_MESH_MODEL_ID_LIGHT_LC_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV -#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_CLI BLE_MESH_MODEL_ID_LIGHT_LC_CLI - -/*!< The following opcodes will only be used in the esp_ble_mesh_config_client_get_state function. */ -typedef uint32_t esp_ble_mesh_opcode_config_client_get_t; /*!< esp_ble_mesh_opcode_config_client_get_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by esp_ble_mesh_config_client_get_state */ -#define ESP_BLE_MESH_MODEL_OP_BEACON_GET OP_BEACON_GET /*!< To determine the Secure Network Beacon state of a Configuration Server */ -#define ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET OP_DEV_COMP_DATA_GET /*!< To determine the Composition Data state of a Configuration Server, a Configuration - Client shall send a Config Composition Data Get message with the Page field value set - to 0xFF. The response is a Config Composition Data Status message that contains the last - page of the Composition Data state. If the Page field of the Config Composition Data Status - message contains a non-zero value, then the Configuration Client shall send another Composition - Data Get message with the Page field value set to one less than the Page field value of the - Config Composition Data Status message. */ -#define ESP_BLE_MESH_MODEL_OP_DEFAULT_TTL_GET OP_DEFAULT_TTL_GET /*!< To determine the Default TTL state of a Configuration Server */ -#define ESP_BLE_MESH_MODEL_OP_GATT_PROXY_GET OP_GATT_PROXY_GET /*!< To determine the GATT Proxy state of a Configuration Server */ -#define ESP_BLE_MESH_MODEL_OP_RELAY_GET OP_RELAY_GET /*!< To determine the Relay and Relay Retransmit states of a Configuration Server */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_GET OP_MOD_PUB_GET /*!< To determine the Publish Address, Publish AppKey Index, CredentialFlag, - Publish Period, Publish Retransmit Count, Publish Retransmit Interval Steps, - and Publish TTL states of a particular Model within the element */ -#define ESP_BLE_MESH_MODEL_OP_FRIEND_GET OP_FRIEND_GET /*!< To determine the Friend state of a Configuration Server */ -#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_GET OP_HEARTBEAT_PUB_GET /*!< To determine the Heartbeat Subscription Source, Heartbeat Subscription Destination, - Heartbeat Subscription Count Log, Heartbeat Subscription Period Log, Heartbeat - Subscription Min Hops, and Heartbeat Subscription Max Hops states of a node */ -#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_GET OP_HEARTBEAT_SUB_GET /*!< To determine the Heartbeat Subscription Source, Heartbeat Subscription Destination, - Heartbeat Subscription Count Log, Heartbeat Subscription Period Log, Heartbeat - Subscription Min Hops, and Heartbeat Subscription Max Hops states of a node */ -#define ESP_BLE_MESH_MODEL_OP_NET_KEY_GET OP_NET_KEY_GET /*!< To determine all NetKeys known to the node */ -#define ESP_BLE_MESH_MODEL_OP_APP_KEY_GET OP_APP_KEY_GET /*!< To determine all AppKeys bound to the NetKey */ -#define ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_GET OP_NODE_IDENTITY_GET /*!< To get the current Node Identity state for a subnet */ -#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_SUB_GET OP_MOD_SUB_GET /*!< To get the list of subscription addresses of a model within the element */ -#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_SUB_GET OP_MOD_SUB_GET_VND /*!< To get the list of subscription addresses of a model within the element */ -#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_APP_GET OP_SIG_MOD_APP_GET /*!< To request report of all AppKeys bound to the SIG Model */ -#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_APP_GET OP_VND_MOD_APP_GET /*!< To request report of all AppKeys bound to the Vendor Model */ -#define ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_GET OP_KRP_GET /*!< To get the current Key Refresh Phase state of the identified network key */ -#define ESP_BLE_MESH_MODEL_OP_LPN_POLLTIMEOUT_GET OP_LPN_TIMEOUT_GET /*!< To get the current value of PollTimeout timer of the Low Power node within a Friend node */ -#define ESP_BLE_MESH_MODEL_OP_NETWORK_TRANSMIT_GET OP_NET_TRANSMIT_GET /*!< To get the current Network Transmit state of a node */ - -/*!< The following opcodes will only be used in the esp_ble_mesh_config_client_set_state function. */ -typedef uint32_t esp_ble_mesh_opcode_config_client_set_t; /*!< esp_ble_mesh_opcode_config_client_set_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by esp_ble_mesh_config_client_set_state */ -#define ESP_BLE_MESH_MODEL_OP_BEACON_SET OP_BEACON_SET /*!< Set the Secure Network Beacon state of a Configuration Server with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_DEFAULT_TTL_SET OP_DEFAULT_TTL_SET /*!< Set the Default TTL state of a Configuration Server with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_GATT_PROXY_SET OP_GATT_PROXY_SET /*!< Determine the GATT Proxy state of a Configuration Server */ -#define ESP_BLE_MESH_MODEL_OP_RELAY_SET OP_RELAY_SET /*!< Set the Relay and Relay Retransmit states of a Configuration Server with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_SET OP_MOD_PUB_SET /*!< Set the Publish Address, Publish AppKey Index, CredentialFlag, Publish - Period, Publish Retransmit Count, Publish Retransmit Interval Steps, and - Publish TTL states of a particular model within the element with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD OP_MOD_SUB_ADD /*!< Add the address to the Subscription List state of a particular model - within the element with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_ADD OP_MOD_SUB_VA_ADD /*!< Add the Label UUID to the Subscription List state of a particular model - within the element with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE OP_MOD_SUB_DEL /*!< Delete the address from the Subscription List state of a particular - model within the element with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_DELETE OP_MOD_SUB_VA_DEL /*!< Delete the Label UUID from the Subscription List state of a particular - model within the element with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_OVERWRITE OP_MOD_SUB_OVERWRITE /*!< Clear the Subscription List and add the address to the Subscription List - state of a particular Model within the element with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_OVERWRITE OP_MOD_SUB_VA_OVERWRITE /*!< Clear the Subscription List and add the Label UUID to the Subscription - List state of a particular model within the element with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_NET_KEY_ADD OP_NET_KEY_ADD /*!< Add the NetKey identified by NetKeyIndex to the NetKey List state with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD OP_APP_KEY_ADD /*!< Add the AppKey to the AppKey List and bind it to the NetKey identified - by the NetKeyIndex of a Configuration Server with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND OP_MOD_APP_BIND /*!< Bind the AppKey to a model of a particular element of a Configuration Server with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_NODE_RESET OP_NODE_RESET /*!< Reset a node (other than a Provisioner) and remove it from the network */ -#define ESP_BLE_MESH_MODEL_OP_FRIEND_SET OP_FRIEND_SET /*!< Set the Friend state of a Configuration Server with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_SET OP_HEARTBEAT_PUB_SET /*!< Set the Heartbeat Publication Destination, Heartbeat Publication Count, - Heartbeat Publication Period, Heartbeat Publication TTL, Publication Features, - and Publication NetKey Index of a node with acknowledgment */ -#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_SET OP_HEARTBEAT_SUB_SET /*!< Determine the Heartbeat Subscription Source, Heartbeat Subscription Destination, - Heartbeat Subscription Count Log, Heartbeat Subscription Period Log, Heartbeat - Subscription Min Hops, and Heartbeat Subscription Max Hops states of a node */ -#define ESP_BLE_MESH_MODEL_OP_NET_KEY_UPDATE OP_NET_KEY_UPDATE /*!< To update a NetKey on a node */ -#define ESP_BLE_MESH_MODEL_OP_NET_KEY_DELETE OP_NET_KEY_DEL /*!< To delete a NetKey on a NetKey List from a node */ -#define ESP_BLE_MESH_MODEL_OP_APP_KEY_UPDATE OP_APP_KEY_UPDATE /*!< To update an AppKey value on the AppKey List on a node */ -#define ESP_BLE_MESH_MODEL_OP_APP_KEY_DELETE OP_APP_KEY_DEL /*!< To delete an AppKey from the AppKey List on a node */ -#define ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_SET OP_NODE_IDENTITY_SET /*!< To set the current Node Identity state for a subnet */ -#define ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_SET OP_KRP_SET /*!< To set the Key Refresh Phase state of the identified network key */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_VIRTUAL_ADDR_SET OP_MOD_PUB_VA_SET /*!< To set the model Publication state of an outgoing message that originates from a model */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE_ALL OP_MOD_SUB_DEL_ALL /*!< To discard the Subscription List of a model */ -#define ESP_BLE_MESH_MODEL_OP_MODEL_APP_UNBIND OP_MOD_APP_UNBIND /*!< To remove the binding between an AppKey and a model */ -#define ESP_BLE_MESH_MODEL_OP_NETWORK_TRANSMIT_SET OP_NET_TRANSMIT_SET /*!< To set the Network Transmit state of a node */ - -/*!< The following opcodes are used by the BLE Mesh Config Server Model internally to respond to the Config Client Model's request messages */ -typedef uint32_t esp_ble_mesh_config_model_status_t; /*!< esp_ble_mesh_config_model_status_t belongs to esp_ble_mesh_opcode_t, this typedef - is only used to locate the opcodes used by the Config Model messages */ -#define ESP_BLE_MESH_MODEL_OP_BEACON_STATUS OP_BEACON_STATUS -#define ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_STATUS OP_DEV_COMP_DATA_STATUS -#define ESP_BLE_MESH_MODEL_OP_DEFAULT_TTL_STATUS OP_DEFAULT_TTL_STATUS -#define ESP_BLE_MESH_MODEL_OP_GATT_PROXY_STATUS OP_GATT_PROXY_STATUS -#define ESP_BLE_MESH_MODEL_OP_RELAY_STATUS OP_RELAY_STATUS -#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_STATUS OP_MOD_PUB_STATUS -#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_STATUS OP_MOD_SUB_STATUS -#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_SUB_LIST OP_MOD_SUB_LIST -#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_SUB_LIST OP_MOD_SUB_LIST_VND -#define ESP_BLE_MESH_MODEL_OP_NET_KEY_STATUS OP_NET_KEY_STATUS -#define ESP_BLE_MESH_MODEL_OP_NET_KEY_LIST OP_NET_KEY_LIST -#define ESP_BLE_MESH_MODEL_OP_APP_KEY_STATUS OP_APP_KEY_STATUS -#define ESP_BLE_MESH_MODEL_OP_APP_KEY_LIST OP_APP_KEY_LIST -#define ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_STATUS OP_NODE_IDENTITY_STATUS -#define ESP_BLE_MESH_MODEL_OP_MODEL_APP_STATUS OP_MOD_APP_STATUS -#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_APP_LIST OP_SIG_MOD_APP_LIST -#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_APP_LIST OP_VND_MOD_APP_LIST -#define ESP_BLE_MESH_MODEL_OP_NODE_RESET_STATUS OP_NODE_RESET_STATUS -#define ESP_BLE_MESH_MODEL_OP_FRIEND_STATUS OP_FRIEND_STATUS -#define ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_STATUS OP_KRP_STATUS -#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_STATUS OP_HEARTBEAT_PUB_STATUS -#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_STATUS OP_HEARTBEAT_SUB_STATUS -#define ESP_BLE_MESH_MODEL_OP_LPN_POLLTIMEOUT_STATUS OP_LPN_TIMEOUT_STATUS -#define ESP_BLE_MESH_MODEL_OP_NETWORK_TRANSMIT_STATUS OP_NET_TRANSMIT_STATUS - -/*!< The following opcodes will only be used in the esp_ble_mesh_health_client_get_state function. */ -typedef uint32_t esp_ble_mesh_opcode_health_client_get_t; /*!< esp_ble_mesh_opcode_health_client_get_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by esp_ble_mesh_health_client_get_state */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_GET OP_HEALTH_FAULT_GET /*!< Get the current Registered Fault state */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_GET OP_HEALTH_PERIOD_GET /*!< Get the current Health Period state */ -#define ESP_BLE_MESH_MODEL_OP_ATTENTION_GET OP_ATTENTION_GET /*!< Get the current Attention Timer state */ - -/*!< The following opcodes will only be used in the esp_ble_mesh_health_client_set_state function. */ -typedef uint32_t esp_ble_mesh_opcode_health_client_set_t; /*!< esp_ble_mesh_opcode_health_client_set_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by esp_ble_mesh_health_client_set_state */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_CLEAR OP_HEALTH_FAULT_CLEAR /*!< Clear Health Fault acknowledged */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_CLEAR_UNACK OP_HEALTH_FAULT_CLEAR_UNREL /*!< Clear Health Fault Unacknowledged */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_TEST OP_HEALTH_FAULT_TEST /*!< Invoke Health Fault Test acknowledged */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_TEST_UNACK OP_HEALTH_FAULT_TEST_UNREL /*!< Invoke Health Fault Test unacknowledged */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_SET OP_HEALTH_PERIOD_SET /*!< Set Health Period acknowledged */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_SET_UNACK OP_HEALTH_PERIOD_SET_UNREL /*!< Set Health Period unacknowledged */ -#define ESP_BLE_MESH_MODEL_OP_ATTENTION_SET OP_ATTENTION_SET /*!< Set Health Attention acknowledged of the Health Server */ -#define ESP_BLE_MESH_MODEL_OP_ATTENTION_SET_UNACK OP_ATTENTION_SET_UNREL /*!< Set Health Attention Unacknowledged of the Health Server */ - -/*!< The following opcodes are used by the BLE Mesh Health Server Model internally to respond to the Health Client Model's request messages */ -typedef uint32_t esp_ble_mesh_health_model_status_t; /*!< esp_ble_mesh_health_model_status_t belongs to esp_ble_mesh_opcode_t, this typedef - is only used to locate the opcodes used by the Health Model messages */ -#define ESP_BLE_MESH_MODEL_OP_HEALTH_CURRENT_STATUS OP_HEALTH_CURRENT_STATUS -#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_STATUS OP_HEALTH_FAULT_STATUS -#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_STATUS OP_HEALTH_PERIOD_STATUS -#define ESP_BLE_MESH_MODEL_OP_ATTENTION_STATUS OP_ATTENTION_STATUS - -typedef uint32_t esp_ble_mesh_generic_message_opcode_t; /*!< esp_ble_mesh_generic_message_opcode_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by functions - esp_ble_mesh_generic_client_get_state & esp_ble_mesh_generic_client_set_state */ -/*!< Generic OnOff Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET BLE_MESH_MODEL_OP_GEN_ONOFF_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET BLE_MESH_MODEL_OP_GEN_ONOFF_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS - -/*!< Generic Level Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_GET BLE_MESH_MODEL_OP_GEN_LEVEL_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET BLE_MESH_MODEL_OP_GEN_LEVEL_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_DELTA_SET BLE_MESH_MODEL_OP_GEN_DELTA_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_MOVE_SET BLE_MESH_MODEL_OP_GEN_MOVE_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK - -/*!< Generic Default Transition Time Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_GET BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET_UNACK BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_STATUS BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_STATUS - -/*!< Generic Power OnOff Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_GET BLE_MESH_MODEL_OP_GEN_ONPOWERUP_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_STATUS BLE_MESH_MODEL_OP_GEN_ONPOWERUP_STATUS - -/*!< Generic Power OnOff Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET_UNACK BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET_UNACK - -/*!< Generic Power Level Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET_UNACK BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS - -/*!< Generic Power Level Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET_UNACK BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET_UNACK - -/*!< Generic Battery Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_BATTERY_GET BLE_MESH_MODEL_OP_GEN_BATTERY_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_BATTERY_STATUS BLE_MESH_MODEL_OP_GEN_BATTERY_STATUS - -/*!< Generic Location Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS - -/*!< Generic Location Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK - -/*!< Generic Manufacturer Property Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_GET BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_SET BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_STATUS BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_STATUS - -/*!< Generic Admin Property Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_STATUS BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_STATUS - -/*!< Generic User Property Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS -#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET -#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_STATUS BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_STATUS - -/*!< Generic Client Property Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET -#define ESP_BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS - -typedef uint32_t esp_ble_mesh_sensor_message_opcode_t; /*!< esp_ble_mesh_sensor_message_opcode_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by functions - esp_ble_mesh_sensor_client_get_state & esp_ble_mesh_sensor_client_set_state */ -/*!< Sensor Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS -#define ESP_BLE_MESH_MODEL_OP_SENSOR_GET BLE_MESH_MODEL_OP_SENSOR_GET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS BLE_MESH_MODEL_OP_SENSOR_STATUS -#define ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_GET BLE_MESH_MODEL_OP_SENSOR_SERIES_GET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS - -/*!< Sensor Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_GET BLE_MESH_MODEL_OP_SENSOR_SETTING_GET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET BLE_MESH_MODEL_OP_SENSOR_SETTING_SET -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS - -typedef uint32_t esp_ble_mesh_time_scene_message_opcode_t; /*!< esp_ble_mesh_time_scene_message_opcode_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by functions - esp_ble_mesh_time_scene_client_get_state & esp_ble_mesh_time_scene_client_set_state */ -/*!< Time Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_TIME_GET BLE_MESH_MODEL_OP_TIME_GET -#define ESP_BLE_MESH_MODEL_OP_TIME_SET BLE_MESH_MODEL_OP_TIME_SET -#define ESP_BLE_MESH_MODEL_OP_TIME_STATUS BLE_MESH_MODEL_OP_TIME_STATUS -#define ESP_BLE_MESH_MODEL_OP_TIME_ROLE_GET BLE_MESH_MODEL_OP_TIME_ROLE_GET -#define ESP_BLE_MESH_MODEL_OP_TIME_ROLE_SET BLE_MESH_MODEL_OP_TIME_ROLE_SET -#define ESP_BLE_MESH_MODEL_OP_TIME_ROLE_STATUS BLE_MESH_MODEL_OP_TIME_ROLE_STATUS -#define ESP_BLE_MESH_MODEL_OP_TIME_ZONE_GET BLE_MESH_MODEL_OP_TIME_ZONE_GET -#define ESP_BLE_MESH_MODEL_OP_TIME_ZONE_SET BLE_MESH_MODEL_OP_TIME_ZONE_SET -#define ESP_BLE_MESH_MODEL_OP_TIME_ZONE_STATUS BLE_MESH_MODEL_OP_TIME_ZONE_STATUS -#define ESP_BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET -#define ESP_BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET -#define ESP_BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS - -/*!< Scene Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_SCENE_GET BLE_MESH_MODEL_OP_SCENE_GET -#define ESP_BLE_MESH_MODEL_OP_SCENE_RECALL BLE_MESH_MODEL_OP_SCENE_RECALL -#define ESP_BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK -#define ESP_BLE_MESH_MODEL_OP_SCENE_STATUS BLE_MESH_MODEL_OP_SCENE_STATUS -#define ESP_BLE_MESH_MODEL_OP_SCENE_REGISTER_GET BLE_MESH_MODEL_OP_SCENE_REGISTER_GET -#define ESP_BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS - -/*!< Scene Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_SCENE_STORE BLE_MESH_MODEL_OP_SCENE_STORE -#define ESP_BLE_MESH_MODEL_OP_SCENE_STORE_UNACK BLE_MESH_MODEL_OP_SCENE_STORE_UNACK -#define ESP_BLE_MESH_MODEL_OP_SCENE_DELETE BLE_MESH_MODEL_OP_SCENE_DELETE -#define ESP_BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK - -/*!< Scheduler Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET -#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS -#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_GET BLE_MESH_MODEL_OP_SCHEDULER_GET -#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_STATUS BLE_MESH_MODEL_OP_SCHEDULER_STATUS - -/*!< Scheduler Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET -#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK - -typedef uint32_t esp_ble_mesh_light_message_opcode_t; /*!< esp_ble_mesh_light_message_opcode_t belongs to esp_ble_mesh_opcode_t, - this typedef is only used to locate the opcodes used by functions - esp_ble_mesh_light_client_get_state & esp_ble_mesh_light_client_set_state */ -/*!< Light Lightness Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS - -/*!< Light Lightness Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET_UNACK - -/*!< Light CTL Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_GET BLE_MESH_MODEL_OP_LIGHT_CTL_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_SET BLE_MESH_MODEL_OP_LIGHT_CTL_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS - -/*!< Light CTL Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK - -/*!< Light HSL Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_GET BLE_MESH_MODEL_OP_LIGHT_HSL_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SET BLE_MESH_MODEL_OP_LIGHT_HSL_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS - -/*!< Light HSL Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK /* Model spec is wrong */ - -/*!< Light xyL Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_GET BLE_MESH_MODEL_OP_LIGHT_XYL_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_SET BLE_MESH_MODEL_OP_LIGHT_XYL_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_XYL_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS - -/*!< Light xyL Setup Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET_UNACK - -/*!< Light Control Message Opcode */ -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_GET BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_GET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK -#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS - -typedef uint32_t esp_ble_mesh_opcode_t; -/*!< End of defines of esp_ble_mesh_opcode_t */ - -#define ESP_BLE_MESH_CFG_STATUS_SUCCESS STATUS_SUCCESS -#define ESP_BLE_MESH_CFG_STATUS_INVALID_ADDRESS STATUS_INVALID_ADDRESS -#define ESP_BLE_MESH_CFG_STATUS_INVALID_MODEL STATUS_INVALID_MODEL -#define ESP_BLE_MESH_CFG_STATUS_INVALID_APPKEY STATUS_INVALID_APPKEY -#define ESP_BLE_MESH_CFG_STATUS_INVALID_NETKEY STATUS_INVALID_NETKEY -#define ESP_BLE_MESH_CFG_STATUS_INSUFFICIENT_RESOURCES STATUS_INSUFF_RESOURCES -#define ESP_BLE_MESH_CFG_STATUS_KEY_INDEX_ALREADY_STORED STATUS_IDX_ALREADY_STORED -#define ESP_BLE_MESH_CFG_STATUS_INVALID_PUBLISH_PARAMETERS STATUS_NVAL_PUB_PARAM -#define ESP_BLE_MESH_CFG_STATUS_NOT_A_SUBSCRIBE_MODEL STATUS_NOT_SUB_MOD -#define ESP_BLE_MESH_CFG_STATUS_STORAGE_FAILURE STATUS_STORAGE_FAIL -#define ESP_BLE_MESH_CFG_STATUS_FEATURE_NOT_SUPPORTED STATUS_FEAT_NOT_SUPP -#define ESP_BLE_MESH_CFG_STATUS_CANNOT_UPDATE STATUS_CANNOT_UPDATE -#define ESP_BLE_MESH_CFG_STATUS_CANNOT_REMOVE STATUS_CANNOT_REMOVE -#define ESP_BLE_MESH_CFG_STATUS_CANNOT_BIND STATUS_CANNOT_BIND -#define ESP_BLE_MESH_CFG_STATUS_TEMP_UNABLE_TO_CHANGE_STATE STATUS_TEMP_STATE_CHG_FAIL -#define ESP_BLE_MESH_CFG_STATUS_CANNOT_SET STATUS_CANNOT_SET -#define ESP_BLE_MESH_CFG_STATUS_UNSPECIFIED_ERROR STATUS_UNSPECIFIED -#define ESP_BLE_MESH_CFG_STATUS_INVALID_BINDING STATUS_INVALID_BINDING -typedef uint8_t esp_ble_mesh_cfg_status_t; /*!< This typedef is only used to indicate the status code - contained in some of the Config Server Model status message */ - -#define ESP_BLE_MESH_MODEL_STATUS_SUCCESS 0x00 -#define ESP_BLE_MESH_MODEL_STATUS_CANNOT_SET_RANGE_MIN 0x01 -#define ESP_BLE_MESH_MODEL_STATUS_CANNOT_SET_RANGE_MAX 0x02 -typedef uint8_t esp_ble_mesh_model_status_t; /*!< This typedef is only used to indicate the status code contained in - some of the server model (e.g. Generic Server Model) status message */ - /** @def ESP_BLE_MESH_TRANSMIT * * @brief Encode transmission count & interval steps. @@ -1124,16 +631,6 @@ typedef enum { ROLE_FAST_PROV, } esp_ble_mesh_dev_role_t; -/** Common parameters of the messages sent by Client Model. */ -typedef struct { - esp_ble_mesh_opcode_t opcode; /*!< Message opcode */ - esp_ble_mesh_model_t *model; /*!< Pointer to the client model structure */ - esp_ble_mesh_msg_ctx_t ctx; /*!< The context used to send message */ - int32_t msg_timeout; /*!< Timeout value (ms) to get response to the sent message */ - /*!< Note: if using default timeout value in menuconfig, make sure to set this value to 0 */ - uint8_t msg_role; /*!< Role of the device - Node/Provisioner */ -} esp_ble_mesh_client_common_param_t; - /*!< Flag which will be set when device is going to be added. */ typedef uint8_t esp_ble_mesh_dev_add_flag_t; #define ADD_DEV_RM_AFTER_PROV_FLAG BIT(0) /*!< Device will be removed from queue after provisioned successfully */ @@ -1198,6 +695,12 @@ typedef enum { FAST_PROV_ACT_MAX, } esp_ble_mesh_fast_prov_action_t; +/*!< This enum value is the type of proxy filter */ +typedef enum { + PROXY_FILTER_WHITELIST, + PROXY_FILTER_BLACKLIST, +} esp_ble_mesh_proxy_filter_type_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 */ @@ -1240,20 +743,26 @@ typedef enum { ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_NET_KEY_COMP_EVT, /*!< Provisioner add local network key completion 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 */ + ESP_BLE_MESH_LPN_ENABLE_COMP_EVT, /*!< Enable Low Power Node completion event */ + ESP_BLE_MESH_LPN_DISABLE_COMP_EVT, /*!< Disable Low Power Node completion event */ + ESP_BLE_MESH_LPN_POLL_COMP_EVT, /*!< Low Power Node send Friend Poll completion event */ + ESP_BLE_MESH_LPN_FRIENDSHIP_ESTABLISH_EVT, /*!< Low Power Node establishes friendship event */ + ESP_BLE_MESH_LPN_FRIENDSHIP_TERMINATE_EVT, /*!< Low Power Node terminates friendship event */ + ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT, /*!< Friend Node establishes friendship event */ + ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT, /*!< Friend Node terminates friendship event */ + ESP_BLE_MESH_PROXY_CLIENT_RECV_ADV_PKT_EVT, /*!< Proxy Client receives Network ID advertising packet event */ + ESP_BLE_MESH_PROXY_CLIENT_CONNECTED_EVT, /*!< Proxy Client establishes connection successfully event */ + ESP_BLE_MESH_PROXY_CLIENT_DISCONNECTED_EVT, /*!< Proxy Client terminates connection successfully event */ + ESP_BLE_MESH_PROXY_CLIENT_RECV_FILTER_STATUS_EVT, /*!< Proxy Client receives Proxy Filter Status event */ + ESP_BLE_MESH_PROXY_CLIENT_CONNECT_COMP_EVT, /*!< Proxy Client connect completion event */ + ESP_BLE_MESH_PROXY_CLIENT_DISCONNECT_COMP_EVT, /*!< Proxy Client disconnect completion event */ + 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_PROV_EVT_MAX, } esp_ble_mesh_prov_cb_event_t; -/*!< This enum value is the event of undefined SIG Models and Vendor Models */ -typedef enum { - ESP_BLE_MESH_MODEL_OPERATION_EVT, /*!< User-defined models receive messages from peer devices (e.g. get, set, status, etc) event */ - ESP_BLE_MESH_MODEL_SEND_COMP_EVT, /*!< User-defined models send messages completion event */ - ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT, /*!< User-defined models publish messages completion event */ - ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT, /*!< User-defined client models receive publish messages event */ - ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT, /*!< Timeout event for the user-defined client models that failed to receive response from peer server models */ - ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT, /*!< When a model is configured to publish messages periodically, this event will occur during every publish period */ - ESP_BLE_MESH_MODEL_EVT_MAX, -} esp_ble_mesh_model_cb_event_t; - /** * @brief BLE Mesh Node/Provisioner callback parameters union */ @@ -1371,8 +880,8 @@ typedef union { */ struct ble_mesh_provisioner_recv_unprov_adv_pkt_param { uint8_t dev_uuid[16]; /*!< Device UUID of the unprovisoned device */ - uint8_t addr[6]; /*!< Device address of the unprovisoned device */ - esp_ble_mesh_addr_type_t addr_type; /*!< Device address type */ + esp_ble_mesh_bd_addr_t addr; /*!< Device address of the unprovisoned device */ + esp_ble_mesh_addr_type_t addr_type; /*!< Device address type */ uint16_t oob_info; /*!< OOB Info of the unprovisoned device */ uint8_t adv_type; /*!< Avertising type of the unprovisoned device */ esp_ble_mesh_prov_bearer_t bearer; /*!< Bearer of the unprovisoned device */ @@ -1523,8 +1032,839 @@ typedef union { struct ble_mesh_set_fast_prov_action_comp_param { uint8_t status_action; /*!< Indicate the result of setting action of fast provisioning */ } set_fast_prov_action_comp; /*!< Event parameter of ESP_BLE_MESH_SET_FAST_PROV_ACTION_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_HEARTBEAT_MESSAGE_RECV_EVT + */ + struct ble_mesh_heartbeat_msg_recv_param { + uint8_t hops; /*!< Heartbeat hops (InitTTL - RxTTL + 1) */ + uint16_t feature; /*!< Bit field of currently active features of the node */ + } heartbeat_msg_recv; /*!< Event parameter of ESP_BLE_MESH_HEARTBEAT_MESSAGE_RECV_EVT */ + /** + * @brief ESP_BLE_MESH_LPN_ENABLE_COMP_EVT + */ + struct ble_mesh_lpn_enable_comp_param { + int err_code; /*!< Indicate the result of enabling LPN functionality */ + } lpn_enable_comp; /*!< Event parameter of ESP_BLE_MESH_LPN_ENABLE_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_LPN_DISABLE_COMP_EVT + */ + struct ble_mesh_lpn_disable_comp_param { + int err_code; /*!< Indicate the result of disabling LPN functionality */ + } lpn_disable_comp; /*!< Event parameter of ESP_BLE_MESH_LPN_DISABLE_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_LPN_POLL_COMP_EVT + */ + struct ble_mesh_lpn_poll_comp_param { + int err_code; /*!< Indicate the result of sending Friend Poll */ + } lpn_poll_comp; /*!< Event parameter of ESP_BLE_MESH_LPN_POLL_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_LPN_FRIENDSHIP_ESTABLISH_EVT + */ + struct ble_mesh_lpn_friendship_establish_param { + uint16_t friend_addr; /*!< Friend Node unicast address */ + } lpn_friendship_establish; /*!< Event parameter of ESP_BLE_MESH_LPN_FRIENDSHIP_ESTABLISH_EVT */ + /** + * @brief ESP_BLE_MESH_LPN_FRIENDSHIP_TERMINATE_EVT + */ + struct ble_mesh_lpn_friendship_terminate_param { + uint16_t friend_addr; /*!< Friend Node unicast address */ + } lpn_friendship_terminate; /*!< Event parameter of ESP_BLE_MESH_LPN_FRIENDSHIP_TERMINATE_EVT */ + /** + * @brief ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT + */ + struct ble_mesh_friend_friendship_establish_param { + uint16_t lpn_addr; /*!< Low Power Node unciast address */ + } frnd_friendship_establish; /*!< Event parameter of ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT */ + /** + * @brief ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT + */ + struct ble_mesh_friend_friendship_terminate_param { + uint16_t lpn_addr; /*!< Low Power Node unicast address */ + /** This enum value is the reason of friendship termination on the friend node side */ + enum { + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL, /*!< Friend Offer has been sent, but Friend Offer is not received within 1 second, friendship fails to be established */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_POLL_TIMEOUT, /*!< Friendship is established, PollTimeout timer expires and no Friend Poll/Sub Add/Sub Remove is received */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_RECV_FRND_REQ, /*!< Receive Friend Request from existing Low Power Node */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR, /*!< Receive Friend Clear from other friend node */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_DISABLE, /*!< Friend feature disabled or corresponding NetKey is deleted */ + } reason; /*!< Friendship terminated reason */ + } frnd_friendship_terminate; /*!< Event parameter of ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_RECV_ADV_PKT_EVT + */ + struct ble_mesh_proxy_client_recv_adv_pkt_param { + esp_ble_mesh_bd_addr_t addr; /*!< Device address */ + esp_ble_mesh_addr_type_t addr_type; /*!< Device address type */ + uint16_t net_idx; /*!< Network ID related NetKey Index */ + uint8_t net_id[8]; /*!< Network ID contained in the advertising packet */ + } proxy_client_recv_adv_pkt; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_RECV_ADV_PKT_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_CONNECTED_EVT + */ + struct ble_mesh_proxy_client_connected_param { + esp_ble_mesh_bd_addr_t addr; /*!< Device address of the Proxy Server */ + esp_ble_mesh_addr_type_t addr_type; /*!< Device address type */ + uint8_t conn_handle; /*!< Proxy connection handle */ + uint16_t net_idx; /*!< Corresponding NetKey Index */ + } proxy_client_connected; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_CONNECTED_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_DISCONNECTED_EVT + */ + struct ble_mesh_proxy_client_disconnected_param { + esp_ble_mesh_bd_addr_t addr; /*!< Device address of the Proxy Server */ + esp_ble_mesh_addr_type_t addr_type; /*!< Device address type */ + uint8_t conn_handle; /*!< Proxy connection handle */ + uint16_t net_idx; /*!< Corresponding NetKey Index */ + uint8_t reason; /*!< Proxy disconnect reason */ + } proxy_client_disconnected; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_DISCONNECTED_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_RECV_FILTER_STATUS_EVT + */ + struct ble_mesh_proxy_client_recv_filter_status_param { + uint8_t conn_handle; /*!< Proxy connection handle */ + uint16_t server_addr; /*!< Proxy Server primary element address */ + uint16_t net_idx; /*!< Corresponding NetKey Index */ + uint8_t filter_type; /*!< Proxy Server filter type(whitelist or blacklist) */ + uint16_t list_size; /*!< Number of addresses in the Proxy Server filter list */ + } proxy_client_recv_filter_status; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_RECV_FILTER_STATUS_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_CONNECT_COMP_EVT + */ + struct ble_mesh_proxy_client_connect_comp_param { + int err_code; /*!< Indicate the result of Proxy Client connect */ + esp_ble_mesh_bd_addr_t addr; /*!< Device address of the Proxy Server */ + esp_ble_mesh_addr_type_t addr_type; /*!< Device address type */ + uint16_t net_idx; /*!< Corresponding NetKey Index */ + } proxy_client_connect_comp; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_CONNECT_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_DISCONNECT_COMP_EVT + */ + struct ble_mesh_proxy_client_disconnect_comp_param { + int err_code; /*!< Indicate the result of Proxy Client disconnect */ + uint8_t conn_handle; /*!< Proxy connection handle */ + } proxy_client_disconnect_comp; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_DISCONNECT_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_SET_FILTER_TYPE_COMP_EVT + */ + struct ble_mesh_proxy_client_set_filter_type_comp_param { + int err_code; /*!< Indicate the result of Proxy Client set filter type */ + uint8_t conn_handle; /*!< Proxy connection handle */ + uint16_t net_idx; /*!< Corresponding NetKey Index */ + } proxy_client_set_filter_type_comp; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_SET_FILTER_TYPE_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_ADD_FILTER_ADDR_COMP_EVT + */ + struct ble_mesh_proxy_client_add_filter_addr_comp_param { + int err_code; /*!< Indicate the result of Proxy Client add filter address */ + uint8_t conn_handle; /*!< Proxy connection handle */ + uint16_t net_idx; /*!< Corresponding NetKey Index */ + } proxy_client_add_filter_addr_comp; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_ADD_FILTER_ADDR_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT + */ + struct ble_mesh_proxy_client_remove_filter_addr_comp_param { + int err_code; /*!< Indicate the result of Proxy Client remove filter address */ + 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 */ } esp_ble_mesh_prov_cb_param_t; +/** + * @brief BLE Mesh models related Model ID and Opcode definitions + */ + +/*!< Foundation Models */ +#define ESP_BLE_MESH_MODEL_ID_CONFIG_SRV BLE_MESH_MODEL_ID_CFG_SRV +#define ESP_BLE_MESH_MODEL_ID_CONFIG_CLI BLE_MESH_MODEL_ID_CFG_CLI +#define ESP_BLE_MESH_MODEL_ID_HEALTH_SRV BLE_MESH_MODEL_ID_HEALTH_SRV +#define ESP_BLE_MESH_MODEL_ID_HEALTH_CLI BLE_MESH_MODEL_ID_HEALTH_CLI + +/*!< Models from the Mesh Model Specification */ +#define ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV BLE_MESH_MODEL_ID_GEN_ONOFF_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI BLE_MESH_MODEL_ID_GEN_ONOFF_CLI +#define ESP_BLE_MESH_MODEL_ID_GEN_LEVEL_SRV BLE_MESH_MODEL_ID_GEN_LEVEL_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_LEVEL_CLI BLE_MESH_MODEL_ID_GEN_LEVEL_CLI +#define ESP_BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI +#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI +#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI +#define ESP_BLE_MESH_MODEL_ID_GEN_BATTERY_SRV BLE_MESH_MODEL_ID_GEN_BATTERY_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_BATTERY_CLI BLE_MESH_MODEL_ID_GEN_BATTERY_CLI +#define ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_SRV BLE_MESH_MODEL_ID_GEN_LOCATION_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_CLI BLE_MESH_MODEL_ID_GEN_LOCATION_CLI +#define ESP_BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV +#define ESP_BLE_MESH_MODEL_ID_GEN_PROP_CLI BLE_MESH_MODEL_ID_GEN_PROP_CLI +#define ESP_BLE_MESH_MODEL_ID_SENSOR_SRV BLE_MESH_MODEL_ID_SENSOR_SRV +#define ESP_BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_SENSOR_CLI BLE_MESH_MODEL_ID_SENSOR_CLI +#define ESP_BLE_MESH_MODEL_ID_TIME_SRV BLE_MESH_MODEL_ID_TIME_SRV +#define ESP_BLE_MESH_MODEL_ID_TIME_SETUP_SRV BLE_MESH_MODEL_ID_TIME_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_TIME_CLI BLE_MESH_MODEL_ID_TIME_CLI +#define ESP_BLE_MESH_MODEL_ID_SCENE_SRV BLE_MESH_MODEL_ID_SCENE_SRV +#define ESP_BLE_MESH_MODEL_ID_SCENE_SETUP_SRV BLE_MESH_MODEL_ID_SCENE_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_SCENE_CLI BLE_MESH_MODEL_ID_SCENE_CLI +#define ESP_BLE_MESH_MODEL_ID_SCHEDULER_SRV BLE_MESH_MODEL_ID_SCHEDULER_SRV +#define ESP_BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_SCHEDULER_CLI BLE_MESH_MODEL_ID_SCHEDULER_CLI +#define ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI +#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SRV BLE_MESH_MODEL_ID_LIGHT_CTL_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_CLI BLE_MESH_MODEL_ID_LIGHT_CTL_CLI +#define ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_CLI BLE_MESH_MODEL_ID_LIGHT_HSL_CLI +#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_SRV BLE_MESH_MODEL_ID_LIGHT_XYL_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_CLI BLE_MESH_MODEL_ID_LIGHT_XYL_CLI +#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SRV BLE_MESH_MODEL_ID_LIGHT_LC_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV +#define ESP_BLE_MESH_MODEL_ID_LIGHT_LC_CLI BLE_MESH_MODEL_ID_LIGHT_LC_CLI + +/** + * esp_ble_mesh_opcode_config_client_get_t belongs to esp_ble_mesh_opcode_t, this typedef is only + * used to locate the opcodes used by esp_ble_mesh_config_client_get_state. + * The following opcodes will only be used in the esp_ble_mesh_config_client_get_state function. + */ +typedef uint32_t esp_ble_mesh_opcode_config_client_get_t; + +#define ESP_BLE_MESH_MODEL_OP_BEACON_GET OP_BEACON_GET /*!< Config Beacon Get */ +#define ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET OP_DEV_COMP_DATA_GET /*!< Config Composition Data Get */ +#define ESP_BLE_MESH_MODEL_OP_DEFAULT_TTL_GET OP_DEFAULT_TTL_GET /*!< Config Default TTL Get */ +#define ESP_BLE_MESH_MODEL_OP_GATT_PROXY_GET OP_GATT_PROXY_GET /*!< Config GATT Proxy Get */ +#define ESP_BLE_MESH_MODEL_OP_RELAY_GET OP_RELAY_GET /*!< Config Relay Get */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_GET OP_MOD_PUB_GET /*!< Config Model Publication Get */ +#define ESP_BLE_MESH_MODEL_OP_FRIEND_GET OP_FRIEND_GET /*!< Config Friend Get */ +#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_GET OP_HEARTBEAT_PUB_GET /*!< Config Heartbeat Publication Get */ +#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_GET OP_HEARTBEAT_SUB_GET /*!< Config Heartbeat Subscription Get */ +#define ESP_BLE_MESH_MODEL_OP_NET_KEY_GET OP_NET_KEY_GET /*!< Config NetKey Get */ +#define ESP_BLE_MESH_MODEL_OP_APP_KEY_GET OP_APP_KEY_GET /*!< Config AppKey Get */ +#define ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_GET OP_NODE_IDENTITY_GET /*!< Config Node Identity Get */ +#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_SUB_GET OP_MOD_SUB_GET /*!< Config SIG Model Subscription Get */ +#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_SUB_GET OP_MOD_SUB_GET_VND /*!< Config Vendor Model Subscription Get */ +#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_APP_GET OP_SIG_MOD_APP_GET /*!< Config SIG Model App Get */ +#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_APP_GET OP_VND_MOD_APP_GET /*!< Config Vendor Model App Get */ +#define ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_GET OP_KRP_GET /*!< Config Key Refresh Phase Get */ +#define ESP_BLE_MESH_MODEL_OP_LPN_POLLTIMEOUT_GET OP_LPN_TIMEOUT_GET /*!< Config Low Power Node PollTimeout Get */ +#define ESP_BLE_MESH_MODEL_OP_NETWORK_TRANSMIT_GET OP_NET_TRANSMIT_GET /*!< Config Network Transmit Get */ + +/** + * esp_ble_mesh_opcode_config_client_set_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by esp_ble_mesh_config_client_set_state. + * The following opcodes will only be used in the esp_ble_mesh_config_client_set_state function. + */ +typedef uint32_t esp_ble_mesh_opcode_config_client_set_t; + +#define ESP_BLE_MESH_MODEL_OP_BEACON_SET OP_BEACON_SET /*!< Config Beacon Set */ +#define ESP_BLE_MESH_MODEL_OP_DEFAULT_TTL_SET OP_DEFAULT_TTL_SET /*!< Config Default TTL Set */ +#define ESP_BLE_MESH_MODEL_OP_GATT_PROXY_SET OP_GATT_PROXY_SET /*!< Config GATT Proxy Set */ +#define ESP_BLE_MESH_MODEL_OP_RELAY_SET OP_RELAY_SET /*!< Config Relay Set */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_SET OP_MOD_PUB_SET /*!< Config Model Publication Set */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD OP_MOD_SUB_ADD /*!< Config Model Subscription Add */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_ADD OP_MOD_SUB_VA_ADD /*!< Config Model Subscription Vritual Address Add */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE OP_MOD_SUB_DEL /*!< Config Model Subscription Delete */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_DELETE OP_MOD_SUB_VA_DEL /*!< Config Model Subscription Virtual Address Delete */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_OVERWRITE OP_MOD_SUB_OVERWRITE /*!< Config Model Subscription Overwrite */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_OVERWRITE OP_MOD_SUB_VA_OVERWRITE /*!< Config Model Subscription Virtual Address Overwrite */ +#define ESP_BLE_MESH_MODEL_OP_NET_KEY_ADD OP_NET_KEY_ADD /*!< Config NetKey Add */ +#define ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD OP_APP_KEY_ADD /*!< Config AppKey Add */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND OP_MOD_APP_BIND /*!< Config Model App Bind */ +#define ESP_BLE_MESH_MODEL_OP_NODE_RESET OP_NODE_RESET /*!< Config Node Reset */ +#define ESP_BLE_MESH_MODEL_OP_FRIEND_SET OP_FRIEND_SET /*!< Config Friend Set */ +#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_SET OP_HEARTBEAT_PUB_SET /*!< Config Heartbeat Publication Set */ +#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_SET OP_HEARTBEAT_SUB_SET /*!< Config Heartbeat Subscription Set */ +#define ESP_BLE_MESH_MODEL_OP_NET_KEY_UPDATE OP_NET_KEY_UPDATE /*!< Config NetKey Update */ +#define ESP_BLE_MESH_MODEL_OP_NET_KEY_DELETE OP_NET_KEY_DEL /*!< Config NetKey Delete */ +#define ESP_BLE_MESH_MODEL_OP_APP_KEY_UPDATE OP_APP_KEY_UPDATE /*!< Config AppKey Update */ +#define ESP_BLE_MESH_MODEL_OP_APP_KEY_DELETE OP_APP_KEY_DEL /*!< Config AppKey Delete */ +#define ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_SET OP_NODE_IDENTITY_SET /*!< Config Node Identity Set */ +#define ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_SET OP_KRP_SET /*!< Config Key Refresh Phase Set */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_VIRTUAL_ADDR_SET OP_MOD_PUB_VA_SET /*!< Config Model Publication Virtual Address Set */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE_ALL OP_MOD_SUB_DEL_ALL /*!< Config Model Subscription Delete All */ +#define ESP_BLE_MESH_MODEL_OP_MODEL_APP_UNBIND OP_MOD_APP_UNBIND /*!< Config Model App Unbind */ +#define ESP_BLE_MESH_MODEL_OP_NETWORK_TRANSMIT_SET OP_NET_TRANSMIT_SET /*!< Config Network Transmit Set */ + +/** + * esp_ble_mesh_opcode_config_status_t belongs to esp_ble_mesh_opcode_t, this typedef is only + * used to locate the opcodes used by the Config Model messages + * The following opcodes are used by the BLE Mesh Config Server Model internally to respond + * to the Config Client Model's request messages. + */ +typedef uint32_t esp_ble_mesh_opcode_config_status_t; + +#define ESP_BLE_MESH_MODEL_OP_BEACON_STATUS OP_BEACON_STATUS +#define ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_STATUS OP_DEV_COMP_DATA_STATUS +#define ESP_BLE_MESH_MODEL_OP_DEFAULT_TTL_STATUS OP_DEFAULT_TTL_STATUS +#define ESP_BLE_MESH_MODEL_OP_GATT_PROXY_STATUS OP_GATT_PROXY_STATUS +#define ESP_BLE_MESH_MODEL_OP_RELAY_STATUS OP_RELAY_STATUS +#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_STATUS OP_MOD_PUB_STATUS +#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_STATUS OP_MOD_SUB_STATUS +#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_SUB_LIST OP_MOD_SUB_LIST +#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_SUB_LIST OP_MOD_SUB_LIST_VND +#define ESP_BLE_MESH_MODEL_OP_NET_KEY_STATUS OP_NET_KEY_STATUS +#define ESP_BLE_MESH_MODEL_OP_NET_KEY_LIST OP_NET_KEY_LIST +#define ESP_BLE_MESH_MODEL_OP_APP_KEY_STATUS OP_APP_KEY_STATUS +#define ESP_BLE_MESH_MODEL_OP_APP_KEY_LIST OP_APP_KEY_LIST +#define ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_STATUS OP_NODE_IDENTITY_STATUS +#define ESP_BLE_MESH_MODEL_OP_MODEL_APP_STATUS OP_MOD_APP_STATUS +#define ESP_BLE_MESH_MODEL_OP_SIG_MODEL_APP_LIST OP_SIG_MOD_APP_LIST +#define ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_APP_LIST OP_VND_MOD_APP_LIST +#define ESP_BLE_MESH_MODEL_OP_NODE_RESET_STATUS OP_NODE_RESET_STATUS +#define ESP_BLE_MESH_MODEL_OP_FRIEND_STATUS OP_FRIEND_STATUS +#define ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_STATUS OP_KRP_STATUS +#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_STATUS OP_HEARTBEAT_PUB_STATUS +#define ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_STATUS OP_HEARTBEAT_SUB_STATUS +#define ESP_BLE_MESH_MODEL_OP_LPN_POLLTIMEOUT_STATUS OP_LPN_TIMEOUT_STATUS +#define ESP_BLE_MESH_MODEL_OP_NETWORK_TRANSMIT_STATUS OP_NET_TRANSMIT_STATUS + +/** + * This typedef is only used to indicate the status code contained in some of + * the Configuration Server Model status message. + */ +typedef uint8_t esp_ble_mesh_cfg_status_t; + +#define ESP_BLE_MESH_CFG_STATUS_SUCCESS 0x00 +#define ESP_BLE_MESH_CFG_STATUS_INVALID_ADDRESS 0x01 +#define ESP_BLE_MESH_CFG_STATUS_INVALID_MODEL 0x02 +#define ESP_BLE_MESH_CFG_STATUS_INVALID_APPKEY 0x03 +#define ESP_BLE_MESH_CFG_STATUS_INVALID_NETKEY 0x04 +#define ESP_BLE_MESH_CFG_STATUS_INSUFFICIENT_RESOURCES 0x05 +#define ESP_BLE_MESH_CFG_STATUS_KEY_INDEX_ALREADY_STORED 0x06 +#define ESP_BLE_MESH_CFG_STATUS_INVALID_PUBLISH_PARAMETERS 0x07 +#define ESP_BLE_MESH_CFG_STATUS_NOT_A_SUBSCRIBE_MODEL 0x08 +#define ESP_BLE_MESH_CFG_STATUS_STORAGE_FAILURE 0x09 +#define ESP_BLE_MESH_CFG_STATUS_FEATURE_NOT_SUPPORTED 0x0A +#define ESP_BLE_MESH_CFG_STATUS_CANNOT_UPDATE 0x0B +#define ESP_BLE_MESH_CFG_STATUS_CANNOT_REMOVE 0x0C +#define ESP_BLE_MESH_CFG_STATUS_CANNOT_BIND 0x0D +#define ESP_BLE_MESH_CFG_STATUS_TEMP_UNABLE_TO_CHANGE_STATE 0x0E +#define ESP_BLE_MESH_CFG_STATUS_CANNOT_SET 0x0F +#define ESP_BLE_MESH_CFG_STATUS_UNSPECIFIED_ERROR 0x10 +#define ESP_BLE_MESH_CFG_STATUS_INVALID_BINDING 0x11 + +/** + * esp_ble_mesh_opcode_health_client_get_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by esp_ble_mesh_health_client_get_state. + * The following opcodes will only be used in the esp_ble_mesh_health_client_get_state function. + */ +typedef uint32_t esp_ble_mesh_opcode_health_client_get_t; + +#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_GET OP_HEALTH_FAULT_GET /*!< Health Fault Get */ +#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_GET OP_HEALTH_PERIOD_GET /*!< Health Period Get */ +#define ESP_BLE_MESH_MODEL_OP_ATTENTION_GET OP_ATTENTION_GET /*!< Health Attention Get */ + +/** + * esp_ble_mesh_opcode_health_client_set_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by esp_ble_mesh_health_client_set_state. + * The following opcodes will only be used in the esp_ble_mesh_health_client_set_state function. + */ +typedef uint32_t esp_ble_mesh_opcode_health_client_set_t; + +#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_CLEAR OP_HEALTH_FAULT_CLEAR /*!< Health Fault Clear */ +#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_CLEAR_UNACK OP_HEALTH_FAULT_CLEAR_UNREL /*!< Health Fault Clear Unacknowledged */ +#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_TEST OP_HEALTH_FAULT_TEST /*!< Health Fault Test */ +#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_TEST_UNACK OP_HEALTH_FAULT_TEST_UNREL /*!< Health Fault Test Unacknowledged */ +#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_SET OP_HEALTH_PERIOD_SET /*!< Health Period Set */ +#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_SET_UNACK OP_HEALTH_PERIOD_SET_UNREL /*!< Health Period Set Unacknowledged */ +#define ESP_BLE_MESH_MODEL_OP_ATTENTION_SET OP_ATTENTION_SET /*!< Health Attention Set */ +#define ESP_BLE_MESH_MODEL_OP_ATTENTION_SET_UNACK OP_ATTENTION_SET_UNREL /*!< Health Attention Set Unacknowledged */ + +/** + * esp_ble_mesh_health_model_status_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by the Health Model messages. + * The following opcodes are used by the BLE Mesh Health Server Model internally to + * respond to the Health Client Model's request messages. + */ +typedef uint32_t esp_ble_mesh_health_model_status_t; + +#define ESP_BLE_MESH_MODEL_OP_HEALTH_CURRENT_STATUS OP_HEALTH_CURRENT_STATUS +#define ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_STATUS OP_HEALTH_FAULT_STATUS +#define ESP_BLE_MESH_MODEL_OP_HEALTH_PERIOD_STATUS OP_HEALTH_PERIOD_STATUS +#define ESP_BLE_MESH_MODEL_OP_ATTENTION_STATUS OP_ATTENTION_STATUS + +/** + * esp_ble_mesh_generic_message_opcode_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by functions esp_ble_mesh_generic_client_get_state + * & esp_ble_mesh_generic_client_set_state. + */ +typedef uint32_t esp_ble_mesh_generic_message_opcode_t; + +/*!< Generic OnOff Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET BLE_MESH_MODEL_OP_GEN_ONOFF_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET BLE_MESH_MODEL_OP_GEN_ONOFF_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS + +/*!< Generic Level Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_GET BLE_MESH_MODEL_OP_GEN_LEVEL_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET BLE_MESH_MODEL_OP_GEN_LEVEL_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_DELTA_SET BLE_MESH_MODEL_OP_GEN_DELTA_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_MOVE_SET BLE_MESH_MODEL_OP_GEN_MOVE_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK + +/*!< Generic Default Transition Time Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_GET BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET_UNACK BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_STATUS BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_STATUS + +/*!< Generic Power OnOff Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_GET BLE_MESH_MODEL_OP_GEN_ONPOWERUP_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_STATUS BLE_MESH_MODEL_OP_GEN_ONPOWERUP_STATUS + +/*!< Generic Power OnOff Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET_UNACK BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET_UNACK + +/*!< Generic Power Level Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET_UNACK BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS + +/*!< Generic Power Level Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET_UNACK BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET_UNACK + +/*!< Generic Battery Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_BATTERY_GET BLE_MESH_MODEL_OP_GEN_BATTERY_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_BATTERY_STATUS BLE_MESH_MODEL_OP_GEN_BATTERY_STATUS + +/*!< Generic Location Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS + +/*!< Generic Location Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK + +/*!< Generic Manufacturer Property Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_GET BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_SET BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_STATUS BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_STATUS + +/*!< Generic Admin Property Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_STATUS BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_STATUS + +/*!< Generic User Property Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS +#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET +#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_STATUS BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_STATUS + +/*!< Generic Client Property Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET +#define ESP_BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS + +/** + * esp_ble_mesh_sensor_message_opcode_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by functions esp_ble_mesh_sensor_client_get_state + * & esp_ble_mesh_sensor_client_set_state. + */ +typedef uint32_t esp_ble_mesh_sensor_message_opcode_t; + +/*!< Sensor Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS +#define ESP_BLE_MESH_MODEL_OP_SENSOR_GET BLE_MESH_MODEL_OP_SENSOR_GET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS BLE_MESH_MODEL_OP_SENSOR_STATUS +#define ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_GET BLE_MESH_MODEL_OP_SENSOR_SERIES_GET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS + +/*!< Sensor Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_GET BLE_MESH_MODEL_OP_SENSOR_SETTING_GET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET BLE_MESH_MODEL_OP_SENSOR_SETTING_SET +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS + +/** + * esp_ble_mesh_time_scene_message_opcode_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by functions esp_ble_mesh_time_scene_client_get_state + * & esp_ble_mesh_time_scene_client_set_state. + */ +typedef uint32_t esp_ble_mesh_time_scene_message_opcode_t; + +/*!< Time Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_TIME_GET BLE_MESH_MODEL_OP_TIME_GET +#define ESP_BLE_MESH_MODEL_OP_TIME_SET BLE_MESH_MODEL_OP_TIME_SET +#define ESP_BLE_MESH_MODEL_OP_TIME_STATUS BLE_MESH_MODEL_OP_TIME_STATUS +#define ESP_BLE_MESH_MODEL_OP_TIME_ROLE_GET BLE_MESH_MODEL_OP_TIME_ROLE_GET +#define ESP_BLE_MESH_MODEL_OP_TIME_ROLE_SET BLE_MESH_MODEL_OP_TIME_ROLE_SET +#define ESP_BLE_MESH_MODEL_OP_TIME_ROLE_STATUS BLE_MESH_MODEL_OP_TIME_ROLE_STATUS +#define ESP_BLE_MESH_MODEL_OP_TIME_ZONE_GET BLE_MESH_MODEL_OP_TIME_ZONE_GET +#define ESP_BLE_MESH_MODEL_OP_TIME_ZONE_SET BLE_MESH_MODEL_OP_TIME_ZONE_SET +#define ESP_BLE_MESH_MODEL_OP_TIME_ZONE_STATUS BLE_MESH_MODEL_OP_TIME_ZONE_STATUS +#define ESP_BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET +#define ESP_BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET +#define ESP_BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS + +/*!< Scene Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_SCENE_GET BLE_MESH_MODEL_OP_SCENE_GET +#define ESP_BLE_MESH_MODEL_OP_SCENE_RECALL BLE_MESH_MODEL_OP_SCENE_RECALL +#define ESP_BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK +#define ESP_BLE_MESH_MODEL_OP_SCENE_STATUS BLE_MESH_MODEL_OP_SCENE_STATUS +#define ESP_BLE_MESH_MODEL_OP_SCENE_REGISTER_GET BLE_MESH_MODEL_OP_SCENE_REGISTER_GET +#define ESP_BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS + +/*!< Scene Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_SCENE_STORE BLE_MESH_MODEL_OP_SCENE_STORE +#define ESP_BLE_MESH_MODEL_OP_SCENE_STORE_UNACK BLE_MESH_MODEL_OP_SCENE_STORE_UNACK +#define ESP_BLE_MESH_MODEL_OP_SCENE_DELETE BLE_MESH_MODEL_OP_SCENE_DELETE +#define ESP_BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK + +/*!< Scheduler Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET +#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS +#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_GET BLE_MESH_MODEL_OP_SCHEDULER_GET +#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_STATUS BLE_MESH_MODEL_OP_SCHEDULER_STATUS + +/*!< Scheduler Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET +#define ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK + +/** + * esp_ble_mesh_light_message_opcode_t belongs to esp_ble_mesh_opcode_t, this typedef is + * only used to locate the opcodes used by functions esp_ble_mesh_light_client_get_state + * & esp_ble_mesh_light_client_set_state. + */ +typedef uint32_t esp_ble_mesh_light_message_opcode_t; + +/*!< Light Lightness Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS + +/*!< Light Lightness Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET_UNACK + +/*!< Light CTL Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_GET BLE_MESH_MODEL_OP_LIGHT_CTL_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_SET BLE_MESH_MODEL_OP_LIGHT_CTL_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS + +/*!< Light CTL Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK + +/*!< Light HSL Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_GET BLE_MESH_MODEL_OP_LIGHT_HSL_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SET BLE_MESH_MODEL_OP_LIGHT_HSL_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS + +/*!< Light HSL Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK /* Model spec is wrong */ + +/*!< Light xyL Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_GET BLE_MESH_MODEL_OP_LIGHT_XYL_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_SET BLE_MESH_MODEL_OP_LIGHT_XYL_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_XYL_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS + +/*!< Light xyL Setup Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET_UNACK + +/*!< Light Control Message Opcode */ +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_GET BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_GET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK +#define ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS + +typedef uint32_t esp_ble_mesh_opcode_t; +/*!< End of defines of esp_ble_mesh_opcode_t */ + +/** + * This typedef is only used to indicate the status code contained in some of the + * server models (e.g. Generic Server Model) status message. + */ +typedef uint8_t esp_ble_mesh_model_status_t; + +#define ESP_BLE_MESH_MODEL_STATUS_SUCCESS 0x00 +#define ESP_BLE_MESH_MODEL_STATUS_CANNOT_SET_RANGE_MIN 0x01 +#define ESP_BLE_MESH_MODEL_STATUS_CANNOT_SET_RANGE_MAX 0x02 + +/** + * @brief BLE Mesh client models related definitions + */ + +/** Client model Get/Set message opcode and corresponding Status message opcode */ +typedef struct { + uint32_t cli_op; /*!< The client message opcode */ + uint32_t status_op; /*!< The server status opcode corresponding to the client message opcode */ +} esp_ble_mesh_client_op_pair_t; + +/** Client Model user data context. */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the client model. Initialized by the stack. */ + int op_pair_size; /*!< Size of the op_pair */ + const esp_ble_mesh_client_op_pair_t *op_pair; /*!< Table containing get/set message opcode and corresponding status message opcode */ + uint32_t publish_status; /*!< Callback used to handle the received unsoliciated message. Initialized by the stack. */ + void *internal_data; /*!< Pointer to the internal data of client model */ + uint8_t msg_role; /*!< Role of the device (Node/Provisioner) that is going to send messages */ +} esp_ble_mesh_client_t; + +/** Common parameters of the messages sent by Client Model. */ +typedef struct { + esp_ble_mesh_opcode_t opcode; /*!< Message opcode */ + esp_ble_mesh_model_t *model; /*!< Pointer to the client model structure */ + esp_ble_mesh_msg_ctx_t ctx; /*!< The context used to send message */ + int32_t msg_timeout; /*!< Timeout value (ms) to get response to the sent message */ + /*!< Note: if using default timeout value in menuconfig, make sure to set this value to 0 */ + uint8_t msg_role; /*!< Role of the device - Node/Provisioner */ +} esp_ble_mesh_client_common_param_t; + +/** + * @brief BLE Mesh server models related definitions + */ + +/** This enum value is the flag of transition timer operation */ +enum { + ESP_BLE_MESH_SERVER_TRANS_TIMER_START, /* Proper transition timer has been started */ + ESP_BLE_MESH_SERVER_FLAG_MAX, +}; + +/** Parameters of the server model state transition */ +typedef struct { + bool just_started; /*!< Indicate if the state transition has just started */ + + uint8_t trans_time; /*!< State transition time */ + uint8_t remain_time; /*!< Remaining time of state transition */ + uint8_t delay; /*!< Delay before starting state transition */ + uint32_t quo_tt; /*!< Duration of each divided transition step */ + uint32_t counter; /*!< Number of steps which the transition duration is divided */ + uint32_t total_duration; /*!< State transition total duration */ + int64_t start_timestamp; /*!< Time when the state transition is started */ + + /** + * Flag used to indicate if the transition timer has been started internally. + * + * If the model which contains esp_ble_mesh_state_transition_t sets "set_auto_rsp" + * to ESP_BLE_MESH_SERVER_RSP_BY_APP, the handler of the timer shall be initialized + * by the users. + * + * And users can use this flag to indicate whether the timer is started or not. + */ + BLE_MESH_ATOMIC_DEFINE(flag, ESP_BLE_MESH_SERVER_FLAG_MAX); + struct k_delayed_work timer; /*!< Timer used for state transition */ +} esp_ble_mesh_state_transition_t; + +/** Parameters of the server model received last same set message. */ +typedef struct { + uint8_t tid; /*!< Transaction number of the last message */ + uint16_t src; /*!< Source address of the last message */ + uint16_t dst; /*!< Destination address of the last messgae */ + int64_t timestamp; /*!< Time when the last message is received */ +} esp_ble_mesh_last_msg_info_t; + +#define ESP_BLE_MESH_SERVER_RSP_BY_APP 0 /*!< Response will be sent internally */ +#define ESP_BLE_MESH_SERVER_AUTO_RSP 1 /*!< Response need to be sent in the application */ + +/** Parameters of the Server Model response control */ +typedef struct { + /** + * @brief BLE Mesh Server Response Option + * 1. If get_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, then the + * response of Client Get messages need to be replied by the application; + * 2. If get_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, then the + * response of Client Get messages will be replied by the server models; + * 3. If set_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, then the + * response of Client Set messages need to be replied by the application; + * 4. If set_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, then the + * response of Client Set messages will be replied by the server models; + * 5. If status_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, then the + * response of Server Status messages need to be replied by the application; + * 6. If status_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, then the + * response of Server Status messages will be replied by the server models; + */ + uint8_t get_auto_rsp : 1, /*!< Response control for Client Get messages */ + set_auto_rsp : 1, /*!< Response control for Client Set messages */ + status_auto_rsp : 1; /*!< Response control for Server Status messages */ +} esp_ble_mesh_server_rsp_ctrl_t; + +/** + * @brief Server model state value union + */ +typedef union { + struct { + uint8_t onoff; /*!< The value of the Generic OnOff state */ + } gen_onoff; /*!< The Generic OnOff state */ + struct { + int16_t level; /*!< The value of the Generic Level state */ + } gen_level; /*!< The Generic Level state */ + struct { + uint8_t onpowerup; /*!< The value of the Generic OnPowerUp state */ + } gen_onpowerup; /*!< The Generic OnPowerUp state */ + struct { + uint16_t power; /*!< The value of the Generic Power Actual state */ + } gen_power_actual; /*!< The Generic Power Actual state */ + struct { + uint16_t lightness; /*!< The value of the Light Lightness Actual state */ + } light_lightness_actual; /*!< The Light Lightness Actual state */ + struct { + uint16_t lightness; /*!< The value of the Light Lightness Linear state */ + } light_lightness_linear; /*!< The Light Lightness Linear state */ + struct { + uint16_t lightness; /*!< The value of the Light CTL Lightness state */ + } light_ctl_lightness; /*!< The Light CTL Lightness state */ + struct { + uint16_t temperature; /*!< The value of the Light CTL Temperature state */ + int16_t delta_uv; /*!< The value of the Light CTL Delta UV state */ + } light_ctl_temp_delta_uv; /*!< The Light CTL Temperature & Delta UV states */ + struct { + uint16_t lightness; /*!< The value of the Light HSL Lightness state */ + } light_hsl_lightness; /*!< The Light HSL Lightness state */ + struct { + uint16_t hue; /*!< The value of the Light HSL Hue state */ + } light_hsl_hue; /*!< The Light HSL Hue state */ + struct { + uint16_t saturation; /*!< The value of the Light HSL Saturation state */ + } light_hsl_saturation; /*!< The Light HSL Saturation state */ + struct { + uint16_t lightness; /*!< The value of the Light xyL Lightness state */ + } light_xyl_lightness; /*!< The Light xyL Lightness state */ + struct { + uint8_t onoff; /*!< The value of the Light LC Light OnOff state */ + } light_lc_light_onoff; /*!< The Light LC Light OnOff state */ +} esp_ble_mesh_server_state_value_t; + +/** This enum value is the type of server model states */ +typedef enum { + ESP_BLE_MESH_GENERIC_ONOFF_STATE, + ESP_BLE_MESH_GENERIC_LEVEL_STATE, + ESP_BLE_MESH_GENERIC_ONPOWERUP_STATE, + ESP_BLE_MESH_GENERIC_POWER_ACTUAL_STATE, + ESP_BLE_MESH_LIGHT_LIGHTNESS_ACTUAL_STATE, + ESP_BLE_MESH_LIGHT_LIGHTNESS_LINEAR_STATE, + ESP_BLE_MESH_LIGHT_CTL_LIGHTNESS_STATE, + ESP_BLE_MESH_LIGHT_CTL_TEMP_DELTA_UV_STATE, + ESP_BLE_MESH_LIGHT_HSL_LIGHTNESS_STATE, + ESP_BLE_MESH_LIGHT_HSL_HUE_STATE, + ESP_BLE_MESH_LIGHT_HSL_SATURATION_STATE, + ESP_BLE_MESH_LIGHT_XYL_LIGHTNESS_STATE, + ESP_BLE_MESH_LIGHT_LC_LIGHT_ONOFF_STATE, + ESP_BLE_MESH_SERVER_MODEL_STATE_MAX, +} esp_ble_mesh_server_state_type_t; + +/*!< This enum value is the event of undefined SIG models and vendor models */ +typedef enum { + ESP_BLE_MESH_MODEL_OPERATION_EVT, /*!< User-defined models receive messages from peer devices (e.g. get, set, status, etc) event */ + ESP_BLE_MESH_MODEL_SEND_COMP_EVT, /*!< User-defined models send messages completion event */ + ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT, /*!< User-defined models publish messages completion event */ + ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT, /*!< User-defined client models receive publish messages event */ + ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT, /*!< Timeout event for the user-defined client models that failed to receive response from peer server models */ + ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT, /*!< When a model is configured to publish messages periodically, this event will occur during every publish period */ + ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_COMP_EVT, /*!< Server models update state value completion event */ + ESP_BLE_MESH_MODEL_EVT_MAX, +} esp_ble_mesh_model_cb_event_t; + /** * @brief BLE Mesh model callback parameters union */ @@ -1579,22 +1919,14 @@ typedef union { struct ble_mesh_model_publish_update_evt_param { esp_ble_mesh_model_t *model; /*!< Pointer to the model which is going to update its publish message */ } model_publish_update; /*!< Event parameter of ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT */ + /** + * @brief ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_COMP_EVT + */ + struct ble_mesh_server_model_update_state_comp_param { + int err_code; /*!< Indicate the result of updating server model state */ + esp_ble_mesh_model_t *model; /*!< Pointer to the server model which state value is updated */ + esp_ble_mesh_server_state_type_t type; /*!< Type of the updated server state */ + } server_model_update_state; /*!< Event parameter of ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_COMP_EVT */ } esp_ble_mesh_model_cb_param_t; -/** Client Model Get/Set message opcode and corresponding Status message opcode */ -typedef struct { - uint32_t cli_op; /*!< The client message opcode */ - uint32_t status_op; /*!< The server status opcode corresponding to the client message opcode */ -} esp_ble_mesh_client_op_pair_t; - -/** Client Model user data context. */ -typedef struct { - esp_ble_mesh_model_t *model; /*!< Pointer to the client model. Initialized by the stack. */ - int op_pair_size; /*!< Size of the op_pair */ - const esp_ble_mesh_client_op_pair_t *op_pair; /*!< Table containing get/set message opcode and corresponding status message opcode */ - uint32_t publish_status; /*!< Callback used to handle the received unsoliciated message. Initialized by the stack. */ - void *internal_data; /*!< Pointer to the internal data of client model */ - uint8_t msg_role; /*!< Role of the device (Node/Provisioner) that is going to send messages */ -} esp_ble_mesh_client_t; - #endif /* _ESP_BLE_MESH_DEFS_H_ */ diff --git a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_generic_model_api.c b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_generic_model_api.c index 24d55dec3..1bac6aea3 100644 --- a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_generic_model_api.c +++ b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_generic_model_api.c @@ -70,3 +70,10 @@ esp_err_t esp_ble_mesh_generic_client_set_state(esp_ble_mesh_client_common_param return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_generic_client_args_t), btc_ble_mesh_generic_client_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } + +esp_err_t esp_ble_mesh_register_generic_server_callback(esp_ble_mesh_generic_server_cb_t callback) +{ + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + return (btc_profile_cb_set(BTC_PID_GENERIC_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_health_model_api.c b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_health_model_api.c index 4c32ab6d4..59e73c224 100644 --- a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_health_model_api.c +++ b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_health_model_api.c @@ -83,12 +83,16 @@ esp_err_t esp_ble_mesh_health_server_fault_update(esp_ble_mesh_elem_t *element) btc_ble_mesh_health_server_args_t arg = {0}; btc_msg_t msg = {0}; + if (element == NULL) { + 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_HEALTH_SERVER; msg.act = BTC_BLE_MESH_ACT_HEALTH_SERVER_FAULT_UPDATE; - arg.fault_update.element = element; + arg.health_fault_update.element = element; return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_health_server_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); diff --git a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_lighting_model_api.c b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_lighting_model_api.c index 33dba45ab..05317e307 100644 --- a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_lighting_model_api.c +++ b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_lighting_model_api.c @@ -71,3 +71,9 @@ esp_err_t esp_ble_mesh_light_client_set_state(esp_ble_mesh_client_common_param_t == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_ble_mesh_register_lighting_server_callback(esp_ble_mesh_lighting_server_cb_t callback) +{ + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + return (btc_profile_cb_set(BTC_PID_LIGHTING_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL); +} diff --git a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_sensor_model_api.c b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_sensor_model_api.c index 7a74b7554..c4e8743de 100644 --- a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_sensor_model_api.c +++ b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_sensor_model_api.c @@ -71,3 +71,11 @@ esp_err_t esp_ble_mesh_sensor_client_set_state(esp_ble_mesh_client_common_param_ == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_ble_mesh_register_sensor_server_callback(esp_ble_mesh_sensor_server_cb_t callback) +{ + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + return (btc_profile_cb_set(BTC_PID_SENSOR_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL); +} + + diff --git a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_time_scene_model_api.c b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_time_scene_model_api.c index 482638011..e9afacdea 100644 --- a/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_time_scene_model_api.c +++ b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_time_scene_model_api.c @@ -71,3 +71,10 @@ esp_err_t esp_ble_mesh_time_scene_client_set_state(esp_ble_mesh_client_common_pa == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_ble_mesh_register_time_scene_server_callback(esp_ble_mesh_time_scene_server_cb_t callback) +{ + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + return (btc_profile_cb_set(BTC_PID_TIME_SCENE_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL); +} + diff --git a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h index 66f1d17d4..9d1785cff 100644 --- a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h +++ b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h @@ -79,8 +79,8 @@ typedef struct esp_ble_mesh_cfg_srv { uint8_t min_hops; /*!< Minimum hops when receiving Heartbeat messages */ uint8_t max_hops; /*!< Maximum hops when receiving Heartbeat messages */ - /** Optional subscription tracking function */ - void (*func)(uint8_t hops, uint16_t feature); + /** Optional heartbeat subscription tracking function */ + esp_ble_mesh_cb_t heartbeat_recv_cb; } heartbeat_sub; } esp_ble_mesh_cfg_srv_t; @@ -513,8 +513,8 @@ typedef struct { /** Parameters of Config Network Transmit Status */ typedef struct { - uint8_t net_trans_count:3; /*!< Number of transmissions for each Network PDU originating from the node */ - uint8_t net_trans_step :5; /*!< Maximum hops when receiving Heartbeat messages */ + uint8_t net_trans_count: 3; /*!< Number of transmissions for each Network PDU originating from the node */ + uint8_t net_trans_step : 5; /*!< Maximum hops when receiving Heartbeat messages */ } esp_ble_mesh_cfg_net_trans_status_cb_t; /** Parameters of Config SIG/Vendor Subscription List */ @@ -610,28 +610,135 @@ typedef enum { ESP_BLE_MESH_CFG_CLIENT_EVT_MAX, } esp_ble_mesh_cfg_client_cb_event_t; -/** Parameter of Config AppKey Add */ +/** + * @brief Configuration Server model related context. + */ + typedef struct { - uint16_t app_idx; /*!< AppKey Index of the Config AppKey Add */ -} esp_ble_mesh_cfg_srv_app_key_add_cb_t; + uint16_t element_addr; /*!< Element Address */ + uint16_t pub_addr; /*!< Publish Address */ + uint16_t app_idx; /*!< AppKey Index */ + bool cred_flag; /*!< Friendship Credential Flag */ + uint8_t pub_ttl; /*!< Publish TTL */ + uint8_t pub_period; /*!< Publish Period */ + uint8_t pub_retransmit; /*!< Publish Retransmit */ + uint16_t company_id; /*!< Company ID */ + uint16_t model_id; /*!< Model ID */ +} esp_ble_mesh_state_change_cfg_mod_pub_set_t; + +/** Parameters of Config Model Subscription Add */ +typedef struct { + uint16_t element_addr; /*!< Element Address */ + uint16_t sub_addr; /*!< Subscription Address */ + uint16_t company_id; /*!< Company ID */ + uint16_t model_id; /*!< Model ID */ +} esp_ble_mesh_state_change_cfg_model_sub_add_t; + +/** Parameters of Config Model Subscription Delete */ +typedef struct { + uint16_t element_addr; /*!< Element Address */ + uint16_t sub_addr; /*!< Subscription Address */ + uint16_t company_id; /*!< Company ID */ + uint16_t model_id; /*!< Model ID */ +} esp_ble_mesh_state_change_cfg_model_sub_delete_t; + +/** Parameters of Config NetKey Add */ +typedef struct { + uint16_t net_idx; /*!< NetKey Index */ + uint8_t net_key[16]; /*!< NetKey */ +} esp_ble_mesh_state_change_cfg_netkey_add_t; + +/** Parameters of Config NetKey Update */ +typedef struct { + uint16_t net_idx; /*!< NetKey Index */ + uint8_t net_key[16]; /*!< NetKey */ +} esp_ble_mesh_state_change_cfg_netkey_update_t; + +/** Parameter of Config NetKey Delete */ +typedef struct { + uint16_t net_idx; /*!< NetKey Index */ +} esp_ble_mesh_state_change_cfg_netkey_delete_t; + +/** Parameters of Config AppKey Add */ +typedef struct { + uint16_t net_idx; /*!< NetKey Index */ + uint16_t app_idx; /*!< AppKey Index */ + uint8_t app_key[16]; /*!< AppKey */ +} esp_ble_mesh_state_change_cfg_appkey_add_t; + +/** Parameters of Config AppKey Update */ +typedef struct { + uint16_t net_idx; /*!< NetKey Index */ + uint16_t app_idx; /*!< AppKey Index */ + uint8_t app_key[16]; /*!< AppKey */ +} esp_ble_mesh_state_change_cfg_appkey_update_t; + +/** Parameters of Config AppKey Delete */ +typedef struct { + uint16_t net_idx; /*!< NetKey Index */ + uint16_t app_idx; /*!< AppKey Index */ +} esp_ble_mesh_state_change_cfg_appkey_delete_t; + +/** Parameters of Config Model App Bind */ +typedef struct { + uint16_t element_addr; /*!< Element Address */ + uint16_t app_idx; /*!< AppKey Index */ + uint16_t company_id; /*!< Company ID */ + uint16_t model_id; /*!< Model ID */ +} esp_ble_mesh_state_change_cfg_model_app_bind_t; + +/** Parameters of Config Model App Unbind */ +typedef struct { + uint16_t element_addr; /*!< Element Address */ + uint16_t app_idx; /*!< AppKey Index */ + uint16_t company_id; /*!< Company ID */ + uint16_t model_id; /*!< Model ID */ +} esp_ble_mesh_state_change_cfg_model_app_unbind_t; + +/** Parameters of Config Key Refresh Phase Set */ +typedef struct { + uint16_t net_idx; /*!< NetKey Index */ + uint8_t kr_phase; /*!< New Key Refresh Phase Transition */ +} esp_ble_mesh_state_change_cfg_kr_phase_set_t; /** - * @brief Configuration Server Model received message union + * @brief Configuration Server model state change value union */ typedef union { - esp_ble_mesh_cfg_srv_app_key_add_cb_t app_key_add; /*!< The Config AppKey Add event value */ -} esp_ble_mesh_cfg_server_common_cb_param_t; + /** + * The recv_op in ctx can be used to decide which state is changed. + */ + esp_ble_mesh_state_change_cfg_mod_pub_set_t mod_pub_set; /*!< Config Model Publication Set */ + esp_ble_mesh_state_change_cfg_model_sub_add_t mod_sub_add; /*!< Config Model Subscription Add */ + esp_ble_mesh_state_change_cfg_model_sub_delete_t mod_sub_delete; /*!< Config Model Subscription Delete */ + esp_ble_mesh_state_change_cfg_netkey_add_t netkey_add; /*!< Config NetKey Add */ + esp_ble_mesh_state_change_cfg_netkey_update_t netkey_update; /*!< Config NetKey Update */ + esp_ble_mesh_state_change_cfg_netkey_delete_t netkey_delete; /*!< Config NetKey Delete */ + esp_ble_mesh_state_change_cfg_appkey_add_t appkey_add; /*!< Config AppKey Add */ + esp_ble_mesh_state_change_cfg_appkey_update_t appkey_update; /*!< Config AppKey Update */ + esp_ble_mesh_state_change_cfg_appkey_delete_t appkey_delete; /*!< Config AppKey Delete */ + esp_ble_mesh_state_change_cfg_model_app_bind_t mod_app_bind; /*!< Config Model App Bind */ + esp_ble_mesh_state_change_cfg_model_app_unbind_t mod_app_unbind; /*!< Config Model App Unbind */ + esp_ble_mesh_state_change_cfg_kr_phase_set_t kr_phase_set; /*!< Config Key Refresh Phase Set */ +} esp_ble_mesh_cfg_server_state_change_t; -/** Configuration Server Model callback parameters */ +/** + * @brief Configuration Server model callback value union + */ +typedef union { + esp_ble_mesh_cfg_server_state_change_t state_change; /*!< ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT */ +} esp_ble_mesh_cfg_server_cb_value_t; + +/** Configuration Server model callback parameters */ typedef struct { - esp_ble_mesh_model_t *model; /*!< Pointer to the server model structure */ - esp_ble_mesh_msg_ctx_t ctx; /*!< The context of the received message */ - esp_ble_mesh_cfg_server_common_cb_param_t status_cb; /*!< The received configuration message callback values */ + esp_ble_mesh_model_t *model; /*!< Pointer to the server model structure */ + esp_ble_mesh_msg_ctx_t ctx; /*!< Context of the received message */ + esp_ble_mesh_cfg_server_cb_value_t value; /*!< Value of the received configuration messages */ } esp_ble_mesh_cfg_server_cb_param_t; -/** This enum value is the event of Configuration Server Model */ +/** This enum value is the event of Configuration Server model */ typedef enum { - ESP_BLE_MESH_CFG_SERVER_RECV_MSG_EVT, + ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT, ESP_BLE_MESH_CFG_SERVER_EVT_MAX, } esp_ble_mesh_cfg_server_cb_event_t; diff --git a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h index df9fb3c2d..fcee7ce53 100644 --- a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h +++ b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h @@ -523,6 +523,775 @@ esp_err_t esp_ble_mesh_generic_client_get_state(esp_ble_mesh_client_common_param esp_err_t esp_ble_mesh_generic_client_set_state(esp_ble_mesh_client_common_param_t *params, esp_ble_mesh_generic_client_set_state_t *set_state); +/** + * @brief Generic Server Models related context. + */ + +/** @def ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV + * + * @brief Define a new Generic OnOff Server Model. + * + * @note 1. The Generic OnOff Server Model is a root model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_onoff_srv_t. + * + * @return New Generic OnOff Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_LEVEL_SRV + * + * @brief Define a new Generic Level Server Model. + * + * @note 1. The Generic Level Server Model is a root model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_level_srv_t. + * + * @return New Generic Level Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_LEVEL_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_LEVEL_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_DEF_TRANS_TIME_SRV + * + * @brief Define a new Generic Default Transition Time Server Model. + * + * @note 1. The Generic Default Transition Time Server Model is a root model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_def_trans_time_srv_t. + * + * @return New Generic Default Transition Time Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_DEF_TRANS_TIME_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_POWER_ONOFF_SRV + * + * @brief Define a new Generic Power OnOff Server Model. + * + * @note 1. The Generic Power OnOff Server model extends the Generic OnOff Server + * model. When this model is present on an element, the corresponding + * Generic Power OnOff Setup Server model shall also be present. + * 2. This model may be used to represent a variety of devices that do not + * fit any of the model descriptions that have been defined but support + * the generic properties of On/Off. + * 3. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_power_onoff_srv_t. + * + * @return New Generic Power OnOff Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_POWER_ONOFF_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_POWER_ONOFF_SETUP_SRV + * + * @brief Define a new Generic Power OnOff Setup Server Model. + * + * @note 1. The Generic Power OnOff Setup Server model extends the Generic Power + * OnOff Server model and the Generic Default Transition Time Server model. + * 2. This model shall support model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_power_onoff_setup_srv_t. + * + * @return New Generic Power OnOff Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_POWER_ONOFF_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_POWER_LEVEL_SRV + * + * @brief Define a new Generic Power Level Server Model. + * + * @note 1. The Generic Power Level Server model extends the Generic Power OnOff + * Server model and the Generic Level Server model. When this model is + * present on an Element, the corresponding Generic Power Level Setup + * Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_power_level_srv_t. + * + * @return New Generic Power Level Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_POWER_LEVEL_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_POWER_LEVEL_SETUP_SRV + * + * @brief Define a new Generic Power Level Setup Server Model. + * + * @note 1. The Generic Power Level Setup Server model extends the Generic Power + * Level Server model and the Generic Power OnOff Setup Server model. + * 2. This model shall support model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_power_level_setup_srv_t. + * + * @return New Generic Power Level Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_POWER_LEVEL_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_BATTERY_SRV + * + * @brief Define a new Generic Battery Server Model. + * + * @note 1. The Generic Battery Server Model is a root model. + * 2. This model shall support model publication and model subscription. + * 3. The model may be used to represent an element that is powered by a battery. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_battery_srv_t. + * + * @return New Generic Battery Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_BATTERY_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_BATTERY_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_LOCATION_SRV + * + * @brief Define a new Generic Location Server Model. + * + * @note 1. The Generic Location Server model is a root model. When this model + * is present on an Element, the corresponding Generic Location Setup + * Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * 3. The model may be used to represent an element that knows its + * location (global or local). + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_location_srv_t. + * + * @return New Generic Location Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_LOCATION_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_LOCATION_SETUP_SRV + * + * @brief Define a new Generic Location Setup Server Model. + * + * @note 1. The Generic Location Setup Server model extends the Generic Location + * Server model. + * 2. This model shall support model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_location_setup_srv_t. + * + * @return New Generic Location Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_LOCATION_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_USER_PROP_SRV + * + * @brief Define a new Generic User Property Server Model. + * + * @note 1. The Generic User Property Server model is a root model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_user_prop_srv_t. + * + * @return New Generic User Property Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_USER_PROP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_ADMIN_PROP_SRV + * + * @brief Define a new Generic Admin Property Server Model. + * + * @note 1. The Generic Admin Property Server model extends the Generic User + * Property Server model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_admin_prop_srv_t. + * + * @return New Generic Admin Property Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_ADMIN_PROP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_MANUFACTURER_PROP_SRV + * + * @brief Define a new Generic Manufacturer Property Server Model. + * + * @note 1. The Generic Manufacturer Property Server model extends the Generic + * User Property Server model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_manu_prop_srv_t. + * + * @return New Generic Manufacturer Property Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_MANUFACTURER_PROP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_GEN_CLIENT_PROP_SRV + * + * @brief Define a new Generic User Property Server Model. + * + * @note 1. The Generic Client Property Server model is a root model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_gen_client_prop_srv_t. + * + * @return New Generic Client Property Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_GEN_CLIENT_PROP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV, \ + NULL, srv_pub, srv_data) + +/** Parameters of Generic OnOff state */ +typedef struct { + uint8_t onoff; /*!< The present value of the Generic OnOff state */ + uint8_t target_onoff; /*!< The target value of the Generic OnOff state */ +} esp_ble_mesh_gen_onoff_state_t; + +/** User data of Generic OnOff Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic OnOff Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_onoff_state_t state; /*!< Parameters of the Generic OnOff state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ +} esp_ble_mesh_gen_onoff_srv_t; + +/** Parameters of Generic Level state */ +typedef struct { + int16_t level; /*!< The present value of the Generic Level state */ + int16_t target_level; /*!< The target value of the Generic Level state */ + + /** + * When a new transaction starts, level should be set to last_last, and use + * "level + incoming delta" to calculate the target level. In another word, + * "last_level" is used to record "level" of the last transaction, and + * "last_delta" is used to record the previously received delta_level value. + */ + int16_t last_level; /*!< The last value of the Generic Level state */ + int32_t last_delta; /*!< The last delta change of the Generic Level state */ + + bool move_start; /*!< Indicate if the transition of the Generic Level state has been started */ + bool positive; /*!< Indicate if the transition is positive or negative */ +} esp_ble_mesh_gen_level_state_t; + +/** User data of Generic Level Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Level Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_level_state_t state; /*!< Parameters of the Generic Level state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_level; /*!< Delta change value of level state transition */ +} esp_ble_mesh_gen_level_srv_t; + +/** Parameter of Generic Default Transition Time state */ +typedef struct { + uint8_t trans_time; /*!< The value of the Generic Default Transition Time state */ +} esp_ble_mesh_gen_def_trans_time_state_t; + +/** User data of Generic Default Transition Time Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Default Transition Time Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_def_trans_time_state_t state; /*!< Parameters of the Generic Default Transition Time state */ +} esp_ble_mesh_gen_def_trans_time_srv_t; + +/** Parameter of Generic OnPowerUp state */ +typedef struct { + uint8_t onpowerup; /*!< The value of the Generic OnPowerUp state */ +} esp_ble_mesh_gen_onpowerup_state_t; + +/** User data of Generic Power OnOff Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Power OnOff Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_onpowerup_state_t *state; /*!< Parameters of the Generic OnPowerUp state */ +} esp_ble_mesh_gen_power_onoff_srv_t; + +/** User data of Generic Power OnOff Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Power OnOff Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_onpowerup_state_t *state; /*!< Parameters of the Generic OnPowerUp state */ +} esp_ble_mesh_gen_power_onoff_setup_srv_t; + +/** Parameters of Generic Power Level state */ +typedef struct { + uint16_t power_actual; /*!< The present value of the Generic Power Actual state */ + uint16_t target_power_actual; /*!< The target value of the Generic Power Actual state */ + + uint16_t power_last; /*!< The value of the Generic Power Last state */ + uint16_t power_default; /*!< The value of the Generic Power Default state */ + + uint8_t status_code; /*!< The status code of setting Generic Power Range state */ + uint16_t power_range_min; /*!< The minimum value of the Generic Power Range state */ + uint16_t power_range_max; /*!< The maximum value of the Generic Power Range state */ +} esp_ble_mesh_gen_power_level_state_t; + +/** User data of Generic Power Level Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Power Level Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_power_level_state_t *state; /*!< Parameters of the Generic Power Level state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_level; /*!< Delta change value of level state transition */ +} esp_ble_mesh_gen_power_level_srv_t; + +/** User data of Generic Power Level Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Power Level Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_power_level_state_t *state; /*!< Parameters of the Generic Power Level state */ +} esp_ble_mesh_gen_power_level_setup_srv_t; + +/** Parameters of Generic Battery state */ +typedef struct { + uint32_t battery_level : 8, /*!< The value of the Generic Battery Level state */ + time_to_discharge : 24; /*!< The value of the Generic Battery Time to Discharge state */ + uint32_t time_to_charge : 24, /*!< The value of the Generic Battery Time to Charge state */ + battery_flags : 8; /*!< The value of the Generic Battery Flags state */ +} esp_ble_mesh_gen_battery_state_t; + +/** User data of Generic Battery Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Battery Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_battery_state_t state; /*!< Parameters of the Generic Battery state */ +} esp_ble_mesh_gen_battery_srv_t; + +/** Parameters of Generic Location state */ +typedef struct { + int32_t global_latitude; /*!< The value of the Global Latitude field */ + int32_t global_longitude; /*!< The value of the Global Longtitude field */ + int16_t global_altitude; /*!< The value of the Global Altitude field */ + int16_t local_north; /*!< The value of the Local North field */ + int16_t local_east; /*!< The value of the Local East field */ + int16_t local_altitude; /*!< The value of the Local Altitude field */ + uint8_t floor_number; /*!< The value of the Floor Number field */ + uint16_t uncertainty; /*!< The value of the Uncertainty field */ +} esp_ble_mesh_gen_location_state_t; + +/** User data of Generic Location Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Location Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_location_state_t *state; /*!< Parameters of the Generic Location state */ +} esp_ble_mesh_gen_location_srv_t; + +/** User data of Generic Location Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Location Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_gen_location_state_t *state; /*!< Parameters of the Generic Location state */ +} esp_ble_mesh_gen_location_setup_srv_t; + +/** This enum value is the access vlue of Generic User Property */ +typedef enum { + ESP_BLE_MESH_GEN_USER_ACCESS_PROHIBIT, + ESP_BLE_MESH_GEN_USER_ACCESS_READ, + ESP_BLE_MESH_GEN_USER_ACCESS_WRITE, + ESP_BLE_MESH_GEN_USER_ACCESS_READ_WRITE, +} esp_ble_mesh_gen_user_prop_access_t; + +/** This enum value is the access value of Generic Admin Property */ +typedef enum { + ESP_BLE_MESH_GEN_ADMIN_NOT_USER_PROP, + ESP_BLE_MESH_GEN_ADMIN_ACCESS_READ, + ESP_BLE_MESH_GEN_ADMIN_ACCESS_WRITE, + ESP_BLE_MESH_GEN_ADMIN_ACCESS_READ_WRITE, +} esp_ble_mesh_gen_admin_prop_access_t; + +/** This enum value is the access value of Generic Manufacturer Property */ +typedef enum { + ESP_BLE_MESH_GEN_MANU_NOT_USER_PROP, + ESP_BLE_MESH_GEN_MANU_ACCESS_READ, +} esp_ble_mesh_gen_manu_prop_access_t; + +/** Parameters of Generic Property states */ +typedef struct { + uint16_t id; /*!< The value of User/Admin/Manufacturer Property ID */ + uint8_t user_access; /*!< The value of User Access field */ + uint8_t admin_access; /*!< The value of Admin Access field */ + uint8_t manu_access; /*!< The value of Manufacturer Access field */ + struct net_buf_simple *val; /*!< The value of User/Admin/Manufacturer Property */ +} esp_ble_mesh_generic_property_t; + +/** User data of Generic User Property Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic User Property Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + uint8_t property_count; /*!< Generic User Property count */ + esp_ble_mesh_generic_property_t *properties; /*!< Parameters of the Generic User Property state */ +} esp_ble_mesh_gen_user_prop_srv_t; + +/** User data of Generic Admin Property Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Admin Property Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + uint8_t property_count; /*!< Generic Admin Property count */ + esp_ble_mesh_generic_property_t *properties; /*!< Parameters of the Generic Admin Property state */ +} esp_ble_mesh_gen_admin_prop_srv_t; + +/** User data of Generic Manufacturer Property Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Manufacturer Property Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + uint8_t property_count; /*!< Generic Manufacturer Property count */ + esp_ble_mesh_generic_property_t *properties; /*!< Parameters of the Generic Manufacturer Property state */ +} esp_ble_mesh_gen_manu_prop_srv_t; + +/** User data of Generic Client Property Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Generic Client Property Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + uint8_t id_count; /*!< Generic Client Property ID count */ + uint16_t *property_ids; /*!< Parameters of the Generic Client Property state */ +} esp_ble_mesh_gen_client_prop_srv_t; + +/** Parameter of Generic OnOff Set state change event */ +typedef struct { + uint8_t onoff; /*!< The value of Generic OnOff state */ +} esp_ble_mesh_state_change_gen_onoff_set_t; + +/** Parameter of Generic Level Set state change event */ +typedef struct { + int16_t level; /*!< The value of Generic Level state */ +} esp_ble_mesh_state_change_gen_level_set_t; + +/** Parameter of Generic Delta Set state change event */ +typedef struct { + int16_t level; /*!< The value of Generic Level state */ +} esp_ble_mesh_state_change_gen_delta_set_t; + +/** Parameter of Generic Move Set state change event */ +typedef struct { + int16_t level; /*!< The value of Generic Level state */ +} esp_ble_mesh_state_change_gen_move_set_t; + +/** Parameter of Generic Default Transition Time Set state change event */ +typedef struct { + uint8_t trans_time; /*!< The value of Generic Default Transition Time state */ +} esp_ble_mesh_state_change_gen_def_trans_time_set_t; + +/** Parameter of Generic OnPowerUp Set state change event */ +typedef struct { + uint8_t onpowerup; /*!< The value of Generic OnPowerUp state */ +} esp_ble_mesh_state_change_gen_onpowerup_set_t; + +/** Parameter of Generic Power Level Set state change event */ +typedef struct { + uint16_t power; /*!< The value of Generic Power Actual state */ +} esp_ble_mesh_state_change_gen_power_level_set_t; + +/** Parameter of Generic Power Default Set state change event */ +typedef struct { + uint16_t power; /*!< The value of Generic Power Default state */ +} esp_ble_mesh_state_change_gen_power_default_set_t; + +/** Parameters of Generic Power Range Set state change event */ +typedef struct { + uint16_t range_min; /*!< The minimum value of Generic Power Range state */ + uint16_t range_max; /*!< The maximum value of Generic Power Range state */ +} esp_ble_mesh_state_change_gen_power_range_set_t; + +/** Parameters of Generic Location Global Set state change event */ +typedef struct { + int32_t latitude; /*!< The Global Latitude value of Generic Location state */ + int32_t longitude; /*!< The Global Longitude value of Generic Location state */ + int16_t altitude; /*!< The Global Altitude value of Generic Location state */ +} esp_ble_mesh_state_change_gen_loc_global_set_t; + +/** Parameters of Generic Location Local Set state change event */ +typedef struct { + int16_t north; /*!< The Local North value of Generic Location state */ + int16_t east; /*!< The Local East value of Generic Location state */ + int16_t altitude; /*!< The Local Altitude value of Generic Location state */ + uint8_t floor_number; /*!< The Floor Number value of Generic Location state */ + uint16_t uncertainty; /*!< The Uncertainty value of Generic Location state */ +} esp_ble_mesh_state_change_gen_loc_local_set_t; + +/** Parameters of Generic User Property Set state change event */ +typedef struct { + uint16_t id; /*!< The property id of Generic User Property state */ + struct net_buf_simple *value; /*!< The property value of Generic User Property state */ +} esp_ble_mesh_state_change_gen_user_property_set_t; + +/** Parameters of Generic Admin Property Set state change event */ +typedef struct { + uint16_t id; /*!< The property id of Generic Admin Property state */ + uint8_t access; /*!< The property access of Generic Admin Property state */ + struct net_buf_simple *value; /*!< The property value of Generic Admin Property state */ +} esp_ble_mesh_state_change_gen_admin_property_set_t; + +/** Parameters of Generic Manufacturer Property Set state change event */ +typedef struct { + uint16_t id; /*!< The property id of Generic Manufacturer Property state */ + uint8_t access; /*!< The property value of Generic Manufacturer Property state */ +} esp_ble_mesh_state_change_gen_manu_property_set_t; + +/** + * @brief Generic Server Model state change value union + */ +typedef union { + /** + * The recv_op in ctx can be used to decide which state is changed. + */ + esp_ble_mesh_state_change_gen_onoff_set_t onoff_set; /*!< Generic OnOff Set */ + esp_ble_mesh_state_change_gen_level_set_t level_set; /*!< Generic Level Set */ + esp_ble_mesh_state_change_gen_delta_set_t delta_set; /*!< Generic Delta Set */ + esp_ble_mesh_state_change_gen_move_set_t move_set; /*!< Generic Move Set */ + esp_ble_mesh_state_change_gen_def_trans_time_set_t def_trans_time_set; /*!< Generic Default Transition Time Set */ + esp_ble_mesh_state_change_gen_onpowerup_set_t onpowerup_set; /*!< Generic OnPowerUp Set */ + esp_ble_mesh_state_change_gen_power_level_set_t power_level_set; /*!< Generic Power Level Set */ + esp_ble_mesh_state_change_gen_power_default_set_t power_default_set; /*!< Generic Power Default Set */ + esp_ble_mesh_state_change_gen_power_range_set_t power_range_set; /*!< Generic Power Range Set */ + esp_ble_mesh_state_change_gen_loc_global_set_t loc_global_set; /*!< Generic Location Global Set */ + esp_ble_mesh_state_change_gen_loc_local_set_t loc_local_set; /*!< Generic Location Local Set */ + esp_ble_mesh_state_change_gen_user_property_set_t user_property_set; /*!< Generic User Property Set */ + esp_ble_mesh_state_change_gen_admin_property_set_t admin_property_set; /*!< Generic Admin Property Set */ + esp_ble_mesh_state_change_gen_manu_property_set_t manu_property_set; /*!< Generic Manufactuer Property Set */ +} esp_ble_mesh_generic_server_state_change_t; + +/** Context of the received Generic User Property Get message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Generic User Property */ +} esp_ble_mesh_server_recv_gen_user_property_get_t; + +/** Context of the received Generic Admin Property Get message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Generic Admin Property */ +} esp_ble_mesh_server_recv_gen_admin_property_get_t; + +/** Context of the received Generic Manufacturer Property message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Generic Manufacturer Property */ +} esp_ble_mesh_server_recv_gen_manufacturer_property_get_t; + +/** Context of the received Generic Client Properties Get message */ +typedef struct { + uint16_t property_id; /*!< A starting Client Property ID present within an element */ +} esp_ble_mesh_server_recv_gen_client_properties_get_t; + +/** + * @brief Generic Server Model received get message union + */ +typedef union { + esp_ble_mesh_server_recv_gen_user_property_get_t user_property; /*!< Generic User Property Get */ + esp_ble_mesh_server_recv_gen_admin_property_get_t admin_property; /*!< Generic Admin Property Get */ + esp_ble_mesh_server_recv_gen_manufacturer_property_get_t manu_property; /*!< Generic Manufacturer Property Get */ + esp_ble_mesh_server_recv_gen_client_properties_get_t client_properties; /*!< Generic Client Properties Get */ +} esp_ble_mesh_generic_server_recv_get_msg_t; + +/** Context of the received Generic OnOff Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint8_t onoff; /*!< Target value of Generic OnOff state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_gen_onoff_set_t; + +/** Context of the received Generic Level Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + int16_t level; /*!< Target value of Generic Level state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_gen_level_set_t; + +/** Context of the received Generic Delta Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + int32_t delta_level; /*!< Delta change of Generic Level state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_gen_delta_set_t; + +/** Context of the received Generic Move Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + int16_t delta_level; /*!< Delta Level step to calculate Move speed for Generic Level state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_gen_move_set_t; + +/** Context of the received Generic Default Transition Time Set message */ +typedef struct { + uint8_t trans_time; /*!< The value of the Generic Default Transition Time state */ +} esp_ble_mesh_server_recv_gen_def_trans_time_set_t; + +/** Context of the received Generic OnPowerUp Set message */ +typedef struct { + uint8_t onpowerup; /*!< The value of the Generic OnPowerUp state */ +} esp_ble_mesh_server_recv_gen_onpowerup_set_t; + +/** Context of the received Generic Power Level Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t power; /*!< Target value of Generic Power Actual state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_gen_power_level_set_t; + +/** Context of the received Generic Power Default Set message */ +typedef struct { + uint16_t power; /*!< The value of the Generic Power Default state */ +} esp_ble_mesh_server_recv_gen_power_default_set_t; + +/** Context of the received Generic Power Range Set message */ +typedef struct { + uint16_t range_min; /*!< Value of Range Min field of Generic Power Range state */ + uint16_t range_max; /*!< Value of Range Max field of Generic Power Range state */ +} esp_ble_mesh_server_recv_gen_power_range_set_t; + +/** Context of the received Generic Location Global Set message */ +typedef struct { + int32_t global_latitude; /*!< Global Coordinates (Latitude) */ + int32_t global_longitude; /*!< Global Coordinates (Longitude) */ + int16_t global_altitude; /*!< Global Altitude */ +} esp_ble_mesh_server_recv_gen_loc_global_set_t; + +/** Context of the received Generic Location Local Set message */ +typedef struct { + int16_t local_north; /*!< Local Coordinates (North) */ + int16_t local_east; /*!< Local Coordinates (East) */ + int16_t local_altitude; /*!< Local Altitude */ + uint8_t floor_number; /*!< Floor Number */ + uint16_t uncertainty; /*!< Uncertainty */ +} esp_ble_mesh_server_recv_gen_loc_local_set_t; + +/** Context of the received Generic User Property Set message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Generic User Property */ + struct net_buf_simple *property_value; /*!< Raw value for the User Property */ +} esp_ble_mesh_server_recv_gen_user_property_set_t; + +/** Context of the received Generic Admin Property Set message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Generic Admin Property */ + uint8_t user_access; /*!< Enumeration indicating user accessn */ + struct net_buf_simple *property_value; /*!< Raw value for the Admin Property */ +} esp_ble_mesh_server_recv_gen_admin_property_set_t; + +/** Context of the received Generic Manufacturer Property Set message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Generic Manufacturer Property */ + uint8_t user_access; /*!< Enumeration indicating user access */ +} esp_ble_mesh_server_recv_gen_manufacturer_property_set_t; + +/** + * @brief Generic Server Model received set message union + */ +typedef union { + esp_ble_mesh_server_recv_gen_onoff_set_t onoff; /*!< Generic OnOff Set/Generic OnOff Set Unack */ + esp_ble_mesh_server_recv_gen_level_set_t level; /*!< Generic Level Set/Generic Level Set Unack */ + esp_ble_mesh_server_recv_gen_delta_set_t delta; /*!< Generic Delta Set/Generic Delta Set Unack */ + esp_ble_mesh_server_recv_gen_move_set_t move; /*!< Generic Move Set/Generic Move Set Unack */ + esp_ble_mesh_server_recv_gen_def_trans_time_set_t def_trans_time; /*!< Generic Default Transition Time Set/Generic Default Transition Time Set Unack */ + esp_ble_mesh_server_recv_gen_onpowerup_set_t onpowerup; /*!< Generic OnPowerUp Set/Generic OnPowerUp Set Unack */ + esp_ble_mesh_server_recv_gen_power_level_set_t power_level; /*!< Generic Power Level Set/Generic Power Level Set Unack */ + esp_ble_mesh_server_recv_gen_power_default_set_t power_default; /*!< Generic Power Default Set/Generic Power Default Set Unack */ + esp_ble_mesh_server_recv_gen_power_range_set_t power_range; /*!< Generic Power Range Set/Generic Power Range Set Unack */ + esp_ble_mesh_server_recv_gen_loc_global_set_t location_global; /*!< Generic Location Global Set/Generic Location Global Set Unack */ + esp_ble_mesh_server_recv_gen_loc_local_set_t location_local; /*!< Generic Location Local Set/Generic Location Local Set Unack */ + esp_ble_mesh_server_recv_gen_user_property_set_t user_property; /*!< Generic User Property Set/Generic User Property Set Unack */ + esp_ble_mesh_server_recv_gen_admin_property_set_t admin_property; /*!< Generic Admin Property Set/Generic Admin Property Set Unack */ + esp_ble_mesh_server_recv_gen_manufacturer_property_set_t manu_property; /*!< Generic Manufacturer Property Set/Generic Manufacturer Property Set Unack */ +} esp_ble_mesh_generic_server_recv_set_msg_t; + +/** + * @brief Generic Server Model callback value union + */ +typedef union { + esp_ble_mesh_generic_server_state_change_t state_change; /*!< ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT */ + esp_ble_mesh_generic_server_recv_get_msg_t get; /*!< ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT */ + esp_ble_mesh_generic_server_recv_set_msg_t set; /*!< ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT */ +} esp_ble_mesh_generic_server_cb_value_t; + +/** Generic Server Model callback parameters */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to Generic Server Models */ + esp_ble_mesh_msg_ctx_t ctx; /*!< Context of the received messages */ + esp_ble_mesh_generic_server_cb_value_t value; /*!< Value of the received Generic Messages */ +} esp_ble_mesh_generic_server_cb_param_t; + +/** This enum value is the event of Generic Server Model */ +typedef enum { + /** + * 1. When get_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, no event will be + * callback to the application layer when Generic Get messages are received. + * 2. When set_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, this event will + * be callback to the application layer when Generic Set/Set Unack messages + * are received. + */ + ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT, + /** + * When get_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Generic Get messages are received. + */ + ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT, + /** + * When set_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Generic Set/Set Unack messages are received. + */ + ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT, + ESP_BLE_MESH_GENERIC_SERVER_EVT_MAX, +} esp_ble_mesh_generic_server_cb_event_t; + +/** + * @brief Bluetooth Mesh Generic Server Model function. + */ + +/** + * @brief Generic Server Model callback function type + * @param event: Event type + * @param param: Pointer to callback parameter + */ +typedef void (* esp_ble_mesh_generic_server_cb_t)(esp_ble_mesh_generic_server_cb_event_t event, + esp_ble_mesh_generic_server_cb_param_t *param); + +/** + * @brief Register BLE Mesh Generic Server Model callback. + * + * @param[in] callback: Pointer to the callback function. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_register_generic_server_callback(esp_ble_mesh_generic_server_cb_t callback); #endif /* _ESP_BLE_MESH_GENERIC_MODEL_API_H_ */ diff --git a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_health_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_health_model_api.h index b35cb0e0b..f0836756e 100644 --- a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_health_model_api.h +++ b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_health_model_api.h @@ -47,39 +47,123 @@ ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_HEALTH_CLI, \ NULL, NULL, cli_data) -/** Health Server Model callbacks */ +/** @def ESP_BLE_MESH_HEALTH_PUB_DEFINE + * + * A helper to define a health publication context + * + * @param _name Name given to the publication context variable. + * @param _max Maximum number of faults the element can have. + * @param _role Role of the device which contains the model. + */ +#define ESP_BLE_MESH_HEALTH_PUB_DEFINE(_name, _max, _role) \ + ESP_BLE_MESH_MODEL_PUB_DEFINE(_name, (1 + 3 + (_max)), _role) + +/** + * SIG identifier of Health Fault Test. + * 0x01 ~ 0xFF: Vendor Specific Test. + */ +#define ESP_BLE_MESH_HEALTH_STANDARD_TEST 0x00 + +/** + * Fault values of Health Fault Test. + * 0x33 ~ 0x7F: Reserved for Future Use. + * 0x80 ~ 0xFF: Vendor Specific Warning/Error. + */ +#define ESP_BLE_MESH_NO_FAULT 0x00 +#define ESP_BLE_MESH_BATTERY_LOW_WARNING 0x01 +#define ESP_BLE_MESH_BATTERY_LOW_ERROR 0x02 +#define ESP_BLE_MESH_SUPPLY_VOLTAGE_TOO_LOW_WARNING 0x03 +#define ESP_BLE_MESH_SUPPLY_VOLTAGE_TOO_LOW_ERROR 0x04 +#define ESP_BLE_MESH_SUPPLY_VOLTAGE_TOO_HIGH_WARNING 0x05 +#define ESP_BLE_MESH_SUPPLY_VOLTAGE_TOO_HIGH_ERROR 0x06 +#define ESP_BLE_MESH_POWER_SUPPLY_INTERRUPTED_WARNING 0x07 +#define ESP_BLE_MESH_POWER_SUPPLY_INTERRUPTED_ERROR 0x08 +#define ESP_BLE_MESH_NO_LOAD_WARNING 0x09 +#define ESP_BLE_MESH_NO_LOAD_ERROR 0x0A +#define ESP_BLE_MESH_OVERLOAD_WARNING 0x0B +#define ESP_BLE_MESH_OVERLOAD_ERROR 0x0C +#define ESP_BLE_MESH_OVERHEAT_WARNING 0x0D +#define ESP_BLE_MESH_OVERHEAT_ERROR 0x0E +#define ESP_BLE_MESH_CONDENSATION_WARNING 0x0F +#define ESP_BLE_MESH_CONDENSATION_ERROR 0x10 +#define ESP_BLE_MESH_VIBRATION_WARNING 0x11 +#define ESP_BLE_MESH_VIBRATION_ERROR 0x12 +#define ESP_BLE_MESH_CONFIGURATION_WARNING 0x13 +#define ESP_BLE_MESH_CONFIGURATION_ERROR 0x14 +#define ESP_BLE_MESH_ELEMENT_NOT_CALIBRATED_WARNING 0x15 +#define ESP_BLE_MESH_ELEMENT_NOT_CALIBRATED_ERROR 0x16 +#define ESP_BLE_MESH_MEMORY_WARNING 0x17 +#define ESP_BLE_MESH_MEMORY_ERROR 0x18 +#define ESP_BLE_MESH_SELF_TEST_WARNING 0x19 +#define ESP_BLE_MESH_SELF_TEST_ERROR 0x1A +#define ESP_BLE_MESH_INPUT_TOO_LOW_WARNING 0x1B +#define ESP_BLE_MESH_INPUT_TOO_LOW_ERROR 0x1C +#define ESP_BLE_MESH_INPUT_TOO_HIGH_WARNING 0x1D +#define ESP_BLE_MESH_INPUT_TOO_HIGH_ERROR 0x1E +#define ESP_BLE_MESH_INPUT_NO_CHANGE_WARNING 0x1F +#define ESP_BLE_MESH_INPUT_NO_CHANGE_ERROR 0x20 +#define ESP_BLE_MESH_ACTUATOR_BLOCKED_WARNING 0x21 +#define ESP_BLE_MESH_ACTUATOR_BLOCKED_ERROR 0x22 +#define ESP_BLE_MESH_HOUSING_OPENED_WARNING 0x23 +#define ESP_BLE_MESH_HOUSING_OPENED_ERROR 0x24 +#define ESP_BLE_MESH_TAMPER_WARNING 0x25 +#define ESP_BLE_MESH_TAMPER_ERROR 0x26 +#define ESP_BLE_MESH_DEVICE_MOVED_WARNING 0x27 +#define ESP_BLE_MESH_DEVICE_MOVED_ERROR 0x28 +#define ESP_BLE_MESH_DEVICE_DROPPED_WARNING 0x29 +#define ESP_BLE_MESH_DEVICE_DROPPED_ERROR 0x2A +#define ESP_BLE_MESH_OVERFLOW_WARNING 0x2B +#define ESP_BLE_MESH_OVERFLOW_ERROR 0x2C +#define ESP_BLE_MESH_EMPTY_WARNING 0x2D +#define ESP_BLE_MESH_EMPTY_ERROR 0x2E +#define ESP_BLE_MESH_INTERNAL_BUS_WARNING 0x2F +#define ESP_BLE_MESH_INTERNAL_BUS_ERROR 0x30 +#define ESP_BLE_MESH_MECHANISM_JAMMED_WARNING 0x31 +#define ESP_BLE_MESH_MECHANISM_JAMMED_ERROR 0x32 + +/** ESP BLE Mesh Health Server callback */ typedef struct { - /** Fetch current faults */ - int (*fault_get_cur)(esp_ble_mesh_model_t *model, uint8_t *test_id, - uint16_t *company_id, uint8_t *faults, uint8_t *fault_count); + /** Clear health registered faults. Initialized by the stack. */ + esp_ble_mesh_cb_t fault_clear; - /** Fetch registered faults */ - int (*fault_get_reg)(esp_ble_mesh_model_t *model, uint16_t company_id, - uint8_t *test_id, uint8_t *faults, uint8_t *fault_count); + /** Run a specific health test. Initialized by the stack. */ + esp_ble_mesh_cb_t fault_test; - /** Clear registered faults */ - int (*fault_clear)(esp_ble_mesh_model_t *model, uint16_t company_id); + /** Health attention on callback. Initialized by the stack. */ + esp_ble_mesh_cb_t attention_on; - /** Run a specific test */ - int (*fault_test)(esp_ble_mesh_model_t *model, uint8_t test_id, uint16_t company_id); - - /** Attention on */ - void (*attn_on)(esp_ble_mesh_model_t *model); - - /** Attention off */ - void (*attn_off)(esp_ble_mesh_model_t *model); + /** Health attention off callback. Initialized by the stack. */ + esp_ble_mesh_cb_t attention_off; } esp_ble_mesh_health_srv_cb_t; -/** Health Server Model Context */ +#define ESP_BLE_MESH_HEALTH_FAULT_ARRAY_SIZE 32 + +/** ESP BLE Mesh Health Server test Context */ +typedef struct { + uint8_t id_count; /*!< Number of Health self-test ID */ + const uint8_t *test_ids; /*!< Array of Health self-test IDs */ + uint16_t company_id; /*!< Company ID used to identify the Health Fault state */ + uint8_t prev_test_id; /*!< Current test ID of the health fault test */ + uint8_t current_faults[ESP_BLE_MESH_HEALTH_FAULT_ARRAY_SIZE]; /*!< Array of current faults */ + uint8_t registered_faults[ESP_BLE_MESH_HEALTH_FAULT_ARRAY_SIZE]; /*!< Array of registered faults */ +} __attribute__((packed)) esp_ble_mesh_health_test_t; + +/** ESP BLE Mesh Health Server Model Context */ typedef struct { /** Pointer to Health Server Model */ esp_ble_mesh_model_t *model; - /** Optional callback struct */ - const esp_ble_mesh_health_srv_cb_t *cb; + /** Health callback struct */ + esp_ble_mesh_health_srv_cb_t health_cb; /** Attention Timer state */ - struct k_delayed_work attn_timer; + struct k_delayed_work attention_timer; + + /** Attention Timer start flag */ + bool attention_timer_start; + + /** Health Server fault test */ + esp_ble_mesh_health_test_t health_test; } esp_ble_mesh_health_srv_t; /** Parameter of Health Fault Get */ @@ -186,14 +270,54 @@ typedef enum { ESP_BLE_MESH_HEALTH_CLIENT_EVT_MAX, } esp_ble_mesh_health_client_cb_event_t; -/** Health Server Model callback parameter */ +/** Parameter of publishing Health Current Status completion event */ typedef struct { - int error_code; /*!< Appropriate error code */ + int error_code; /*!< The result of publishing Health Current Status */ + esp_ble_mesh_elem_t *element; /*!< Pointer to the element which contains the Health Server Model */ +} esp_ble_mesh_health_fault_update_comp_cb_t; + +/** Parameters of Health Fault Clear event */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Health Server Model */ + uint16_t company_id; /*!< Bluetooth assigned 16-bit Company ID */ +} esp_ble_mesh_health_fault_clear_cb_t; + +/** Parameters of Health Fault Test event */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Health Server Model */ + uint8_t test_id; /*!< ID of a specific test to be performed */ + uint16_t company_id; /*!< Bluetooth assigned 16-bit Company ID */ +} esp_ble_mesh_health_fault_test_cb_t; + +/** Parameter of Health Attention On event */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Health Server Model */ + uint8_t time; /*!< Duration of attention timer on (in seconds) */ +} esp_ble_mesh_health_attention_on_cb_t; + +/** Parameter of Health Attention Off event */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Health Server Model */ +} esp_ble_mesh_health_attention_off_cb_t; + +/** + * @brief Health Server Model callback parameters union + */ +typedef union { + esp_ble_mesh_health_fault_update_comp_cb_t fault_update_comp; /*!< ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMP_EVT */ + esp_ble_mesh_health_fault_clear_cb_t fault_clear; /*!< ESP_BLE_MESH_HEALTH_SERVER_FAULT_CLEAR_EVT */ + esp_ble_mesh_health_fault_test_cb_t fault_test; /*!< ESP_BLE_MESH_HEALTH_SERVER_FAULT_TEST_EVT */ + esp_ble_mesh_health_attention_on_cb_t attention_on; /*!< ESP_BLE_MESH_HEALTH_SERVER_ATTENTION_ON_EVT */ + esp_ble_mesh_health_attention_off_cb_t attention_off; /*!< ESP_BLE_MESH_HEALTH_SERVER_ATTENTION_OFF_EVT */ } esp_ble_mesh_health_server_cb_param_t; /** This enum value is the event of Health Server Model */ typedef enum { - ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMPLETE_EVT, + ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMP_EVT, + ESP_BLE_MESH_HEALTH_SERVER_FAULT_CLEAR_EVT, + ESP_BLE_MESH_HEALTH_SERVER_FAULT_TEST_EVT, + ESP_BLE_MESH_HEALTH_SERVER_ATTENTION_ON_EVT, + ESP_BLE_MESH_HEALTH_SERVER_ATTENTION_OFF_EVT, ESP_BLE_MESH_HEALTH_SERVER_EVT_MAX, } esp_ble_mesh_health_server_cb_event_t; @@ -270,7 +394,7 @@ esp_err_t esp_ble_mesh_health_client_set_state(esp_ble_mesh_client_common_param_ esp_ble_mesh_health_client_set_state_t *set_state); /** - * @brief This function is called by the Health Server Model to start to publish its Current Health Fault. + * @brief This function is called by the Health Server Model to update the context of its Health Current status. * * @param[in] element: The element to which the Health Server Model belongs. * diff --git a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h index f0291a350..ff08cfcc0 100644 --- a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h +++ b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h @@ -579,6 +579,1097 @@ esp_err_t esp_ble_mesh_light_client_get_state(esp_ble_mesh_client_common_param_t esp_err_t esp_ble_mesh_light_client_set_state(esp_ble_mesh_client_common_param_t *params, esp_ble_mesh_light_client_set_state_t *set_state); +/** + * @brief Lighting Server Models related context. + */ + +/** @def ESP_BLE_MESH_MODEL_LIGHT_LIGHTNESS_SRV + * + * @brief Define a new Light Lightness Server Model. + * + * @note 1. The Light Lightness Server model extends the Generic Power OnOff + * Server model and the Generic Level Server model. When this model + * is present on an Element, the corresponding Light Lightness Setup + * Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_lightness_srv_t. + * + * @return New Light Lightness Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_LIGHTNESS_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_LIGHTNESS_SETUP_SRV + * + * @brief Define a new Light Lightness Setup Server Model. + * + * @note 1. The Light Lightness Setup Server model extends the Light Lightness + * Server model and the Generic Power OnOff Setup Server model. + * 2. This model shall support model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_lightness_setup_srv_t. + * + * @return New Light Lightness Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_LIGHTNESS_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_CTL_SRV + * + * @brief Define a new Light CTL Server Model. + * + * @note 1. The Light CTL Server model extends the Light Lightness Server model. + * When this model is present on an Element, the corresponding Light + * CTL Temperature Server model and the corresponding Light CTL Setup + * Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * 3. The model requires two elements: the main element and the Temperature + * element. The Temperature element contains the corresponding Light CTL + * Temperature Server model and an instance of a Generic Level state + * bound to the Light CTL Temperature state on the Temperature element. + * The Light CTL Temperature state on the Temperature element is bound to + * the Light CTL state on the main element. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_ctl_srv_t. + * + * @return New Light CTL Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_CTL_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_CTL_SETUP_SRV + * + * @brief Define a new Light CTL Setup Server Model. + * + * @note 1. The Light CTL Setup Server model extends the Light CTL Server and + * the Light Lightness Setup Server. + * 2. This model shall support model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_ctl_setup_srv_t. + * + * @return New Light CTL Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_CTL_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_CTL_TEMP_SRV + * + * @brief Define a new Light CTL Temperature Server Model. + * + * @note 1. The Light CTL Temperature Server model extends the Generic Level + * Server model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_ctl_temp_srv_t. + * + * @return New Light CTL Temperature Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_CTL_TEMP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_HSL_SRV + * + * @brief Define a new Light HSL Server Model. + * + * @note 1. The Light HSL Server model extends the Light Lightness Server model. When + * this model is present on an Element, the corresponding Light HSL Hue + * Server model and the corresponding Light HSL Saturation Server model and + * the corresponding Light HSL Setup Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * 3. The model requires three elements: the main element and the Hue element + * and the Saturation element. The Hue element contains the corresponding + * Light HSL Hue Server model and an instance of a Generic Level state bound + * to the Light HSL Hue state on the Hue element. The Saturation element + * contains the corresponding Light HSL Saturation Server model and an + * instance of a Generic Level state bound to the Light HSL Saturation state + * on the Saturation element. The Light HSL Hue state on the Hue element is + * bound to the Light HSL state on the main element and the Light HSL + * Saturation state on the Saturation element is bound to the Light HSL state + * on the main element. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_hsl_srv_t. + * + * @return New Light HSL Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_HSL_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_HSL_SETUP_SRV + * + * @brief Define a new Light HSL Setup Server Model. + * + * @note 1. The Light HSL Setup Server model extends the Light HSL Server and + * the Light Lightness Setup Server. + * 2. This model shall support model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_hsl_setup_srv_t. + * + * @return New Light HSL Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_HSL_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_HSL_HUE_SRV + * + * @brief Define a new Light HSL Hue Server Model. + * + * @note 1. The Light HSL Hue Server model extends the Generic Level Server model. + * This model is associated with the Light HSL Server model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_hsl_hue_srv_t. + * + * @return New Light HSL Hue Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_HSL_HUE_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_HSL_SAT_SRV + * + * @brief Define a new Light HSL Saturation Server Model. + * + * @note 1. The Light HSL Saturation Server model extends the Generic Level Server + * model. This model is associated with the Light HSL Server model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_hsl_sat_srv_t. + * + * @return New Light HSL Saturation Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_HSL_SAT_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_XYL_SRV + * + * @brief Define a new Light xyL Server Model. + * + * @note 1. The Light xyL Server model extends the Light Lightness Server model. + * When this model is present on an Element, the corresponding Light xyL + * Setup Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_xyl_srv_t. + * + * @return New Light xyL Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_XYL_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_XYL_SETUP_SRV + * + * @brief Define a new Light xyL Setup Server Model. + * + * @note 1. The Light xyL Setup Server model extends the Light xyL Server and + * the Light Lightness Setup Server. + * 2. This model shall support model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_xyl_setup_srv_t. + * + * @return New Light xyL Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_XYL_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_LC_SRV + * + * @brief Define a new Light LC Server Model. + * + * @note 1. The Light LC (Lightness Control) Server model extends the Light + * Lightness Server model and the Generic OnOff Server model. When + * this model is present on an Element, the corresponding Light LC + * Setup Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * 3. This model may be used to represent an element that is a client to + * a Sensor Server model and controls the Light Lightness Actual state + * via defined state bindings. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_lc_srv_t. + * + * @return New Light LC Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_LC_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_LIGHT_LC_SETUP_SRV + * + * @brief Define a new Light LC Setup Server Model. + * + * @note 1. The Light LC (Lightness Control) Setup model extends the Light LC + * Server model. + * 2. This model shall support model publication and model subscription. + * 3. This model may be used to configure setup parameters for the Light + * LC Server model. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_light_lc_setup_srv_t. + * + * @return New Light LC Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_LIGHT_LC_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** Parameters of Light Lightness state */ +typedef struct { + uint16_t lightness_linear; /*!< The present value of Light Lightness Linear state */ + uint16_t target_lightness_linear; /*!< The target value of Light Lightness Linear state */ + + uint16_t lightness_actual; /*!< The present value of Light Lightness Actual state */ + uint16_t target_lightness_actual; /*!< The target value of Light Lightness Actual state */ + + uint16_t lightness_last; /*!< The value of Light Lightness Last state */ + uint16_t lightness_default; /*!< The value of Light Lightness Default state */ + + uint8_t status_code; /*!< The status code of setting Light Lightness Range state */ + uint16_t lightness_range_min; /*!< The minimum value of Light Lightness Range state */ + uint16_t lightness_range_max; /*!< The maximum value of Light Lightness Range state */ +} esp_ble_mesh_light_lightness_state_t; + +/** User data of Light Lightness Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting Lightness Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_lightness_state_t *state; /*!< Parameters of the Light Lightness state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t actual_transition; /*!< Parameters of state transition */ + esp_ble_mesh_state_transition_t linear_transition; /*!< Parameters of state transition */ + int32_t tt_delta_lightness_actual; /*!< Delta change value of lightness actual state transition */ + int32_t tt_delta_lightness_linear; /*!< Delta change value of lightness linear state transition */ +} esp_ble_mesh_light_lightness_srv_t; + +/** User data of Light Lightness Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting Lightness Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_lightness_state_t *state; /*!< Parameters of the Light Lightness state */ +} esp_ble_mesh_light_lightness_setup_srv_t; + +/** Parameters of Light CTL state */ +typedef struct { + uint16_t lightness; /*!< The present value of Light CTL Lightness state */ + uint16_t target_lightness; /*!< The target value of Light CTL Lightness state */ + + uint16_t temperature; /*!< The present value of Light CTL Temperature state */ + uint16_t target_temperature; /*!< The target value of Light CTL Temperature state */ + + int16_t delta_uv; /*!< The present value of Light CTL Delta UV state */ + int16_t target_delta_uv; /*!< The target value of Light CTL Delta UV state */ + + uint8_t status_code; /*!< The statue code of setting Light CTL Temperature Range state */ + uint16_t temperature_range_min; /*!< The minimum value of Light CTL Temperature Range state */ + uint16_t temperature_range_max; /*!< The maximum value of Light CTL Temperature Range state */ + + uint16_t lightness_default; /*!< The value of Light Lightness Default state */ + uint16_t temperature_default; /*!< The value of Light CTL Temperature Default state */ + int16_t delta_uv_default; /*!< The value of Light CTL Delta UV Default state */ +} esp_ble_mesh_light_ctl_state_t; + +/** User data of Light CTL Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting CTL Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_ctl_state_t *state; /*!< Parameters of the Light CTL state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_lightness; /*!< Delta change value of lightness state transition */ + int32_t tt_delta_temperature; /*!< Delta change value of temperature state transition */ + int32_t tt_delta_delta_uv; /*!< Delta change value of delta uv state transition */ +} esp_ble_mesh_light_ctl_srv_t; + +/** User data of Light CTL Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting CTL Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_ctl_state_t *state; /*!< Parameters of the Light CTL state */ +} esp_ble_mesh_light_ctl_setup_srv_t; + +/** User data of Light CTL Temperature Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting CTL Temperature Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_ctl_state_t *state; /*!< Parameters of the Light CTL state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_temperature; /*!< Delta change value of temperature state transition */ + int32_t tt_delta_delta_uv; /*!< Delta change value of delta uv state transition */ +} esp_ble_mesh_light_ctl_temp_srv_t; + +/** Parameters of Light HSL state */ +typedef struct { + uint16_t lightness; /*!< The present value of Light HSL Lightness state */ + uint16_t target_lightness; /*!< The target value of Light HSL Lightness state */ + + uint16_t hue; /*!< The present value of Light HSL Hue state */ + uint16_t target_hue; /*!< The target value of Light HSL Hue state */ + + uint16_t saturation; /*!< The present value of Light HSL Saturation state */ + uint16_t target_saturation; /*!< The target value of Light HSL Saturation state */ + + uint16_t lightness_default; /*!< The value of Light Lightness Default state */ + uint16_t hue_default; /*!< The value of Light HSL Hue Default state */ + uint16_t saturation_default; /*!< The value of Light HSL Saturation Default state */ + + uint8_t status_code; /*!< The status code of setting Light HSL Hue & Saturation Range state */ + uint16_t hue_range_min; /*!< The minimum value of Light HSL Hue Range state */ + uint16_t hue_range_max; /*!< The maximum value of Light HSL Hue Range state */ + uint16_t saturation_range_min; /*!< The minimum value of Light HSL Saturation state */ + uint16_t saturation_range_max; /*!< The maximum value of Light HSL Saturation state */ +} esp_ble_mesh_light_hsl_state_t; + +/** User data of Light HSL Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting HSL Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_hsl_state_t *state; /*!< Parameters of the Light HSL state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_lightness; /*!< Delta change value of lightness state transition */ + int32_t tt_delta_hue; /*!< Delta change value of hue state transition */ + int32_t tt_delta_saturation; /*!< Delta change value of saturation state transition */ +} esp_ble_mesh_light_hsl_srv_t; + +/** User data of Light HSL Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting HSL Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_hsl_state_t *state; /*!< Parameters of the Light HSL state */ +} esp_ble_mesh_light_hsl_setup_srv_t; + +/** User data of Light HSL Hue Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting HSL Hue Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_hsl_state_t *state; /*!< Parameters of the Light HSL state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_hue; /*!< Delta change value of hue state transition */ +} esp_ble_mesh_light_hsl_hue_srv_t; + +/** User data of Light HSL Saturation Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting HSL Saturation Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_hsl_state_t *state; /*!< Parameters of the Light HSL state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_saturation; /*!< Delta change value of saturation state transition */ +} esp_ble_mesh_light_hsl_sat_srv_t; + +/** Parameters of Light xyL state */ +typedef struct { + uint16_t lightness; /*!< The present value of Light xyL Lightness state */ + uint16_t target_lightness; /*!< The target value of Light xyL Lightness state */ + + uint16_t x; /*!< The present value of Light xyL x state */ + uint16_t target_x; /*!< The target value of Light xyL x state */ + + uint16_t y; /*!< The present value of Light xyL y state */ + uint16_t target_y; /*!< The target value of Light xyL y state */ + + uint16_t lightness_default; /*!< The value of Light Lightness Default state */ + uint16_t x_default; /*!< The value of Light xyL x Default state */ + uint16_t y_default; /*!< The value of Light xyL y Default state */ + + uint8_t status_code; /*!< The status code of setting Light xyL x & y Range state */ + uint16_t x_range_min; /*!< The minimum value of Light xyL x Range state */ + uint16_t x_range_max; /*!< The maximum value of Light xyL x Range state */ + uint16_t y_range_min; /*!< The minimum value of Light xyL y Range state */ + uint16_t y_range_max; /*!< The maximum value of Light xyL y Range state */ +} esp_ble_mesh_light_xyl_state_t; + +/** User data of Light xyL Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting xyL Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_xyl_state_t *state; /*!< Parameters of the Light xyL state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ + int32_t tt_delta_lightness; /*!< Delta change value of lightness state transition */ + int32_t tt_delta_x; /*!< Delta change value of x state transition */ + int32_t tt_delta_y; /*!< Delta change value of y state transition */ +} esp_ble_mesh_light_xyl_srv_t; + +/** User data of Light xyL Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting xyL Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_xyl_state_t *state; /*!< Parameters of the Light xyL state */ +} esp_ble_mesh_light_xyl_setup_srv_t; + +/** Parameters of Light LC states */ +typedef struct { + /** + * 0b0 The controller is turned off. + * - The binding with the Light Lightness state is disabled. + * 0b1 The controller is turned on. + * - The binding with the Light Lightness state is enabled. + */ + uint32_t mode : 1, /*!< The value of Light LC Mode state */ + occupancy_mode : 1, /*!< The value of Light LC Occupancy Mode state */ + light_onoff : 1, /*!< The present value of Light LC Light OnOff state */ + target_light_onoff : 1, /*!< The target value of Light LC Light OnOff state */ + occupancy : 1, /*!< The value of Light LC Occupancy state */ + ambient_luxlevel : 24; /*!< The value of Light LC Ambient LuxLevel state */ + + /** + * 1. Light LC Linear Output = max((Lightness Out)^2/65535, Regulator Output) + * 2. If the Light LC Mode state is set to 0b1, the binding is enabled and upon + * a change of the Light LC Linear Output state, the following operation + * shall be performed: + * Light Lightness Linear = Light LC Linear Output + * 3. If the Light LC Mode state is set to 0b0, the binding is disabled (i.e., + * upon a change of the Light LC Linear Output state, no operation on the + * Light Lightness Linear state is performed). + */ + uint16_t linear_output; /*!< The value of Light LC Linear Output state */ +} esp_ble_mesh_light_lc_state_t; + +/** + * Parameters of Light Property states. + * The Light LC Property states are read / write states that determine the + * configuration of a Light Lightness Controller. Each state is represented + * by a device property and is controlled by Light LC Property messages. + */ +typedef struct { + /** + * A timing state that determines the delay for changing the Light LC + * Occupancy state upon receiving a Sensor Status message from an + * occupancy sensor. + */ + uint32_t time_occupancy_delay; /*!< The value of Light LC Time Occupany Delay state */ + /** + * A timing state that determines the time the controlled lights fade + * to the level determined by the Light LC Lightness On state. + */ + uint32_t time_fade_on; /*!< The value of Light LC Time Fade On state */ + /** + * A timing state that determines the time the controlled lights stay + * at the level determined by the Light LC Lightness On state. + */ + uint32_t time_run_on; /*!< The value of Light LC Time Run On state */ + /** + * A timing state that determines the time the controlled lights fade + * from the level determined by the Light LC Lightness On state to the + * level determined by the Light Lightness Prolong state. + */ + uint32_t time_fade; /*!< The value of Light LC Time Fade state */ + /** + * A timing state that determines the time the controlled lights stay at + * the level determined by the Light LC Lightness Prolong state. + */ + uint32_t time_prolong; /*!< The value of Light LC Time Prolong state */ + /** + * A timing state that determines the time the controlled lights fade from + * the level determined by the Light LC Lightness Prolong state to the level + * determined by the Light LC Lightness Standby state when the transition is + * automatic. + */ + uint32_t time_fade_standby_auto; /*!< The value of Light LC Time Fade Standby Auto state */ + /** + * A timing state that determines the time the controlled lights fade from + * the level determined by the Light LC Lightness Prolong state to the level + * determined by the Light LC Lightness Standby state when the transition is + * triggered by a change in the Light LC Light OnOff state. + */ + uint32_t time_fade_standby_manual; /*!< The value of Light LC Time Fade Standby Manual state */ + + /** + * A lightness state that determines the perceptive light lightness at the + * Occupancy and Run internal controller states. + */ + uint16_t lightness_on; /*!< The value of Light LC Lightness On state */ + /** + * A lightness state that determines the light lightness at the Prolong + * internal controller state. + */ + uint16_t lightness_prolong; /*!< The value of Light LC Lightness Prolong state */ + /** + * A lightness state that determines the light lightness at the Standby + * internal controller state. + */ + uint16_t lightness_standby; /*!< The value of Light LC Lightness Standby state */ + + /** + * A uint16 state representing the Ambient LuxLevel level that determines + * if the controller transitions from the Light Control Standby state. + */ + uint16_t ambient_luxlevel_on; /*!< The value of Light LC Ambient LuxLevel On state */ + /** + * A uint16 state representing the required Ambient LuxLevel level in the + * Prolong state. + */ + uint16_t ambient_luxlevel_prolong; /*!< The value of Light LC Ambient LuxLevel Prolong state */ + /** + * A uint16 state representing the required Ambient LuxLevel level in the + * Standby state. + */ + uint16_t ambient_luxlevel_standby; /*!< The value of Light LC Ambient LuxLevel Standby state */ + + /** + * A float32 state representing the integral coefficient that determines the + * integral part of the equation defining the output of the Light LC PI + * Feedback Regulator, when Light LC Ambient LuxLevel is less than LuxLevel + * Out. Valid range: 0.0 ~ 1000.0. The default value is 250.0. + */ + float regulator_kiu; /*!< The value of Light LC Regulator Kiu state */ + /** + * A float32 state representing the integral coefficient that determines the + * integral part of the equation defining the output of the Light LC PI + * Feedback Regulator, when Light LC Ambient LuxLevel is greater than or equal + * to the value of the LuxLevel Out state. Valid range: 0.0 ~ 1000.0. The + * default value is 25.0. + */ + float regulator_kid; /*!< The value of Light LC Regulator Kid state */ + /** + * A float32 state representing the proportional coefficient that determines + * the proportional part of the equation defining the output of the Light LC + * PI Feedback Regulator, when Light LC Ambient LuxLevel is less than the value + * of the LuxLevel Out state. Valid range: 0.0 ~ 1000.0. The default value is 80.0. + */ + float regulator_kpu; /*!< The value of Light LC Regulator Kpu state */ + /** + * A float32 state representing the proportional coefficient that determines + * the proportional part of the equation defining the output of the Light LC PI + * Feedback Regulator, when Light LC Ambient LuxLevel is greater than or equal + * to the value of the LuxLevel Out state. Valid range: 0.0 ~ 1000.0. The default + * value is 80.0. + */ + float regulator_kpd; /*!< The value of Light LC Regulator Kpd state */ + /** + * A int8 state representing the percentage accuracy of the Light LC PI Feedback + * Regulator. Valid range: 0.0 ~ 100.0. The default value is 2.0. + */ + int8_t regulator_accuracy; /*!< The value of Light LC Regulator Accuracy state */ + + /** + * If the message Raw field contains a Raw Value for the Time Since Motion + * Sensed device property, which represents a value less than or equal to + * the value of the Light LC Occupancy Delay state, it shall delay setting + * the Light LC Occupancy state to 0b1 by the difference between the value + * of the Light LC Occupancy Delay state and the received Time Since Motion + * value. + */ + uint32_t set_occupancy_to_1_delay; /*!< The value of the difference between value of the + Light LC Occupancy Delay state and the received + Time Since Motion value */ +} esp_ble_mesh_light_lc_property_state_t; + +/** This enum value is the Light LC State Machine states */ +typedef enum { + ESP_BLE_MESH_LC_OFF, + ESP_BLE_MESH_LC_STANDBY, + ESP_BLE_MESH_LC_FADE_ON, + ESP_BLE_MESH_LC_RUN, + ESP_BLE_MESH_LC_FADE, + ESP_BLE_MESH_LC_PROLONG, + ESP_BLE_MESH_LC_FADE_STANDBY_AUTO, + ESP_BLE_MESH_LC_FADE_STANDBY_MANUAL, +} esp_ble_mesh_lc_state_t; + +/** Parameters of Light LC state machine */ +typedef struct { + /** + * The Fade On, Fade, Fade Standby Auto, and Fade Standby Manual states are + * transition states that define the transition of the Lightness Out and + * LuxLevel Out states. This transition can be started as a result of the + * Light LC State Machine change or as a result of receiving the Light LC + * Light OnOff Set or Light LC Light Set Unacknowledged message. + */ + struct { + uint8_t fade_on; /*!< The value of transition time of Light LC Time Fade On */ + uint8_t fade; /*!< The value of transition time of Light LC Time Fade */ + uint8_t fade_standby_auto; /*!< The value of transition time of Light LC Time Fade Standby Auto */ + uint8_t fade_standby_manual; /*!< The value of transition time of Light LC Time Fade Standby Manual */ + } trans_time; /*!< The value of transition time */ + esp_ble_mesh_lc_state_t state; /*!< The value of Light LC state machine state */ + struct k_delayed_work timer; /*!< Timer of Light LC state machine */ +} esp_ble_mesh_light_lc_state_machine_t; + +/** Parameters of Light Lightness controller */ +typedef struct { + esp_ble_mesh_light_lc_state_t state; /*!< Parameters of Light LC state */ + esp_ble_mesh_light_lc_property_state_t prop_state; /*!< Parameters of Light LC Property state */ + esp_ble_mesh_light_lc_state_machine_t state_machine; /*!< Parameters of Light LC state machine */ +} esp_ble_mesh_light_control_t; + +/** User data of Light LC Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting LC Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_control_t *lc; /*!< Parameters of the Light controller */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ +} esp_ble_mesh_light_lc_srv_t; + +/** User data of Light LC Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Lighting LC Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_light_control_t *lc; /*!< Parameters of the Light controller */ +} esp_ble_mesh_light_lc_setup_srv_t; + +/** Parameter of Light Lightness Actual state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light Lightness Actual state */ +} esp_ble_mesh_state_change_light_lightness_set_t; + +/** Parameter of Light Lightness Linear state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light Lightness Linear state */ +} esp_ble_mesh_state_change_light_lightness_linear_set_t; + +/** Parameter of Light Lightness Default state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light Lightness Default state */ +} esp_ble_mesh_state_change_light_lightness_default_set_t; + +/** Parameters of Light Lightness Range state change event */ +typedef struct { + uint16_t range_min; /*!< The minimum value of Light Lightness Range state */ + uint16_t range_max; /*!< The maximum value of Light Lightness Range state */ +} esp_ble_mesh_state_change_light_lightness_range_set_t; + +/** Parameters of Light CTL state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light CTL Lightness state */ + uint16_t temperature; /*!< The value of Light CTL Temperature state */ + int16_t delta_uv; /*!< The value of Light CTL Delta UV state */ +} esp_ble_mesh_state_change_light_ctl_set_t; + +/** Parameters of Light CTL Temperature state change event */ +typedef struct { + uint16_t temperature; /*!< The value of Light CTL Temperature state */ + int16_t delta_uv; /*!< The value of Light CTL Delta UV state */ +} esp_ble_mesh_state_change_light_ctl_temperature_set_t; + +/** Parameters of Light CTL Temperature Range state change event */ +typedef struct { + uint16_t range_min; /*!< The minimum value of Light CTL Temperature Range state */ + uint16_t range_max; /*!< The maximum value of Light CTL Temperature Range state */ +} esp_ble_mesh_state_change_light_ctl_temperature_range_set_t; + +/** Parameters of Light CTL Default state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light Lightness Default state */ + uint16_t temperature; /*!< The value of Light CTL Temperature Default state */ + int16_t delta_uv; /*!< The value of Light CTL Delta UV Default state */ +} esp_ble_mesh_state_change_light_ctl_default_set_t; + +/** Parameters of Light HSL state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light HSL Lightness state */ + uint16_t hue; /*!< The value of Light HSL Hue state */ + uint16_t saturation; /*!< The value of Light HSL Saturation state */ +} esp_ble_mesh_state_change_light_hsl_set_t; + +/** Parameter of Light HSL Hue state change event */ +typedef struct { + uint16_t hue; /*!< The value of Light HSL Hue state */ +} esp_ble_mesh_state_change_light_hsl_hue_set_t; + +/** Parameter of Light HSL Saturation state change event */ +typedef struct { + uint16_t saturation; /*!< The value of Light HSL Saturation state */ +} esp_ble_mesh_state_change_light_hsl_saturation_set_t; + +/** Parameters of Light HSL Default state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light HSL Lightness Default state */ + uint16_t hue; /*!< The value of Light HSL Hue Default state */ + uint16_t saturation; /*!< The value of Light HSL Saturation Default state */ +} esp_ble_mesh_state_change_light_hsl_default_set_t; + +/** Parameters of Light HSL Range state change event */ +typedef struct { + uint16_t hue_range_min; /*!< The minimum hue value of Light HSL Range state */ + uint16_t hue_range_max; /*!< The maximum hue value of Light HSL Range state */ + uint16_t saturation_range_min; /*!< The minimum saturation value of Light HSL Range state */ + uint16_t saturation_range_max; /*!< The maximum saturation value of Light HSL Range state */ +} esp_ble_mesh_state_change_light_hsl_range_set_t; + +/** Parameters of Light xyL state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light xyL Lightness state */ + uint16_t x; /*!< The value of Light xyL x state */ + uint16_t y; /*!< The value of Light xyL y state */ +} esp_ble_mesh_state_change_light_xyl_set_t; + +/** Parameters of Light xyL Default state change event */ +typedef struct { + uint16_t lightness; /*!< The value of Light Lightness Default state */ + uint16_t x; /*!< The value of Light xyL x Default state */ + uint16_t y; /*!< The value of Light xyL y Default state */ +} esp_ble_mesh_state_change_light_xyl_default_set_t; + +/** Parameters of Light xyL Range state change event */ +typedef struct { + uint16_t x_range_min; /*!< The minimum value of Light xyL x Range state */ + uint16_t x_range_max; /*!< The maximum value of Light xyL x Range state */ + uint16_t y_range_min; /*!< The minimum value of Light xyL y Range state */ + uint16_t y_range_max; /*!< The maximum value of Light xyL y Range state */ +} esp_ble_mesh_state_change_light_xyl_range_set_t; + +/** Parameter of Light LC Mode state change event */ +typedef struct { + uint8_t mode; /*!< The value of Light LC Mode state */ +} esp_ble_mesh_state_change_light_lc_mode_set_t; + +/** Parameter of Light LC Occupancy Mode state change event */ +typedef struct { + uint8_t mode; /*!< The value of Light LC Occupany Mode state */ +} esp_ble_mesh_state_change_light_lc_om_set_t; + +/** Parameter of Light LC Light OnOff state change event */ +typedef struct { + uint8_t onoff; /*!< The value of Light LC Light OnOff state */ +} esp_ble_mesh_state_change_light_lc_light_onoff_set_t; + +/** Parameters of Light LC Property state change event */ +typedef struct { + uint16_t property_id; /*!< The property id of Light LC Property state */ + struct net_buf_simple *property_value; /*!< The property value of Light LC Property state */ +} esp_ble_mesh_state_change_light_lc_property_set_t; + +/** Parameters of Sensor Status state change event */ +typedef struct { + uint16_t property_id; /*!< The value of Sensor Property ID */ + /** Parameters of Sensor Status related state */ + union { + uint8_t occupancy; /*!< The value of Light LC Occupancy state */ + uint32_t set_occupancy_to_1_delay; /*!< The value of Light LC Set Occupancy to 1 Delay state */ + uint32_t ambient_luxlevel; /*!< The value of Light LC Ambient Luxlevel state */ + } state; +} esp_ble_mesh_state_change_sensor_status_t; + +/** + * @brief Lighting Server Model state change value union + */ +typedef union { + /** + * The recv_op in ctx can be used to decide which state is changed. + */ + esp_ble_mesh_state_change_light_lightness_set_t lightness_set; /*!< Light Lightness Set */ + esp_ble_mesh_state_change_light_lightness_linear_set_t lightness_linear_set; /*!< Light Lightness Linear Set */ + esp_ble_mesh_state_change_light_lightness_default_set_t lightness_default_set; /*!< Light Lightness Default Set */ + esp_ble_mesh_state_change_light_lightness_range_set_t lightness_range_set; /*!< Light Lightness Range Set */ + esp_ble_mesh_state_change_light_ctl_set_t ctl_set; /*!< Light CTL Set */ + esp_ble_mesh_state_change_light_ctl_temperature_set_t ctl_temp_set; /*!< Light CTL Temperature Set */ + esp_ble_mesh_state_change_light_ctl_temperature_range_set_t ctl_temp_range_set; /*!< Light CTL Temperature Range Set */ + esp_ble_mesh_state_change_light_ctl_default_set_t ctl_default_set; /*!< Light CTL Default Set */ + esp_ble_mesh_state_change_light_hsl_set_t hsl_set; /*!< Light HSL Set */ + esp_ble_mesh_state_change_light_hsl_hue_set_t hsl_hue_set; /*!< Light HSL Hue Set */ + esp_ble_mesh_state_change_light_hsl_saturation_set_t hsl_saturation_set; /*!< Light HSL Saturation Set */ + esp_ble_mesh_state_change_light_hsl_default_set_t hsl_default_set; /*!< Light HSL Default Set */ + esp_ble_mesh_state_change_light_hsl_range_set_t hsl_range_set; /*!< Light HSL Range Set */ + esp_ble_mesh_state_change_light_xyl_set_t xyl_set; /*!< Light xyL Set */ + esp_ble_mesh_state_change_light_xyl_default_set_t xyl_default_set; /*!< Light xyL Default Set */ + esp_ble_mesh_state_change_light_xyl_range_set_t xyl_range_set; /*!< Light xyL Range Set */ + esp_ble_mesh_state_change_light_lc_mode_set_t lc_mode_set; /*!< Light LC Mode Set */ + esp_ble_mesh_state_change_light_lc_om_set_t lc_om_set; /*!< Light LC Occupancy Mode Set */ + esp_ble_mesh_state_change_light_lc_light_onoff_set_t lc_light_onoff_set; /*!< Light LC Light OnOff Set */ + esp_ble_mesh_state_change_light_lc_property_set_t lc_property_set; /*!< Light LC Property Set */ + esp_ble_mesh_state_change_sensor_status_t sensor_status; /*!< Sensor Status */ +} esp_ble_mesh_lighting_server_state_change_t; + +/** Context of the received Light LC Property Get message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Light LC Property */ +} esp_ble_mesh_server_recv_light_lc_property_get_t; + +/** + * @brief Lighting Server Model received get message union + */ +typedef union { + esp_ble_mesh_server_recv_light_lc_property_get_t lc_property; /*!< Light LC Property Get */ +} esp_ble_mesh_lighting_server_recv_get_msg_t; + +/** Context of the received Light Lightness Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t lightness; /*!< Target value of light lightness actual state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_lightness_set_t; + +/** Context of the received Light Lightness Linear Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t lightness; /*!< Target value of light lightness linear state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_lightness_linear_set_t; + +/** Context of the received Light Lightness Default Set message */ +typedef struct { + uint16_t lightness; /*!< The value of the Light Lightness Default state */ +} esp_ble_mesh_server_recv_light_lightness_default_set_t; + +/** Context of the received Light Lightness Range Set message */ +typedef struct { + uint16_t range_min; /*!< Value of range min field of light lightness range state */ + uint16_t range_max; /*!< Value of range max field of light lightness range state */ +} esp_ble_mesh_server_recv_light_lightness_range_set_t; + +/** Context of the received Light CTL Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t lightness; /*!< Target value of light ctl lightness state */ + uint16_t temperature; /*!< Target value of light ctl temperature state */ + int16_t delta_uv; /*!< Target value of light ctl delta UV state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_ctl_set_t; + +/** Context of the received Light CTL Temperature Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t temperature; /*!< Target value of light ctl temperature state */ + int16_t delta_uv; /*!< Target value of light ctl delta UV state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_ctl_temperature_set_t; + +/** Context of the received Light CTL Temperature Range Set message */ +typedef struct { + uint16_t range_min; /*!< Value of temperature range min field of light ctl temperature range state */ + uint16_t range_max; /*!< Value of temperature range max field of light ctl temperature range state */ +} esp_ble_mesh_server_recv_light_ctl_temperature_range_set_t; + +/** Context of the received Light CTL Default Set message */ +typedef struct { + uint16_t lightness; /*!< Value of light lightness default state */ + uint16_t temperature; /*!< Value of light temperature default state */ + int16_t delta_uv; /*!< Value of light delta UV default state */ +} esp_ble_mesh_server_recv_light_ctl_default_set_t; + +/** Context of the received Light HSL Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t lightness; /*!< Target value of light hsl lightness state */ + uint16_t hue; /*!< Target value of light hsl hue state */ + uint16_t saturation; /*!< Target value of light hsl saturation state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_hsl_set_t; + +/** Context of the received Light HSL Hue Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t hue; /*!< Target value of light hsl hue state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_hsl_hue_set_t; + +/** Context of the received Light HSL Saturation Set message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t saturation; /*!< Target value of light hsl hue state */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_hsl_saturation_set_t; + +/** Context of the received Light HSL Default Set message */ +typedef struct { + uint16_t lightness; /*!< Value of light lightness default state */ + uint16_t hue; /*!< Value of light hue default state */ + uint16_t saturation; /*!< Value of light saturation default state */ +} esp_ble_mesh_server_recv_light_hsl_default_set_t; + +/** Context of the received Light HSL Range Set message */ +typedef struct { + uint16_t hue_range_min; /*!< Value of hue range min field of light hsl hue range state */ + uint16_t hue_range_max; /*!< Value of hue range max field of light hsl hue range state */ + uint16_t saturation_range_min; /*!< Value of saturation range min field of light hsl saturation range state */ + uint16_t saturation_range_max; /*!< Value of saturation range max field of light hsl saturation range state */ +} esp_ble_mesh_server_recv_light_hsl_range_set_t; + +/** Context of the received Light xyL Set message */ +typedef struct { + bool op_en; /*!< Indicate whether optional parameters included */ + uint16_t lightness; /*!< The target value of the Light xyL Lightness state */ + uint16_t x; /*!< The target value of the Light xyL x state */ + uint16_t y; /*!< The target value of the Light xyL y state */ + uint8_t tid; /*!< Transaction Identifier */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_xyl_set_t; + +/** Context of the received Light xyL Default Set message */ +typedef struct { + uint16_t lightness; /*!< The value of the Light Lightness Default state */ + uint16_t x; /*!< The value of the Light xyL x Default state */ + uint16_t y; /*!< The value of the Light xyL y Default state */ +} esp_ble_mesh_server_recv_light_xyl_default_set_t; + +/** Context of the received Light xyl Range Set message */ +typedef struct { + uint16_t x_range_min; /*!< The value of the xyL x Range Min field of the Light xyL x Range state */ + uint16_t x_range_max; /*!< The value of the xyL x Range Max field of the Light xyL x Range state */ + uint16_t y_range_min; /*!< The value of the xyL y Range Min field of the Light xyL y Range state */ + uint16_t y_range_max; /*!< The value of the xyL y Range Max field of the Light xyL y Range state */ +} esp_ble_mesh_server_recv_light_xyl_range_set_t; + +/** Context of the received Light LC Mode Set message */ +typedef struct { + uint8_t mode; /*!< The target value of the Light LC Mode state */ +} esp_ble_mesh_server_recv_light_lc_mode_set_t; + +/** Context of the received Light OM Set message */ +typedef struct { + uint8_t mode; /*!< The target value of the Light LC Occupancy Mode state */ +} esp_ble_mesh_server_recv_light_lc_om_set_t; + +/** Context of the received Light LC Light OnOff Set message */ +typedef struct { + bool op_en; /*!< Indicate whether optional parameters included */ + uint8_t light_onoff; /*!< The target value of the Light LC Light OnOff state */ + uint8_t tid; /*!< Transaction Identifier */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_light_lc_light_onoff_set_t; + +/** Context of the received Light LC Property Set message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a Light LC Property */ + struct net_buf_simple *property_value; /*!< Raw value for the Light LC Property */ +} esp_ble_mesh_server_recv_light_lc_property_set_t; + +/** + * @brief Lighting Server Model received set message union + */ +typedef union { + esp_ble_mesh_server_recv_light_lightness_set_t lightness; /*!< Light Lightness Set/Light Lightness Set Unack */ + esp_ble_mesh_server_recv_light_lightness_linear_set_t lightness_linear; /*!< Light Lightness Linear Set/Light Lightness Linear Set Unack */ + esp_ble_mesh_server_recv_light_lightness_default_set_t lightness_default; /*!< Light Lightness Default Set/Light Lightness Default Set Unack */ + esp_ble_mesh_server_recv_light_lightness_range_set_t lightness_range; /*!< Light Lightness Range Set/Light Lightness Range Set Unack */ + esp_ble_mesh_server_recv_light_ctl_set_t ctl; /*!< Light CTL Set/Light CTL Set Unack */ + esp_ble_mesh_server_recv_light_ctl_temperature_set_t ctl_temp; /*!< Light CTL Temperature Set/Light CTL Temperature Set Unack */ + esp_ble_mesh_server_recv_light_ctl_temperature_range_set_t ctl_temp_range; /*!< Light CTL Temperature Range Set/Light CTL Temperature Range Set Unack */ + esp_ble_mesh_server_recv_light_ctl_default_set_t ctl_default; /*!< Light CTL Default Set/Light CTL Default Set Unack */ + esp_ble_mesh_server_recv_light_hsl_set_t hsl; /*!< Light HSL Set/Light HSL Set Unack */ + esp_ble_mesh_server_recv_light_hsl_hue_set_t hsl_hue; /*!< Light HSL Hue Set/Light HSL Hue Set Unack */ + esp_ble_mesh_server_recv_light_hsl_saturation_set_t hsl_saturation; /*!< Light HSL Saturation Set/Light HSL Saturation Set Unack */ + esp_ble_mesh_server_recv_light_hsl_default_set_t hsl_default; /*!< Light HSL Default Set/Light HSL Default Set Unack */ + esp_ble_mesh_server_recv_light_hsl_range_set_t hsl_range; /*!< Light HSL Range Set/Light HSL Range Set Unack */ + esp_ble_mesh_server_recv_light_xyl_set_t xyl; /*!< Light xyL Set/Light xyL Set Unack */ + esp_ble_mesh_server_recv_light_xyl_default_set_t xyl_default; /*!< Light xyL Default Set/Light xyL Default Set Unack */ + esp_ble_mesh_server_recv_light_xyl_range_set_t xyl_range; /*!< Light xyL Range Set/Light xyL Range Set Unack */ + esp_ble_mesh_server_recv_light_lc_mode_set_t lc_mode; /*!< Light LC Mode Set/Light LC Mode Set Unack */ + esp_ble_mesh_server_recv_light_lc_om_set_t lc_om; /*!< Light LC OM Set/Light LC OM Set Unack */ + esp_ble_mesh_server_recv_light_lc_light_onoff_set_t lc_light_onoff; /*!< Light LC Light OnOff Set/Light LC Light OnOff Set Unack */ + esp_ble_mesh_server_recv_light_lc_property_set_t lc_property; /*!< Light LC Property Set/Light LC Property Set Unack */ +} esp_ble_mesh_lighting_server_recv_set_msg_t; + +/** Context of the received Sensor Status message */ +typedef struct { + struct net_buf_simple *data; /*!< Value of sensor data state (optional) */ +} esp_ble_mesh_server_recv_sensor_status_t; + +/** + * @brief Lighting Server Model received status message union + */ +typedef union { + esp_ble_mesh_server_recv_sensor_status_t sensor_status; /*!< Sensor Status */ +} esp_ble_mesh_lighting_server_recv_status_msg_t; + +/** + * @brief Lighting Server Model callback value union + */ +typedef union { + esp_ble_mesh_lighting_server_state_change_t state_change; /*!< ESP_BLE_MESH_LIGHTING_SERVER_STATE_CHANGE_EVT */ + esp_ble_mesh_lighting_server_recv_get_msg_t get; /*!< ESP_BLE_MESH_LIGHTING_SERVER_RECV_GET_MSG_EVT */ + esp_ble_mesh_lighting_server_recv_set_msg_t set; /*!< ESP_BLE_MESH_LIGHTING_SERVER_RECV_SET_MSG_EVT */ + esp_ble_mesh_lighting_server_recv_status_msg_t status; /*!< ESP_BLE_MESH_LIGHTING_SERVER_RECV_STATUS_MSG_EVT */ +} esp_ble_mesh_lighting_server_cb_value_t; + +/** Lighting Server Model callback parameters */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to Lighting Server Models */ + esp_ble_mesh_msg_ctx_t ctx; /*!< Context of the received messages */ + esp_ble_mesh_lighting_server_cb_value_t value; /*!< Value of the received Lighting Messages */ +} esp_ble_mesh_lighting_server_cb_param_t; + +/** This enum value is the event of Lighting Server Model */ +typedef enum { + /** + * 1. When get_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, no event will be + * callback to the application layer when Lighting Get messages are received. + * 2. When set_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, this event will + * be callback to the application layer when Lighting Set/Set Unack messages + * are received. + */ + ESP_BLE_MESH_LIGHTING_SERVER_STATE_CHANGE_EVT, + /** + * When get_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Lighting Get messages are received. + */ + ESP_BLE_MESH_LIGHTING_SERVER_RECV_GET_MSG_EVT, + /** + * When set_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Lighting Set/Set Unack messages are received. + */ + ESP_BLE_MESH_LIGHTING_SERVER_RECV_SET_MSG_EVT, + /** + * When status_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will + * be callback to the application layer when Sensor Status message is received. + */ + ESP_BLE_MESH_LIGHTING_SERVER_RECV_STATUS_MSG_EVT, + ESP_BLE_MESH_LIGHTING_SERVER_EVT_MAX, +} esp_ble_mesh_lighting_server_cb_event_t; + +/** + * @brief Bluetooth Mesh Lighting Server Model function. + */ + +/** + * @brief Lighting Server Model callback function type + * @param event: Event type + * @param param: Pointer to callback parameter + */ +typedef void (* esp_ble_mesh_lighting_server_cb_t)(esp_ble_mesh_lighting_server_cb_event_t event, + esp_ble_mesh_lighting_server_cb_param_t *param); + +/** + * @brief Register BLE Mesh Lighting Server Model callback. + * + * @param[in] callback: Pointer to the callback function. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_register_lighting_server_callback(esp_ble_mesh_lighting_server_cb_t callback); #endif /* _ESP_BLE_MESH_LIGHTING_MODEL_API_H_ */ diff --git a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h index 1bc237a8a..52bc082dd 100644 --- a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h +++ b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h @@ -255,6 +255,372 @@ esp_err_t esp_ble_mesh_sensor_client_get_state(esp_ble_mesh_client_common_param_ esp_err_t esp_ble_mesh_sensor_client_set_state(esp_ble_mesh_client_common_param_t *params, esp_ble_mesh_sensor_client_set_state_t *set_state); +/** + * @brief Sensor Server Models related context. + */ + +/** @def ESP_BLE_MESH_MODEL_SENSOR_SRV + * + * @brief Define a new Sensor Server Model. + * + * @note 1. The Sensor Server model is a root model. When this model is present + * on an element, the corresponding Sensor Setup Server model shall + * also be present. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_sensor_srv_t. + * + * @return New Sensor Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_SENSOR_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_SENSOR_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_SENSOR_SETUP_SRV + * + * @brief Define a new Sensor Setup Server Model. + * + * @note 1. The Sensor Setup Server model extends the Sensor Server model. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_sensor_setup_srv_t. + * + * @return New Sensor Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_SENSOR_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +#define ESP_BLE_MESH_INVALID_SENSOR_PROPERTY_ID 0x0000 /*!< Invalid Sensor Property ID */ + +#define ESP_BLE_MESH_SENSOR_PROPERTY_ID_LEN 0x02 /*!< Length of Sensor Property ID */ + +#define ESP_BLE_MESH_SENSOR_DESCRIPTOR_LEN 0x08 /*!< Length of Sensor Descriptor state */ + +#define ESP_BLE_MESH_SENSOR_UNSPECIFIED_POS_TOLERANCE 0x000 /*!< Unspecified Sensor Positive Tolerance */ +#define ESP_BLE_MESH_SENSOR_UNSPECIFIED_NEG_TOLERANCE 0x000 /*!< Unspecified Sensor Negative Tolerance */ + +#define ESP_BLE_MESH_SENSOR_NOT_APPL_MEASURE_PERIOD 0x00 /*!< Not applicable Sensor Measurement Period */ + +#define ESP_BLE_MESH_SENSOR_NOT_APPL_UPDATE_INTERVAL 0x00 /*!< Not applicable Sensor Update Interval */ + +#define ESP_BLE_MESH_INVALID_SENSOR_SETTING_PROPERTY_ID 0x0000 /*!< Invalid Sensor Setting Property ID */ + +#define ESP_BLE_MESH_SENSOR_SETTING_PROPERTY_ID_LEN 0x02 /*!< Length of Sensor Setting Property ID */ +#define ESP_BLE_MESH_SENSOR_SETTING_ACCESS_LEN 0x01 /*!< Length of Sensor Setting Access */ + +#define ESP_BLE_MESH_SENSOR_SETTING_ACCESS_READ 0x01 /*!< Sensor Setting Access - Read */ +#define ESP_BLE_MESH_SENSOR_SETTING_ACCESS_READ_WRITE 0x03 /*!< Sensor Setting Access - Read & Write */ + +#define ESP_BLE_MESH_SENSOR_DIVISOR_TRIGGER_TYPE_LEN 0x01 /*!< Length of Sensor Divisor Trigger Type */ +#define ESP_BLE_MESH_SENSOR_STATUS_MIN_INTERVAL_LEN 0x01 /*!< Length of Sensor Status Min Interval */ + +#define ESP_BLE_MESH_SENSOR_PERIOD_DIVISOR_MAX_VALUE 15 /*!< Maximum value of Sensor Period Divisor */ + +#define ESP_BLE_MESH_SENSOR_STATUS_MIN_INTERVAL_MAX 26 /*!< Maximum value of Sensor Status Min Interval */ + +/** + * Sensor Status Trigger Type - Format Type of the characteristic + * that the Sensor Property ID state references + */ +#define ESP_BLE_MESH_SENSOR_STATUS_TRIGGER_TYPE_CHAR 0 +/** Sensor Status Trigger Type - Format Type "uint16" */ +#define ESP_BLE_MESH_SENSOR_STATUS_TRIGGER_TYPE_UINT16 1 + +#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_A 0x00 /*!< Sensor Data Format A */ +#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_B 0x01 /*!< Sensor Data Format B */ + +#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID_LEN 0x02 /*!< MPID length of Sensor Data Format A */ +#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN 0x03 /*!< MPID length of Sensor Data Format B */ + +/** + * Zero length of Sensor Data. + * + * Note: + * The Length field is a 1-based uint7 value (valid range 0x0–0x7F, + * representing range of 1–127). The value 0x7F represents a length + * of zero. + */ +#define ESP_BLE_MESH_SENSOR_DATA_ZERO_LEN 0x7F + +/** This enum value is value of Sensor Sampling Function */ +enum esp_ble_mesh_sensor_sample_func { + ESP_BLE_MESH_SAMPLE_FUNC_UNSPECIFIED, + ESP_BLE_MESH_SAMPLE_FUNC_INSTANTANEOUS, + ESP_BLE_MESH_SAMPLE_FUNC_ARITHMETIC_MEAN, + ESP_BLE_MESH_SAMPLE_FUNC_RMS, + ESP_BLE_MESH_SAMPLE_FUNC_MAXIMUM, + ESP_BLE_MESH_SAMPLE_FUNC_MINIMUM, + ESP_BLE_MESH_SAMPLE_FUNC_ACCUMULATED, + ESP_BLE_MESH_SAMPLE_FUNC_COUNT, +}; + +/** Parameters of Sensor Descriptor state */ +typedef struct { + uint32_t positive_tolerance : 12, /*!< The value of Sensor Positive Tolerance field */ + negative_tolerance : 12, /*!< The value of Sensor Negative Tolerance field */ + sampling_function : 8; /*!< The value of Sensor Sampling Function field */ + uint8_t measure_period; /*!< The value of Sensor Measurement Period field */ + uint8_t update_interval; /*!< The value of Sensor Update Interval field */ +} esp_ble_mesh_sensor_descriptor_t; + +/** Parameters of Sensor Setting state */ +typedef struct { + uint16_t property_id; /*!< The value of Sensor Setting Property ID field */ + uint8_t access; /*!< The value of Sensor Setting Access field */ + struct net_buf_simple *raw; /*!< The value of Sensor Setting Raw field */ +} esp_ble_mesh_sensor_setting_t; + +/** Parameters of Sensor Cadence state */ +typedef struct { + uint8_t period_divisor : 7, /*!< The value of Fast Cadence Period Divisor field */ + trigger_type : 1; /*!< The value of Status Trigger Type field */ + /** + * Note: + * The parameter "size" in trigger_delta_down, trigger_delta_up, fast_cadence_low & + * fast_cadence_high indicates the exact length of these four parameters, and they + * are associated with the Sensor Property ID. Users need to initialize the "size" + * precisely. + */ + struct net_buf_simple *trigger_delta_down; /*!< The value of Status Trigger Delta Down field */ + struct net_buf_simple *trigger_delta_up; /*!< The value of Status Trigger Delta Up field */ + uint8_t min_interval; /*!< The value of Status Min Interval field */ + struct net_buf_simple *fast_cadence_low; /*!< The value of Fast Cadence Low field */ + struct net_buf_simple *fast_cadence_high; /*!< The value of Fast Cadence High field */ +} esp_ble_mesh_sensor_cadence_t; + +/** Parameters of Sensor Data state */ +typedef struct { + /** + * Format A: The Length field is a 1-based uint4 value (valid range 0x0–0xF, + * representing range of 1 – 16). + * Format B: The Length field is a 1-based uint7 value (valid range 0x0–0x7F, + * representing range of 1 – 127). The value 0x7F represents a + * length of zero. + */ + uint8_t format : 1, /*!< The value of the Sensor Data format */ + length : 7; /*!< The value of the Sensor Data length */ + struct net_buf_simple *raw_value; /*!< The value of Sensor Data raw value */ +} esp_ble_mesh_sensor_data_t; + +/** Parameters of Sensor Series Column state */ +typedef struct { + struct net_buf_simple *raw_value_x; /*!< The value of Sensor Raw Value X field */ + struct net_buf_simple *column_width; /*!< The value of Sensor Column Width field */ + struct net_buf_simple *raw_value_y; /*!< The value of Sensor Raw Value Y field */ +} esp_ble_mesh_sensor_series_column_t; + +/** Parameters of Sensor states */ +typedef struct { + uint16_t sensor_property_id; /*!< The value of Sensor Property ID field */ + + /* Constant throughout the lifetime of an element */ + esp_ble_mesh_sensor_descriptor_t descriptor; /*!< Parameters of the Sensor Descriptor state */ + + /** + * Multiple Sensor Setting states may be present for each sensor. + * The Sensor Setting Property ID values shall be unique for each + * Sensor Property ID that identifies a sensor within an element. + */ + const uint8_t setting_count; /*!< */ + esp_ble_mesh_sensor_setting_t *settings; /*!< Parameters of the Sensor Setting state */ + + /** + * The Sensor Cadence state may be not supported by sensors based + * on device properties referencing "non-scalar characteristics" + * such as "histograms" or "composite characteristics". + */ + esp_ble_mesh_sensor_cadence_t *cadence; /*!< Parameters of the Sensor Cadence state */ + + esp_ble_mesh_sensor_data_t sensor_data; /*!< Parameters of the Sensor Data state */ + + esp_ble_mesh_sensor_series_column_t series_column; /*!< Parameters of the Sensor Series Column state */ +} esp_ble_mesh_sensor_state_t; + +/** User data of Sensor Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Sensor Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + const uint8_t state_count; /*!< Sensor state count */ + esp_ble_mesh_sensor_state_t *states; /*!< Parameters of the Sensor states */ +} esp_ble_mesh_sensor_srv_t; + +/** User data of Sensor Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Sensor Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + const uint8_t state_count; /*!< Sensor state count */ + esp_ble_mesh_sensor_state_t *states; /*!< Parameters of the Sensor states */ +} esp_ble_mesh_sensor_setup_srv_t; + +/** Parameters of Sensor Cadence Set state change event */ +typedef struct { + uint16_t property_id; /*!< The value of Sensor Property ID state */ + uint8_t period_divisor : 7, /*!< The value of Fast Cadence Period Divisor state */ + trigger_type : 1; /*!< The value of Status Trigger Type state */ + struct net_buf_simple *trigger_delta_down; /*!< The value of Status Trigger Delta Down state */ + struct net_buf_simple *trigger_delta_up; /*!< The value of Status Trigger Delta Up state */ + uint8_t min_interval; /*!< The value of Status Min Interval state */ + struct net_buf_simple *fast_cadence_low; /*!< The value of Fast Cadence Low state */ + struct net_buf_simple *fast_cadence_high; /*!< The value of Fast Cadence High state */ +} esp_ble_mesh_state_change_sensor_cadence_set_t; + +/** Parameters of Sensor Setting Set state change event */ +typedef struct { + uint16_t property_id; /*!< The value of Sensor Property ID state */ + uint16_t setting_property_id; /*!< The value of Sensor Setting Property ID state */ + struct net_buf_simple *setting_value; /*!< The value of Sensor Property Value state */ +} esp_ble_mesh_state_change_sensor_setting_set_t; + +/** + * @brief Sensor Server Model state change value union + */ +typedef union { + /** + * The recv_op in ctx can be used to decide which state is changed. + */ + esp_ble_mesh_state_change_sensor_cadence_set_t sensor_cadence_set; /*!< Sensor Cadence Set */ + esp_ble_mesh_state_change_sensor_setting_set_t sensor_setting_set; /*!< Sensor Setting Set */ +} esp_ble_mesh_sensor_server_state_change_t; + +/** Context of the received Sensor Descriptor Get message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t property_id; /*!< Property ID of a sensor (optional) */ +} esp_ble_mesh_server_recv_sensor_descriptor_get_t; + +/** Context of the received Sensor Cadence Get message */ +typedef struct { + uint16_t property_id; /*!< Property ID of a sensor */ +} esp_ble_mesh_server_recv_sensor_cadence_get_t; + +/** Context of the received Sensor Settings Get message */ +typedef struct { + uint16_t property_id; /*!< Property ID of a sensor */ +} esp_ble_mesh_server_recv_sensor_settings_get_t; + +/** Context of the received Sensor Setting Get message */ +typedef struct { + uint16_t property_id; /*!< Property ID of a sensor */ + uint16_t setting_property_id; /*!< Setting ID identifying a setting within a sensor */ +} esp_ble_mesh_server_recv_sensor_setting_get_t; + +/** Context of the received Sensor Get message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t property_id; /*!< Property ID for the sensor (optional) */ +} esp_ble_mesh_server_recv_sensor_get_t; + +/** Context of the received Sensor Column Get message */ +typedef struct { + uint16_t property_id; /*!< Property identifying a sensor */ + struct net_buf_simple *raw_value_x; /*!< Raw value identifying a column */ +} esp_ble_mesh_server_recv_sensor_column_get_t; + +/** Context of the received Sensor Series Get message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t property_id; /*!< Property identifying a sensor */ + struct net_buf_simple *raw_value; /*!< Raw value containg X1 and X2 (optional) */ +} esp_ble_mesh_server_recv_sensor_series_get_t; + +/** + * @brief Sensor Server Model received get message union + */ +typedef union { + esp_ble_mesh_server_recv_sensor_descriptor_get_t sensor_descriptor; /*!< Sensor Descriptor Get */ + esp_ble_mesh_server_recv_sensor_cadence_get_t sensor_cadence; /*!< Sensor Cadence Get */ + esp_ble_mesh_server_recv_sensor_settings_get_t sensor_settings; /*!< Sensor Settings Get */ + esp_ble_mesh_server_recv_sensor_setting_get_t sensor_setting; /*!< Sensor Setting Get */ + esp_ble_mesh_server_recv_sensor_get_t sensor_data; /*!< Sensor Get */ + esp_ble_mesh_server_recv_sensor_column_get_t sensor_column; /*!< Sensor Column Get */ + esp_ble_mesh_server_recv_sensor_series_get_t sensor_series; /*!< Sensor Series Get */ +} esp_ble_mesh_sensor_server_recv_get_msg_t; + +/** Context of the received Sensor Cadence Set message */ +typedef struct { + uint16_t property_id; /*!< Property ID for the sensor */ + struct net_buf_simple *cadence; /*!< Value of Sensor Cadence state */ +} esp_ble_mesh_server_recv_sensor_cadence_set_t; + +/** Context of the received Sensor Setting Set message */ +typedef struct { + uint16_t property_id; /*!< Property ID identifying a sensor */ + uint16_t setting_property_id; /*!< Setting ID identifying a setting within a sensor */ + struct net_buf_simple *setting_raw; /*!< Raw value for the setting */ +} esp_ble_mesh_server_recv_sensor_setting_set_t; + +/** + * @brief Sensor Server Model received set message union + */ +typedef union { + esp_ble_mesh_server_recv_sensor_cadence_set_t sensor_cadence; /*!< Sensor Cadence Set */ + esp_ble_mesh_server_recv_sensor_setting_set_t sensor_setting; /*!< Sensor Setting Set */ +} esp_ble_mesh_sensor_server_recv_set_msg_t; + +/** + * @brief Sensor Server Model callback value union + */ +typedef union { + esp_ble_mesh_sensor_server_state_change_t state_change; /*!< ESP_BLE_MESH_SENSOR_SERVER_STATE_CHANGE_EVT */ + esp_ble_mesh_sensor_server_recv_get_msg_t get; /*!< ESP_BLE_MESH_SENSOR_SERVER_RECV_GET_MSG_EVT */ + esp_ble_mesh_sensor_server_recv_set_msg_t set; /*!< ESP_BLE_MESH_SENSOR_SERVER_RECV_SET_MSG_EVT */ +} esp_ble_mesh_sensor_server_cb_value_t; + +/** Sensor Server Model callback parameters */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to Sensor Server Models */ + esp_ble_mesh_msg_ctx_t ctx; /*!< Context of the received messages */ + esp_ble_mesh_sensor_server_cb_value_t value; /*!< Value of the received Sensor Messages */ +} esp_ble_mesh_sensor_server_cb_param_t; + +/** This enum value is the event of Sensor Server Model */ +typedef enum { + /** + * 1. When get_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, no event will be + * callback to the application layer when Sensor Get messages are received. + * 2. When set_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, this event will + * be callback to the application layer when Sensor Set/Set Unack messages + * are received. + */ + ESP_BLE_MESH_SENSOR_SERVER_STATE_CHANGE_EVT, + /** + * When get_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Sensor Get messages are received. + */ + ESP_BLE_MESH_SENSOR_SERVER_RECV_GET_MSG_EVT, + /** + * When set_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Sensor Set/Set Unack messages are received. + */ + ESP_BLE_MESH_SENSOR_SERVER_RECV_SET_MSG_EVT, + ESP_BLE_MESH_SENSOR_SERVER_EVT_MAX, +} esp_ble_mesh_sensor_server_cb_event_t; + +/** + * @brief Bluetooth Mesh Sensor Server Model function. + */ + +/** + * @brief Sensor Server Model callback function type + * @param event: Event type + * @param param: Pointer to callback parameter + */ +typedef void (* esp_ble_mesh_sensor_server_cb_t)(esp_ble_mesh_sensor_server_cb_event_t event, + esp_ble_mesh_sensor_server_cb_param_t *param); + +/** + * @brief Register BLE Mesh Sensor Server Model callback. + * + * @param[in] callback: Pointer to the callback function. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_register_sensor_server_callback(esp_ble_mesh_sensor_server_cb_t callback); + #endif /* _ESP_BLE_MESH_SENSOR_MODEL_API_H_ */ diff --git a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h index 3d2aebd12..525fe3a88 100644 --- a/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h +++ b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h @@ -314,5 +314,599 @@ esp_err_t esp_ble_mesh_time_scene_client_get_state(esp_ble_mesh_client_common_pa esp_err_t esp_ble_mesh_time_scene_client_set_state(esp_ble_mesh_client_common_param_t *params, esp_ble_mesh_time_scene_client_set_state_t *set_state); +/** + * @brief Time Scene Server Models related context. + */ + +/** @def ESP_BLE_MESH_MODEL_TIME_SRV + * + * @brief Define a new Time Server Model. + * + * @note 1. The Time Server model is a root model. When this model is present on an + * Element, the corresponding Time Setup Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_time_srv_t. + * + * @return New Time Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_TIME_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_TIME_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_TIME_SETUP_SRV + * + * @brief Define a new Time Setup Server Model. + * + * @note 1. The Time Setup Server model extends the Time Server model. Time is + * sensitive information that is propagated across a mesh network. + * 2. Only an authorized Time Client should be allowed to change the Time + * and Time Role states. A dedicated application key Bluetooth SIG + * Proprietary should be used on the Time Setup Server to restrict + * access to the server to only authorized Time Clients. + * 3. This model does not support subscribing nor publishing. + * + * @param srv_data Pointer to the unique struct esp_ble_mesh_time_setup_srv_t. + * + * @return New Time Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_TIME_SETUP_SRV(srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_TIME_SETUP_SRV, \ + NULL, NULL, srv_data) + +/** @def ESP_BLE_MESH_MODEL_SCENE_SRV + * + * @brief Define a new Scene Server Model. + * + * @note 1. The Scene Server model is a root model. When this model is present + * on an Element, the corresponding Scene Setup Server model shall + * also be present. + * 2. This model shall support model publication and model subscription. + * 3. The model may be present only on the Primary element of a node. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_scene_srv_t. + * + * @return New Scene Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_SCENE_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_SCENE_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV + * + * @brief Define a new Scene Setup Server Model. + * + * @note 1. The Scene Setup Server model extends the Scene Server model and + * the Generic Default Transition Time Server model. + * 2. This model shall support model subscription. + * 3. The model may be present only on the Primary element of a node. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_scene_setup_srv_t. + * + * @return New Scene Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_SCENE_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_SCHEDULER_SRV + * + * @brief Define a new Scheduler Server Model. + * + * @note 1. The Scheduler Server model extends the Scene Server model. When + * this model is present on an Element, the corresponding Scheduler + * Setup Server model shall also be present. + * 2. This model shall support model publication and model subscription. + * 3. The model may be present only on the Primary element of a node. + * 4. The model requires the Time Server model shall be present on the element. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_scheduler_srv_t. + * + * @return New Scheduler Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_SCHEDULER_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_SCHEDULER_SRV, \ + NULL, srv_pub, srv_data) + +/** @def ESP_BLE_MESH_MODEL_SCHEDULER_SETUP_SRV + * + * @brief Define a new Scheduler Setup Server Model. + * + * @note 1. The Scheduler Setup Server model extends the Scheduler Server and + * the Scene Setup Server models. + * 2. This model shall support model subscription. + * 3. The model may be present only on the Primary element of a node. + * + * @param srv_pub Pointer to the unique struct esp_ble_mesh_model_pub_t. + * @param srv_data Pointer to the unique struct esp_ble_mesh_scheduler_setup_srv_t. + * + * @return New Scheduler Setup Server Model instance. + */ +#define ESP_BLE_MESH_MODEL_SCHEDULER_SETUP_SRV(srv_pub, srv_data) \ + ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV, \ + NULL, srv_pub, srv_data) + +#define ESP_BLE_MESH_UNKNOWN_TAI_SECONDS 0x0000000000 /*!< Unknown TAI Seconds */ +#define ESP_BLE_MESH_UNKNOWN_TAI_ZONE_CHANGE 0x0000000000 /*!< Unknown TAI of Zone Change */ +#define ESP_BLE_MESH_UNKNOWN_TAI_DELTA_CHANGE 0x0000000000 /*!< Unknown TAI of Delta Change */ + +#define ESP_BLE_MESH_TAI_UTC_DELAT_MAX_VALUE 0x7FFF /*!< Maximum TAI-UTC Delta value */ + +#define ESP_BLE_MESH_TAI_SECONDS_LEN 0x05 /*!< Length of TAI Seconds */ +#define ESP_BLE_MESH_TAI_OF_ZONE_CHANGE_LEN 0x05 /*!< Length of TAI of Zone Change */ +#define ESP_BLE_MESH_TAI_OF_DELAT_CHANGE_LEN 0x05 /*!< Length of TAI of Delta Change */ + +#define ESP_BLE_MESH_INVALID_SCENE_NUMBER 0x0000 /*!< Invalid Scene Number */ +#define ESP_BLE_MESH_SCENE_NUMBER_LEN 0x02 /*!< Length of the Scene Number */ + +#define ESP_BLE_MESH_SCHEDULE_YEAR_ANY_YEAR 0x64 /*!< Any year of the Scheduled year */ + +#define ESP_BLE_MESH_SCHEDULE_DAY_ANY_DAY 0x00 /*!< Any day of the Scheduled day */ + +#define ESP_BLE_MESH_SCHEDULE_HOUR_ANY_HOUR 0x18 /*!< Any hour of the Scheduled hour */ +#define ESP_BLE_MESH_SCHEDULE_HOUR_ONCE_A_DAY 0x19 /*!< Any hour of the Scheduled Day */ + +#define ESP_BLE_MESH_SCHEDULE_SEC_ANY_OF_HOUR 0x3C /*!< Any minute of the Scheduled hour */ +#define ESP_BLE_MESH_SCHEDULE_SEC_EVERY_15_MIN 0x3D /*!< Every 15 minutes of the Scheduled hour */ +#define ESP_BLE_MESH_SCHEDULE_SEC_EVERY_20_MIN 0x3E /*!< Every 20 minutes of the Scheduled hour */ +#define ESP_BLE_MESH_SCHEDULE_SEC_ONCE_AN_HOUR 0x3F /*!< Once of the Scheduled hour */ + +#define ESP_BLE_MESH_SCHEDULE_SEC_ANY_OF_MIN 0x3C /*!< Any second of the Scheduled minute */ +#define ESP_BLE_MESH_SCHEDULE_SEC_EVERY_15_SEC 0x3D /*!< Every 15 seconds of the Scheduled minute */ +#define ESP_BLE_MESH_SCHEDULE_SEC_EVERY_20_SEC 0x3E /*!< Every 20 seconds of the Scheduled minute */ +#define ESP_BLE_MESH_SCHEDULE_SEC_ONCE_AN_MIN 0x3F /*!< Once of the Scheduled minute */ + +#define ESP_BLE_MESH_SCHEDULE_ACT_TURN_OFF 0x00 /*!< Scheduled Action - Turn Off */ +#define ESP_BLE_MESH_SCHEDULE_ACT_TURN_ON 0x01 /*!< Scheduled Action - Turn On */ +#define ESP_BLE_MESH_SCHEDULE_ACT_SCENE_RECALL 0x02 /*!< Scheduled Action - Scene Recall */ +#define ESP_BLE_MESH_SCHEDULE_ACT_NO_ACTION 0x0F /*!< Scheduled Action - No Action */ + +#define ESP_BLE_MESH_SCHEDULE_SCENE_NO_SCENE 0x0000 /*!< Scheduled Scene - No Scene */ + +#define ESP_BLE_MESH_SCHEDULE_ENTRY_MAX_INDEX 0x0F /*!< Maximum number of Scheduled entries */ + +#define ESP_BLE_MESH_TIME_NONE 0x00 /*!< Time Role - None */ +#define ESP_BLE_MESH_TIME_AUTHORITY 0x01 /*!< Time Role - Mesh Time Authority */ +#define ESP_BLE_MESH_TIME_RELAY 0x02 /*!< Time Role - Mesh Time Relay */ +#define ESP_BLE_MESH_TIME_CLINET 0x03 /*!< Time Role - Mesh Time Client */ + +#define ESP_BLE_MESH_SCENE_SUCCESS 0x00 /*!< Scene operation - Success */ +#define ESP_BLE_MESH_SCENE_REG_FULL 0x01 /*!< Scene operation - Scene Register Full */ +#define ESP_BLE_MESH_SCENE_NOT_FOUND 0x02 /*!< Scene operation - Scene Not Found */ + +/** Parameters of Time state */ +typedef struct { + struct { + uint8_t tai_seconds[5]; /*!< The value of the TAI Seconds state */ + uint8_t subsecond; /*!< The value of the Subsecond field */ + uint8_t uncertainty; /*!< The value of the Uncertainty field */ + uint8_t time_zone_offset_curr; /*!< The value of the Time Zone Offset Current field */ + uint8_t time_zone_offset_new; /*!< The value of the Time Zone Offset New state */ + uint8_t tai_zone_change[5]; /*!< The value of the TAI of Zone Chaneg field */ + uint16_t time_authority : 1, /*!< The value of the Time Authority bit */ + tai_utc_delta_curr : 15; /*!< The value of the TAI-UTC Delta Current state */ + uint16_t tai_utc_delta_new : 15; /*!< The value of the TAI-UTC Delta New state */ + uint8_t tai_delta_change[5]; /*!< The value of the TAI of Delta Change field */ + } time; /*!< Parameters of the Time state */ + uint8_t time_role; /*!< The value of the Time Role state */ +} esp_ble_mesh_time_state_t; + +/** User data of Time Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Time Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_time_state_t *state; /*!< Parameters of the Time state */ +} esp_ble_mesh_time_srv_t; + +/** User data of Time Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Time Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_time_state_t *state; /*!< Parameters of the Time state */ +} esp_ble_mesh_time_setup_srv_t; + +/** + * 1. Scene Store is an operation of storing values of a present state of an element. + * 2. The structure and meaning of the stored state is determined by a model. States + * to be stored are specified by each model. + * 3. The Scene Store operation shall persistently store all values of all states + * marked as Stored with Scene for all models present on all elements of a node. + * 4. If a model is extending another model, the extending model shall determine the + * Stored with Scene behavior of that model. + */ + +/** Parameters of Scene Register state */ +typedef struct { + uint16_t scene_number; /*!< The value of the Scene Number */ + uint8_t scene_type; /*!< The value of the Scene Type */ + /** + * Scene value may use a union to represent later, the union contains + * structures of all the model states which can be stored in a scene. + */ + struct net_buf_simple *scene_value; /*!< The value of the Scene Value */ +} esp_ble_mesh_scene_register_t; + +/** + * Parameters of Scenes state. + * + * Scenes serve as memory banks for storage of states (e.g., a power level + * or a light level/color). Values of states of an element can be stored + * as a scene and can be recalled later from the scene memory. + * + * A scene is represented by a Scene Number, which is a 16-bit non-zero, + * mesh-wide value. (There can be a maximum of 65535 scenes in a mesh + * network.) The meaning of a scene, as well as the state storage container + * associated with it, are determined by a model. + * + * The Scenes state change may start numerous parallel model transitions. + * In that case, each individual model handles the transition internally. + * + * The scene transition is defined as a group of individual model transitions + * started by a Scene Recall operation. The scene transition is in progress + * when at least one transition from the group of individual model transitions + * is in progress. + */ +typedef struct { + const uint16_t scene_count; /*!< The Scenes state's scene count */ + esp_ble_mesh_scene_register_t *scenes; /*!< Parameters of the Scenes state */ + + /** + * The Current Scene state is a 16-bit value that contains either the Scene + * Number of the currently active scene or a value of 0x0000 when no scene + * is active. + * + * When a Scene Store operation or a Scene Recall operation completes with + * success, the Current Scene state value shall be to the Scene Number used + * during that operation. + * + * When the Current Scene Number is deleted from a Scene Register state as a + * result of Scene Delete operation, the Current Scene state shall be set to + * 0x0000. + * + * When any of the element's state that is marked as “Stored with Scene” has + * changed not as a result of a Scene Recall operation, the value of the + * Current Scene state shall be set to 0x0000. + * + * When a scene transition is in progress, the value of the Current Scene + * state shall be set to 0x0000. + */ + uint16_t current_scene; /*!< The value of the Current Scene state */ + + /** + * The Target Scene state is a 16-bit value that contains the target Scene + * Number when a scene transition is in progress. + * + * When the scene transition is in progress and the target Scene Number is + * deleted from a Scene Register state as a result of Scene Delete operation, + * the Target Scene state shall be set to 0x0000. + * + * When the scene transition is in progress and a new Scene Number is stored + * in the Scene Register as a result of Scene Store operation, the Target + * Scene state shall be set to the new Scene Number. + * + * When the scene transition is not in progress, the value of the Target Scene + * state shall be set to 0x0000. + */ + uint16_t target_scene; /*!< The value of the Target Scene state */ + + /* Indicate the status code for the last operation */ + uint8_t status_code; /*!< The status code of the last scene operation */ + + /* Indicate if scene transition is in progress */ + bool in_progress; /*!< Indicate if the scene transition is in progress */ +} esp_ble_mesh_scenes_state_t; + +/** User data of Scene Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Scene Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_scenes_state_t *state; /*!< Parameters of the Scenes state */ + esp_ble_mesh_last_msg_info_t last; /*!< Parameters of the last received set message */ + esp_ble_mesh_state_transition_t transition; /*!< Parameters of state transition */ +} esp_ble_mesh_scene_srv_t; + +/** User data of Scene Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Scene Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_scenes_state_t *state; /*!< Parameters of the Scenes state */ +} esp_ble_mesh_scene_setup_srv_t; + +/** Parameters of Scheduler Register state */ +typedef struct { + bool in_use; /*!< Indicate if the registered schedule is in use */ + uint64_t year : 7, /*!< The value of Scheduled year for the action */ + month : 12, /*!< The value of Scheduled month for the action */ + day : 5, /*!< The value of Scheduled day of the month for the action */ + hour : 5, /*!< The value of Scheduled hour for the action */ + minute : 6, /*!< The value of Scheduled minute for the action */ + second : 6, /*!< The value of Scheduled second for the action */ + day_of_week : 7, /*!< The value of Schedule days of the week for the action */ + action : 4, /*!< The value of Action to be performed at the scheduled time */ + trans_time : 8; /*!< The value of Transition time for this action */ + uint16_t scene_number; /*!< The value of Scene Number to be used for some actions */ +} esp_ble_mesh_schedule_register_t; + +/** Parameters of Scheduler state */ +typedef struct { + const uint8_t schedule_count; /*!< Scheduler count */ + esp_ble_mesh_schedule_register_t *schedules; /*!< Up to 16 scheduled entries */ +} esp_ble_mesh_scheduler_state_t; + +/** User data of Scheduler Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Scheduler Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_scheduler_state_t *state; /*!< Parameters of the Scheduler state */ +} esp_ble_mesh_scheduler_srv_t; + +/** User data of Scheduler Setup Server Model */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to the Scheduler Setup Server Model. Initialized internally. */ + esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl; /*!< Response control of the server model received messages */ + esp_ble_mesh_scheduler_state_t *state; /*!< Parameters of the Scheduler state */ +} esp_ble_mesh_scheduler_setup_srv_t; + +/** Parameters of Time Set state change event */ +typedef struct { + uint8_t tai_seconds[5]; /*!< The current TAI time in seconds */ + uint8_t subsecond; /*!< The sub-second time in units of 1/256 second */ + uint8_t uncertainty; /*!< The estimated uncertainty in 10-millisecond steps */ + uint16_t time_authority : 1; /*!< 0 = No Time Authority, 1 = Time Authority */ + uint16_t tai_utc_delta_curr : 15; /*!< Current difference between TAI and UTC in seconds */ + uint8_t time_zone_offset_curr; /*!< The local time zone offset in 15-minute increments */ +} esp_ble_mesh_state_change_time_set_t; + +/** Parameters of Time Status state change event */ +typedef struct { + uint8_t tai_seconds[5]; /*!< The current TAI time in seconds */ + uint8_t subsecond; /*!< The sub-second time in units of 1/256 second */ + uint8_t uncertainty; /*!< The estimated uncertainty in 10-millisecond steps */ + uint16_t time_authority : 1; /*!< 0 = No Time Authority, 1 = Time Authority */ + uint16_t tai_utc_delta_curr : 15; /*!< Current difference between TAI and UTC in seconds */ + uint8_t time_zone_offset_curr; /*!< The local time zone offset in 15-minute increments */ +} esp_ble_mesh_state_change_time_status_t; + +/** Parameters of Time Zone Set state change event */ +typedef struct { + uint8_t time_zone_offset_new; /*!< Upcoming local time zone offset */ + uint8_t tai_zone_change[5]; /*!< TAI Seconds time of the upcoming Time Zone Offset change */ +} esp_ble_mesh_state_change_time_zone_set_t; + +/** Parameters of TAI UTC Delta Set state change event */ +typedef struct { + uint16_t tai_utc_delta_new : 15; /*!< Upcoming difference between TAI and UTC in seconds */ + uint8_t tai_delta_change[5]; /*!< TAI Seconds time of the upcoming TAI-UTC Delta change */ +} esp_ble_mesh_state_change_tai_utc_delta_set_t; + +/** Parameter of Time Role Set state change event */ +typedef struct { + uint8_t time_role; /*!< The Time Role for the element */ +} esp_ble_mesh_state_change_time_role_set_t; + +/** Parameter of Scene Store state change event */ +typedef struct { + uint16_t scene_number; /*!< The number of scenes to be stored */ +} esp_ble_mesh_state_change_scene_store_t; + +/** Parameter of Scene Recall state change event */ +typedef struct { + uint16_t scene_number; /*!< The number of scenes to be recalled */ +} esp_ble_mesh_state_change_scene_recall_t; + +/** Parameter of Scene Delete state change event */ +typedef struct { + uint16_t scene_number; /*!< The number of scenes to be deleted */ +} esp_ble_mesh_state_change_scene_delete_t; + +/** Parameter of Scheduler Action Set state change event */ +typedef struct { + uint64_t index : 4; /*!< Index of the Schedule Register entry to set */ + uint64_t year : 7; /*!< Scheduled year for the action */ + uint64_t month : 12; /*!< Scheduled month for the action */ + uint64_t day : 5; /*!< Scheduled day of the month for the action */ + uint64_t hour : 5; /*!< Scheduled hour for the action */ + uint64_t minute : 6; /*!< Scheduled minute for the action */ + uint64_t second : 6; /*!< Scheduled second for the action */ + uint64_t day_of_week : 7; /*!< Schedule days of the week for the action */ + uint64_t action : 4; /*!< Action to be performed at the scheduled time */ + uint64_t trans_time : 8; /*!< Transition time for this action */ + uint16_t scene_number; /*!< Scene number to be used for some actions */ +} esp_ble_mesh_state_change_scheduler_act_set_t; + +/** + * @brief Time Scene Server Model state change value union + */ +typedef union { + /** + * The recv_op in ctx can be used to decide which state is changed. + */ + esp_ble_mesh_state_change_time_set_t time_set; /*!< Time Set */ + esp_ble_mesh_state_change_time_status_t time_status; /*!< Time Status */ + esp_ble_mesh_state_change_time_zone_set_t time_zone_set; /*!< Time Zone Set */ + esp_ble_mesh_state_change_tai_utc_delta_set_t tai_utc_delta_set; /*!< TAI UTC Delta Set */ + esp_ble_mesh_state_change_time_role_set_t time_role_set; /*!< Time Role Set */ + esp_ble_mesh_state_change_scene_store_t scene_store; /*!< Scene Store */ + esp_ble_mesh_state_change_scene_recall_t scene_recall; /*!< Scene Recall */ + esp_ble_mesh_state_change_scene_delete_t scene_delete; /*!< Scene Delete */ + esp_ble_mesh_state_change_scheduler_act_set_t scheduler_act_set; /*!< Scheduler Action Set */ +} esp_ble_mesh_time_scene_server_state_change_t; + +/** Context of the received Scheduler Action Get message */ +typedef struct { + uint8_t index; /*!< Index of the Schedule Register entry to get */ +} esp_ble_mesh_server_recv_scheduler_act_get_t; + +/** + * @brief Time Scene Server Model received get message union + */ +typedef union { + esp_ble_mesh_server_recv_scheduler_act_get_t scheduler_act; /*!< Scheduler Action Get */ +} esp_ble_mesh_time_scene_server_recv_get_msg_t; + +/** Context of the received Time Set message */ +typedef struct { + uint8_t tai_seconds[5]; /*!< The current TAI time in seconds */ + uint8_t subsecond; /*!< The sub-second time in units of 1/256 second */ + uint8_t uncertainty; /*!< The estimated uncertainty in 10-millisecond steps */ + uint16_t time_authority : 1; /*!< 0 = No Time Authority, 1 = Time Authority */ + uint16_t tai_utc_delta : 15; /*!< Current difference between TAI and UTC in seconds */ + uint8_t time_zone_offset; /*!< The local time zone offset in 15-minute increments */ +} esp_ble_mesh_server_recv_time_set_t; + +/** Context of the received Time Zone Set message */ +typedef struct { + uint8_t time_zone_offset_new; /*!< Upcoming local time zone offset */ + uint8_t tai_zone_change[5]; /*!< TAI Seconds time of the upcoming Time Zone Offset change */ +} esp_ble_mesh_server_recv_time_zone_set_t; + +/** Context of the received TAI UTC Delta Set message */ +typedef struct { + uint16_t tai_utc_delta_new : 15; /*!< Upcoming difference between TAI and UTC in seconds */ + uint16_t padding : 1; /*!< Always 0b0. Other values are Prohibited. */ + uint8_t tai_delta_change[5]; /*!< TAI Seconds time of the upcoming TAI-UTC Delta change */ +} esp_ble_mesh_server_recv_tai_utc_delta_set_t; + +/** Context of the received Time Role Set message */ +typedef struct { + uint8_t time_role; /*!< The Time Role for the element */ +} esp_ble_mesh_server_recv_time_role_set_t; + +/** Context of the received Scene Store message */ +typedef struct { + uint16_t scene_number; /*!< The number of scenes to be stored */ +} esp_ble_mesh_server_recv_scene_store_t; + +/** Context of the received Scene Recall message */ +typedef struct { + bool op_en; /*!< Indicate if optional parameters are included */ + uint16_t scene_number; /*!< The number of scenes to be recalled */ + uint8_t tid; /*!< Transaction ID */ + uint8_t trans_time; /*!< Time to complete state transition (optional) */ + uint8_t delay; /*!< Indicate message execution delay (C.1) */ +} esp_ble_mesh_server_recv_scene_recall_t; + +/** Context of the received Scene Delete message */ +typedef struct { + uint16_t scene_number; /*!< The number of scenes to be deleted */ +} esp_ble_mesh_server_recv_scene_delete_t; + +/** Context of the received Scheduler Action Set message */ +typedef struct { + uint64_t index : 4; /*!< Index of the Schedule Register entry to set */ + uint64_t year : 7; /*!< Scheduled year for the action */ + uint64_t month : 12; /*!< Scheduled month for the action */ + uint64_t day : 5; /*!< Scheduled day of the month for the action */ + uint64_t hour : 5; /*!< Scheduled hour for the action */ + uint64_t minute : 6; /*!< Scheduled minute for the action */ + uint64_t second : 6; /*!< Scheduled second for the action */ + uint64_t day_of_week : 7; /*!< Schedule days of the week for the action */ + uint64_t action : 4; /*!< Action to be performed at the scheduled time */ + uint64_t trans_time : 8; /*!< Transition time for this action */ + uint16_t scene_number; /*!< Scene number to be used for some actions */ +} esp_ble_mesh_server_recv_scheduler_act_set_t; + +/** + * @brief Time Scene Server Model received set message union + */ +typedef union { + esp_ble_mesh_server_recv_time_set_t time; /*!< Time Set */ + esp_ble_mesh_server_recv_time_zone_set_t time_zone; /*!< Time Zone Set */ + esp_ble_mesh_server_recv_tai_utc_delta_set_t tai_utc_delta; /*!< TAI-UTC Delta Set */ + esp_ble_mesh_server_recv_time_role_set_t time_role; /*!< Time Role Set */ + esp_ble_mesh_server_recv_scene_store_t scene_store; /*!< Scene Store/Scene Store Unack */ + esp_ble_mesh_server_recv_scene_recall_t scene_recall; /*!< Scene Recall/Scene Recall Unack */ + esp_ble_mesh_server_recv_scene_delete_t scene_delete; /*!< Scene Delete/Scene Delete Unack */ + esp_ble_mesh_server_recv_scheduler_act_set_t scheduler_act; /*!< Scheduler Action Set/Scheduler Action Set Unack */ +} esp_ble_mesh_time_scene_server_recv_set_msg_t; + +/** Context of the received Time Status message */ +typedef struct { + uint8_t tai_seconds[5]; /*!< The current TAI time in seconds */ + uint8_t subsecond; /*!< The sub-second time in units of 1/256 second */ + uint8_t uncertainty; /*!< The estimated uncertainty in 10-millisecond steps */ + uint16_t time_authority : 1; /*!< 0 = No Time Authority, 1 = Time Authority */ + uint16_t tai_utc_delta : 15; /*!< Current difference between TAI and UTC in seconds */ + uint8_t time_zone_offset; /*!< The local time zone offset in 15-minute increments */ +} esp_ble_mesh_server_recv_time_status_t; + +/** + * @brief Time Scene Server Model received status message union + */ +typedef union { + esp_ble_mesh_server_recv_time_status_t time_status; /*!< Time Status */ +} esp_ble_mesh_time_scene_server_recv_status_msg_t; + +/** + * @brief Time Scene Server Model callback value union + */ +typedef union { + esp_ble_mesh_time_scene_server_state_change_t state_change; /*!< ESP_BLE_MESH_TIME_SCENE_SERVER_STATE_CHANGE_EVT */ + esp_ble_mesh_time_scene_server_recv_get_msg_t get; /*!< ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_GET_MSG_EVT */ + esp_ble_mesh_time_scene_server_recv_set_msg_t set; /*!< ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_SET_MSG_EVT */ + esp_ble_mesh_time_scene_server_recv_status_msg_t status; /*!< ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_STATUS_MSG_EVT */ +} esp_ble_mesh_time_scene_server_cb_value_t; + +/** Time Scene Server Model callback parameters */ +typedef struct { + esp_ble_mesh_model_t *model; /*!< Pointer to Time and Scenes Server Models */ + esp_ble_mesh_msg_ctx_t ctx; /*!< Context of the received messages */ + esp_ble_mesh_time_scene_server_cb_value_t value; /*!< Value of the received Time and Scenes Messages */ +} esp_ble_mesh_time_scene_server_cb_param_t; + +/** This enum value is the event of Time Scene Server Model */ +typedef enum { + /** + * 1. When get_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, no event will be + * callback to the application layer when Time Scene Get messages are received. + * 2. When set_auto_rsp is set to ESP_BLE_MESH_SERVER_AUTO_RSP, this event will + * be callback to the application layer when Time Scene Set/Set Unack messages + * are received. + */ + ESP_BLE_MESH_TIME_SCENE_SERVER_STATE_CHANGE_EVT, + /** + * When get_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Time Scene Get messages are received. + */ + ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_GET_MSG_EVT, + /** + * When set_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will be + * callback to the application layer when Time Scene Set/Set Unack messages are received. + */ + ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_SET_MSG_EVT, + /** + * When status_auto_rsp is set to ESP_BLE_MESH_SERVER_RSP_BY_APP, this event will + * be callback to the application layer when TIme Status message is received. + */ + ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_STATUS_MSG_EVT, + ESP_BLE_MESH_TIME_SCENE_SERVER_EVT_MAX, +} esp_ble_mesh_time_scene_server_cb_event_t; + +/** + * @brief Bluetooth Mesh Time and Scenes Server Model function. + */ + +/** + * @brief Time Scene Server Model callback function type + * @param event: Event type + * @param param: Pointer to callback parameter + */ +typedef void (* esp_ble_mesh_time_scene_server_cb_t)(esp_ble_mesh_time_scene_server_cb_event_t event, + esp_ble_mesh_time_scene_server_cb_param_t *param); + +/** + * @brief Register BLE Mesh Time and Scenes Server Model callback. + * + * @param[in] callback: Pointer to the callback function. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_register_time_scene_server_callback(esp_ble_mesh_time_scene_server_cb_t callback); + #endif /* _ESP_BLE_MESH_TIME_SCENE_MODEL_API_H_ */ diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_config_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_config_model.c index fe2700e20..7cd73b942 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_config_model.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_config_model.c @@ -288,12 +288,17 @@ static void btc_ble_mesh_config_client_callback(esp_ble_mesh_cfg_client_cb_param LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_CONFIG_CLIENT)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_CONFIG_CLIENT; msg.act = act; btc_transfer_context(&msg, cb_params, - sizeof(esp_ble_mesh_cfg_client_cb_param_t), btc_ble_mesh_config_client_copy_req_data); + sizeof(esp_ble_mesh_cfg_client_cb_param_t), btc_ble_mesh_config_client_copy_req_data); } void bt_mesh_config_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, @@ -361,7 +366,7 @@ void btc_ble_mesh_config_client_publish_callback(u32_t opcode, } bt_mesh_config_client_cb_evt_to_btc(opcode, - BTC_BLE_MESH_EVT_CONFIG_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); + BTC_BLE_MESH_EVT_CONFIG_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); return; } @@ -398,7 +403,7 @@ static int btc_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param case ESP_BLE_MESH_MODEL_OP_MODEL_PUB_GET: return (cb->error_code = bt_mesh_cfg_mod_pub_get(&ctx, get->model_pub_get.element_addr, - get->model_pub_get.model_id, get->model_pub_get.company_id)); + get->model_pub_get.model_id, get->model_pub_get.company_id)); case ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_GET: return (cb->error_code = bt_mesh_cfg_hb_pub_get(&ctx)); case ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_GET: @@ -408,11 +413,11 @@ static int btc_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param case ESP_BLE_MESH_MODEL_OP_SIG_MODEL_SUB_GET: return (cb->error_code = bt_mesh_cfg_mod_sub_get(&ctx, get->sig_model_sub_get.element_addr, - get->sig_model_sub_get.model_id)); + get->sig_model_sub_get.model_id)); case ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_SUB_GET: return (cb->error_code = bt_mesh_cfg_mod_sub_get_vnd(&ctx, get->vnd_model_sub_get.element_addr, - get->vnd_model_sub_get.model_id, get->vnd_model_sub_get.company_id)); + get->vnd_model_sub_get.model_id, get->vnd_model_sub_get.company_id)); case ESP_BLE_MESH_MODEL_OP_NET_KEY_GET: return (cb->error_code = bt_mesh_cfg_net_key_get(&ctx)); case ESP_BLE_MESH_MODEL_OP_APP_KEY_GET: @@ -422,11 +427,11 @@ static int btc_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param case ESP_BLE_MESH_MODEL_OP_SIG_MODEL_APP_GET: return (cb->error_code = bt_mesh_cfg_mod_app_get(&ctx, get->sig_model_app_get.element_addr, - get->sig_model_app_get.model_id)); + get->sig_model_app_get.model_id)); case ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_APP_GET: return (cb->error_code = bt_mesh_cfg_mod_app_get_vnd(&ctx, get->vnd_model_app_get.element_addr, - get->vnd_model_app_get.model_id, get->vnd_model_app_get.company_id)); + get->vnd_model_app_get.model_id, get->vnd_model_app_get.company_id)); case ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_GET: return (cb->error_code = bt_mesh_cfg_kr_phase_get(&ctx, get->kr_phase_get.net_idx)); case ESP_BLE_MESH_MODEL_OP_LPN_POLLTIMEOUT_GET: @@ -475,16 +480,16 @@ static int btc_ble_mesh_config_client_set_state(esp_ble_mesh_client_common_param case ESP_BLE_MESH_MODEL_OP_NET_KEY_ADD: return (cb->error_code = bt_mesh_cfg_net_key_add(&ctx, set->net_key_add.net_idx, - &set->net_key_add.net_key[0])); + &set->net_key_add.net_key[0])); case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: return (cb->error_code = bt_mesh_cfg_app_key_add(&ctx, set->app_key_add.net_idx, - set->app_key_add.app_idx, &set->app_key_add.app_key[0])); + set->app_key_add.app_idx, &set->app_key_add.app_key[0])); case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: return (cb->error_code = bt_mesh_cfg_mod_app_bind(&ctx, set->model_app_bind.element_addr, - set->model_app_bind.model_app_idx, set->model_app_bind.model_id, - set->model_app_bind.company_id)); + set->model_app_bind.model_app_idx, set->model_app_bind.model_id, + set->model_app_bind.company_id)); case ESP_BLE_MESH_MODEL_OP_MODEL_PUB_SET: { struct bt_mesh_cfg_mod_pub model_pub = { .addr = set->model_pub_set.publish_addr, @@ -496,46 +501,46 @@ static int btc_ble_mesh_config_client_set_state(esp_ble_mesh_client_common_param }; return (cb->error_code = bt_mesh_cfg_mod_pub_set(&ctx, set->model_pub_set.element_addr, - set->model_pub_set.model_id, set->model_pub_set.company_id, &model_pub)); + set->model_pub_set.model_id, set->model_pub_set.company_id, &model_pub)); } case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD: return (cb->error_code = bt_mesh_cfg_mod_sub_add(&ctx, set->model_sub_add.element_addr, - set->model_sub_add.sub_addr, set->model_sub_add.model_id, - set->model_sub_add.company_id)); + set->model_sub_add.sub_addr, set->model_sub_add.model_id, + set->model_sub_add.company_id)); case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE: return (cb->error_code = bt_mesh_cfg_mod_sub_del(&ctx, set->model_sub_delete.element_addr, - set->model_sub_delete.sub_addr, set->model_sub_delete.model_id, - set->model_sub_delete.company_id)); + set->model_sub_delete.sub_addr, set->model_sub_delete.model_id, + set->model_sub_delete.company_id)); case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_OVERWRITE: return (cb->error_code = bt_mesh_cfg_mod_sub_overwrite(&ctx, set->model_sub_overwrite.element_addr, - set->model_sub_overwrite.sub_addr, set->model_sub_overwrite.model_id, - set->model_sub_overwrite.company_id)); + set->model_sub_overwrite.sub_addr, set->model_sub_overwrite.model_id, + set->model_sub_overwrite.company_id)); case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_ADD: return (cb->error_code = bt_mesh_cfg_mod_sub_va_add(&ctx, set->model_sub_va_add.element_addr, - &set->model_sub_va_add.label_uuid[0], set->model_sub_va_add.model_id, - set->model_sub_va_add.company_id)); + &set->model_sub_va_add.label_uuid[0], set->model_sub_va_add.model_id, + set->model_sub_va_add.company_id)); case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_OVERWRITE: return (cb->error_code = bt_mesh_cfg_mod_sub_va_overwrite(&ctx, set->model_sub_va_overwrite.element_addr, - &set->model_sub_va_overwrite.label_uuid[0], set->model_sub_va_overwrite.model_id, - set->model_sub_va_overwrite.company_id)); + &set->model_sub_va_overwrite.label_uuid[0], set->model_sub_va_overwrite.model_id, + set->model_sub_va_overwrite.company_id)); case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_DELETE: return (cb->error_code = bt_mesh_cfg_mod_sub_va_del(&ctx, set->model_sub_va_delete.element_addr, - &set->model_sub_va_delete.label_uuid[0], set->model_sub_va_delete.model_id, - set->model_sub_va_delete.company_id)); + &set->model_sub_va_delete.label_uuid[0], set->model_sub_va_delete.model_id, + set->model_sub_va_delete.company_id)); case ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_SET: return (cb->error_code = bt_mesh_cfg_hb_sub_set(&ctx, - (struct bt_mesh_cfg_hb_sub *)&set->heartbeat_sub_set)); + (struct bt_mesh_cfg_hb_sub *)&set->heartbeat_sub_set)); case ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_SET: return (cb->error_code = bt_mesh_cfg_hb_pub_set(&ctx, - (const struct bt_mesh_cfg_hb_pub *)&set->heartbeat_pub_set)); + (const struct bt_mesh_cfg_hb_pub *)&set->heartbeat_pub_set)); case ESP_BLE_MESH_MODEL_OP_NODE_RESET: return (cb->error_code = bt_mesh_cfg_node_reset(&ctx)); case ESP_BLE_MESH_MODEL_OP_MODEL_PUB_VIRTUAL_ADDR_SET: { @@ -548,41 +553,41 @@ static int btc_ble_mesh_config_client_set_state(esp_ble_mesh_client_common_param }; return (cb->error_code = bt_mesh_cfg_mod_pub_va_set(&ctx, set->model_pub_va_set.element_addr, - set->model_pub_va_set.model_id, set->model_pub_va_set.company_id, - set->model_pub_va_set.label_uuid, &model_pub)); + set->model_pub_va_set.model_id, set->model_pub_va_set.company_id, + set->model_pub_va_set.label_uuid, &model_pub)); } case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE_ALL: return (cb->error_code = bt_mesh_cfg_mod_sub_del_all(&ctx, set->model_sub_delete_all.element_addr, - set->model_sub_delete_all.model_id, set->model_sub_delete_all.company_id)); + set->model_sub_delete_all.model_id, set->model_sub_delete_all.company_id)); case ESP_BLE_MESH_MODEL_OP_NET_KEY_UPDATE: return (cb->error_code = bt_mesh_cfg_net_key_update(&ctx, set->net_key_update.net_idx, - set->net_key_update.net_key)); + set->net_key_update.net_key)); case ESP_BLE_MESH_MODEL_OP_NET_KEY_DELETE: return (cb->error_code = bt_mesh_cfg_net_key_delete(&ctx, set->net_key_delete.net_idx)); case ESP_BLE_MESH_MODEL_OP_APP_KEY_UPDATE: return (cb->error_code = bt_mesh_cfg_app_key_update(&ctx, set->app_key_update.net_idx, - set->app_key_update.app_idx, set->app_key_update.app_key)); + set->app_key_update.app_idx, set->app_key_update.app_key)); case ESP_BLE_MESH_MODEL_OP_APP_KEY_DELETE: return (cb->error_code = bt_mesh_cfg_app_key_delete(&ctx, set->app_key_delete.net_idx, - set->app_key_delete.app_idx)); + set->app_key_delete.app_idx)); case ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_SET: return (cb->error_code = bt_mesh_cfg_node_identity_set(&ctx, set->node_identity_set.net_idx, - set->node_identity_set.identity)); + set->node_identity_set.identity)); case ESP_BLE_MESH_MODEL_OP_MODEL_APP_UNBIND: return (cb->error_code = bt_mesh_cfg_mod_app_unbind(&ctx, set->model_app_unbind.element_addr, - set->model_app_unbind.model_app_idx, set->model_app_unbind.model_id, - set->model_app_unbind.company_id)); + set->model_app_unbind.model_app_idx, set->model_app_unbind.model_id, + set->model_app_unbind.company_id)); case ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_SET: return (cb->error_code = bt_mesh_cfg_kr_phase_set(&ctx, set->kr_phase_set.net_idx, - set->kr_phase_set.transition)); + set->kr_phase_set.transition)); case ESP_BLE_MESH_MODEL_OP_NETWORK_TRANSMIT_SET: return (cb->error_code = bt_mesh_cfg_net_transmit_set(&ctx, set->net_transmit_set.net_transmit)); @@ -687,6 +692,11 @@ static void btc_ble_mesh_config_server_callback(esp_ble_mesh_cfg_server_cb_param LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_CONFIG_SERVER)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_CONFIG_SERVER; msg.act = act; @@ -709,8 +719,8 @@ void bt_mesh_config_server_cb_evt_to_btc(u8_t evt_type, } switch (evt_type) { - case BTC_BLE_MESH_EVT_CONFIG_SERVER_RECV_MSG: - act = ESP_BLE_MESH_CFG_SERVER_RECV_MSG_EVT; + case BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE: + act = ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT; break; default: LOG_ERROR("%s, Unknown config server event type %d", __func__, evt_type); @@ -726,8 +736,8 @@ void bt_mesh_config_server_cb_evt_to_btc(u8_t evt_type, cb_params.ctx.recv_dst = ctx->recv_dst; if (val && len) { - length = (len <= sizeof(cb_params.status_cb)) ? len : sizeof(cb_params.status_cb); - memcpy(&cb_params.status_cb, val, length); + length = (len <= sizeof(cb_params.value)) ? len : sizeof(cb_params.value); + memcpy(&cb_params.value, val, length); } btc_ble_mesh_config_server_callback(&cb_params, act); diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_generic_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_generic_model.c index a33ad6fca..a761c7722 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_generic_model.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_generic_model.c @@ -361,12 +361,17 @@ static void btc_ble_mesh_generic_client_callback(esp_ble_mesh_generic_client_cb_ LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_GENERIC_CLIENT)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GENERIC_CLIENT; msg.act = act; btc_transfer_context(&msg, cb_params, - sizeof(esp_ble_mesh_generic_client_cb_param_t), btc_ble_mesh_generic_client_copy_req_data); + sizeof(esp_ble_mesh_generic_client_cb_param_t), btc_ble_mesh_generic_client_copy_req_data); } void bt_mesh_generic_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, @@ -434,7 +439,7 @@ void btc_ble_mesh_generic_client_publish_callback(u32_t opcode, } bt_mesh_generic_client_cb_evt_to_btc(opcode, - BTC_BLE_MESH_EVT_GENERIC_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); + BTC_BLE_MESH_EVT_GENERIC_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); return; } @@ -473,7 +478,7 @@ void btc_ble_mesh_generic_client_call_handler(btc_msg_t *msg) cb.params = arg->generic_client_get_state.params; cb.error_code = bt_mesh_generic_client_get_state(&common, - (void *)arg->generic_client_get_state.get_state, (void *)&cb.status_cb); + (void *)arg->generic_client_get_state.get_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_generic_client_callback(&cb, ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT); @@ -499,7 +504,7 @@ void btc_ble_mesh_generic_client_call_handler(btc_msg_t *msg) cb.params = arg->generic_client_set_state.params; cb.error_code = bt_mesh_generic_client_set_state(&common, - (void *)arg->generic_client_set_state.set_state, (void *)&cb.status_cb); + (void *)arg->generic_client_set_state.set_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_generic_client_callback(&cb, ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT); @@ -534,3 +539,232 @@ void btc_ble_mesh_generic_client_cb_handler(btc_msg_t *msg) btc_ble_mesh_generic_client_free_req_data(msg); return; } + +/* Generic Server Models related functions */ + +static inline void btc_ble_mesh_generic_server_cb_to_app( + esp_ble_mesh_generic_server_cb_event_t event, + esp_ble_mesh_generic_server_cb_param_t *param) +{ + esp_ble_mesh_generic_server_cb_t btc_ble_mesh_cb = + (esp_ble_mesh_generic_server_cb_t)btc_profile_cb_get(BTC_PID_GENERIC_SERVER); + if (btc_ble_mesh_cb) { + btc_ble_mesh_cb(event, param); + } +} + +static void btc_ble_mesh_generic_server_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src) +{ + esp_ble_mesh_generic_server_cb_param_t *p_dest_data = (esp_ble_mesh_generic_server_cb_param_t *)p_dest; + esp_ble_mesh_generic_server_cb_param_t *p_src_data = (esp_ble_mesh_generic_server_cb_param_t *)p_src; + u16_t length; + + if (!msg || !p_src_data || !p_dest_data) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (msg->act) { + case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT: + switch (p_src_data->ctx.recv_op) { + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK: + if (p_src_data->value.state_change.user_property_set.value) { + length = p_src_data->value.state_change.user_property_set.value->len; + p_dest_data->value.state_change.user_property_set.value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.user_property_set.value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.user_property_set.value, + p_src_data->value.state_change.user_property_set.value->data, + p_src_data->value.state_change.user_property_set.value->len); + } + break; + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK: + if (p_src_data->value.state_change.admin_property_set.value) { + length = p_src_data->value.state_change.admin_property_set.value->len; + p_dest_data->value.state_change.admin_property_set.value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.admin_property_set.value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.admin_property_set.value, + p_src_data->value.state_change.admin_property_set.value->data, + p_src_data->value.state_change.admin_property_set.value->len); + } + break; + default: + break; + } + break; + case ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT: + switch (p_src_data->ctx.recv_op) { + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK: + if (p_src_data->value.set.user_property.property_value) { + length = p_src_data->value.set.user_property.property_value->len; + p_dest_data->value.set.user_property.property_value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.set.user_property.property_value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.set.user_property.property_value, + p_src_data->value.set.user_property.property_value->data, + p_src_data->value.set.user_property.property_value->len); + } + break; + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK: + if (p_src_data->value.set.admin_property.property_value) { + length = p_src_data->value.set.admin_property.property_value->len; + p_dest_data->value.set.admin_property.property_value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.set.admin_property.property_value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.set.admin_property.property_value, + p_src_data->value.set.admin_property.property_value->data, + p_src_data->value.set.admin_property.property_value->len); + } + break; + default: + break; + } + break; + default: + break; + } +} + +static void btc_ble_mesh_generic_server_free_req_data(btc_msg_t *msg) +{ + esp_ble_mesh_generic_server_cb_param_t *arg = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + arg = (esp_ble_mesh_generic_server_cb_param_t *)(msg->arg); + + switch (msg->act) { + case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT: + switch (arg->ctx.recv_op) { + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK: + bt_mesh_free_buf(arg->value.state_change.user_property_set.value); + break; + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK: + bt_mesh_free_buf(arg->value.state_change.admin_property_set.value); + break; + default: + break; + } + break; + case ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT: + switch (arg->ctx.recv_op) { + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK: + bt_mesh_free_buf(arg->value.set.user_property.property_value); + break; + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET: + case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK: + bt_mesh_free_buf(arg->value.set.admin_property.property_value); + break; + default: + break; + } + break; + default: + break; + } +} + +static void btc_ble_mesh_generic_server_callback(esp_ble_mesh_generic_server_cb_param_t *cb_params, uint8_t act) +{ + btc_msg_t msg = {0}; + + LOG_DEBUG("%s", __func__); + + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_GENERIC_SERVER)) { + return; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GENERIC_SERVER; + msg.act = act; + + btc_transfer_context(&msg, cb_params, + sizeof(esp_ble_mesh_generic_server_cb_param_t), btc_ble_mesh_generic_server_copy_req_data); +} + +void bt_mesh_generic_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len) +{ + esp_ble_mesh_generic_server_cb_param_t cb_params = {0}; + size_t length; + uint8_t act; + + if (model == NULL || ctx == NULL) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (evt_type) { + case BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE: + act = ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT; + break; + case BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG: + act = ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT; + break; + case BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG: + act = ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT; + break; + default: + LOG_ERROR("%s, Unknown Generic Server event type", __func__); + return; + } + + cb_params.model = (esp_ble_mesh_model_t *)model; + cb_params.ctx.net_idx = ctx->net_idx; + cb_params.ctx.app_idx = ctx->app_idx; + cb_params.ctx.addr = ctx->addr; + cb_params.ctx.recv_ttl = ctx->recv_ttl; + cb_params.ctx.recv_op = ctx->recv_op; + cb_params.ctx.recv_dst = ctx->recv_dst; + + if (val && len) { + length = (len <= sizeof(cb_params.value)) ? len : sizeof(cb_params.value); + memcpy(&cb_params.value, val, length); + } + + btc_ble_mesh_generic_server_callback(&cb_params, act); + return; +} + +void btc_ble_mesh_generic_server_cb_handler(btc_msg_t *msg) +{ + esp_ble_mesh_generic_server_cb_param_t *param = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + param = (esp_ble_mesh_generic_server_cb_param_t *)(msg->arg); + + if (msg->act < ESP_BLE_MESH_GENERIC_SERVER_EVT_MAX) { + btc_ble_mesh_generic_server_cb_to_app(msg->act, param); + } else { + LOG_ERROR("%s, Unknown msg->act = %d", __func__, msg->act); + } + + btc_ble_mesh_generic_server_free_req_data(msg); + return; +} diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_health_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_health_model.c index c728f135e..ab8ef2f12 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_health_model.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_health_model.c @@ -229,12 +229,17 @@ static void btc_ble_mesh_health_client_callback(esp_ble_mesh_health_client_cb_pa LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_HEALTH_CLIENT)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_HEALTH_CLIENT; msg.act = act; btc_transfer_context(&msg, cb_params, - sizeof(esp_ble_mesh_health_client_cb_param_t), btc_ble_mesh_health_client_copy_req_data); + sizeof(esp_ble_mesh_health_client_cb_param_t), btc_ble_mesh_health_client_copy_req_data); } void bt_mesh_health_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, @@ -302,7 +307,7 @@ void btc_ble_mesh_health_publish_callback(u32_t opcode, } bt_mesh_health_client_cb_evt_to_btc(opcode, - BTC_BLE_MESH_EVT_HEALTH_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); + BTC_BLE_MESH_EVT_HEALTH_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); return; } @@ -415,7 +420,7 @@ void btc_ble_mesh_health_client_call_handler(btc_msg_t *msg) break; } btc_ble_mesh_health_client_get_state(arg->health_client_get_state.params, - arg->health_client_get_state.get_state, &cb); + arg->health_client_get_state.get_state, &cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_health_client_callback(&cb, ESP_BLE_MESH_HEALTH_CLIENT_GET_STATE_EVT); @@ -431,7 +436,7 @@ void btc_ble_mesh_health_client_call_handler(btc_msg_t *msg) break; } btc_ble_mesh_health_client_set_state(arg->health_client_set_state.params, - arg->health_client_set_state.set_state, &cb); + arg->health_client_set_state.set_state, &cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_health_client_callback(&cb, ESP_BLE_MESH_HEALTH_CLIENT_SET_STATE_EVT); @@ -517,7 +522,7 @@ static void btc_ble_mesh_health_server_copy_req_data(btc_msg_t *msg, void *p_des } switch (msg->act) { - case ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMPLETE_EVT: + case ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMP_EVT: break; default: break; @@ -532,7 +537,7 @@ static void btc_ble_mesh_health_server_free_req_data(btc_msg_t *msg) } switch (msg->act) { - case ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMPLETE_EVT: + case ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMP_EVT: break; default: break; @@ -545,17 +550,22 @@ static void btc_ble_mesh_health_server_callback(esp_ble_mesh_health_server_cb_pa LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_HEALTH_SERVER)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_HEALTH_SERVER; msg.act = act; btc_transfer_context(&msg, cb_params, - sizeof(esp_ble_mesh_health_server_cb_param_t), btc_ble_mesh_health_server_copy_req_data); + sizeof(esp_ble_mesh_health_server_cb_param_t), btc_ble_mesh_health_server_copy_req_data); } void btc_ble_mesh_health_server_call_handler(btc_msg_t *msg) { - esp_ble_mesh_health_server_cb_param_t health_server_cb = {0}; + esp_ble_mesh_health_server_cb_param_t param = {0}; btc_ble_mesh_health_server_args_t *arg = NULL; if (!msg || !msg->arg) { @@ -567,10 +577,10 @@ void btc_ble_mesh_health_server_call_handler(btc_msg_t *msg) switch (msg->act) { case BTC_BLE_MESH_ACT_HEALTH_SERVER_FAULT_UPDATE: - health_server_cb.error_code = - bt_mesh_fault_update((struct bt_mesh_elem *)arg->fault_update.element); - btc_ble_mesh_health_server_callback( - &health_server_cb, ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMPLETE_EVT); + param.fault_update_comp.element = arg->health_fault_update.element; + param.fault_update_comp.error_code = + bt_mesh_fault_update((struct bt_mesh_elem *)arg->health_fault_update.element); + btc_ble_mesh_health_server_callback(¶m, ESP_BLE_MESH_HEALTH_SERVER_FAULT_UPDATE_COMP_EVT); break; default: break; @@ -600,3 +610,43 @@ void btc_ble_mesh_health_server_cb_handler(btc_msg_t *msg) btc_ble_mesh_health_server_free_req_data(msg); return; } + +void btc_ble_mesh_health_server_fault_clear(struct bt_mesh_model *model, u16_t company_id) +{ + esp_ble_mesh_health_server_cb_param_t param = {0}; + + param.fault_clear.model = (esp_ble_mesh_model_t *)model; + param.fault_clear.company_id = company_id; + + btc_ble_mesh_health_server_callback(¶m, ESP_BLE_MESH_HEALTH_SERVER_FAULT_CLEAR_EVT); +} + +void btc_ble_mesh_health_server_fault_test(struct bt_mesh_model *model, u8_t test_id, u16_t company_id) +{ + esp_ble_mesh_health_server_cb_param_t param = {0}; + + param.fault_test.model = (esp_ble_mesh_model_t *)model; + param.fault_test.test_id = test_id; + param.fault_test.company_id = company_id; + + btc_ble_mesh_health_server_callback(¶m, ESP_BLE_MESH_HEALTH_SERVER_FAULT_TEST_EVT); +} + +void btc_ble_mesh_health_server_attention_on(struct bt_mesh_model *model, u8_t time) +{ + esp_ble_mesh_health_server_cb_param_t param = {0}; + + param.attention_on.model = (esp_ble_mesh_model_t *)model; + param.attention_on.time = time; + + btc_ble_mesh_health_server_callback(¶m, ESP_BLE_MESH_HEALTH_SERVER_ATTENTION_ON_EVT); +} + +void btc_ble_mesh_health_server_attention_off(struct bt_mesh_model *model) +{ + esp_ble_mesh_health_server_cb_param_t param = {0}; + + param.attention_off.model = (esp_ble_mesh_model_t *)model; + + btc_ble_mesh_health_server_callback(¶m, ESP_BLE_MESH_HEALTH_SERVER_ATTENTION_OFF_EVT); +} diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_lighting_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_lighting_model.c index 9d75fbd97..b0c4d9f29 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_lighting_model.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_lighting_model.c @@ -205,12 +205,17 @@ static void btc_ble_mesh_lighting_client_callback(esp_ble_mesh_light_client_cb_p LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_LIGHTING_CLIENT)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_LIGHTING_CLIENT; msg.act = act; btc_transfer_context(&msg, cb_params, - sizeof(esp_ble_mesh_light_client_cb_param_t), btc_ble_mesh_lighting_client_copy_req_data); + sizeof(esp_ble_mesh_light_client_cb_param_t), btc_ble_mesh_lighting_client_copy_req_data); } void bt_mesh_lighting_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, @@ -278,7 +283,7 @@ void btc_ble_mesh_lighting_client_publish_callback(u32_t opcode, } bt_mesh_lighting_client_cb_evt_to_btc(opcode, - BTC_BLE_MESH_EVT_LIGHTING_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); + BTC_BLE_MESH_EVT_LIGHTING_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); return; } @@ -317,7 +322,7 @@ void btc_ble_mesh_lighting_client_call_handler(btc_msg_t *msg) cb.params = arg->light_client_get_state.params; cb.error_code = bt_mesh_light_client_get_state(&common, - (void *)arg->light_client_get_state.get_state, (void *)&cb.status_cb); + (void *)arg->light_client_get_state.get_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_lighting_client_callback(&cb, ESP_BLE_MESH_LIGHT_CLIENT_GET_STATE_EVT); @@ -343,7 +348,7 @@ void btc_ble_mesh_lighting_client_call_handler(btc_msg_t *msg) cb.params = arg->light_client_set_state.params; cb.error_code = bt_mesh_light_client_set_state(&common, - (void *)arg->light_client_set_state.set_state, (void *)&cb.status_cb); + (void *)arg->light_client_set_state.set_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_lighting_client_callback(&cb, ESP_BLE_MESH_LIGHT_CLIENT_SET_STATE_EVT); @@ -379,3 +384,202 @@ void btc_ble_mesh_lighting_client_cb_handler(btc_msg_t *msg) return; } +/* Lighting Server Models related functions */ + +static inline void btc_ble_mesh_lighting_server_cb_to_app( + esp_ble_mesh_lighting_server_cb_event_t event, + esp_ble_mesh_lighting_server_cb_param_t *param) +{ + esp_ble_mesh_lighting_server_cb_t btc_ble_mesh_cb = + (esp_ble_mesh_lighting_server_cb_t)btc_profile_cb_get(BTC_PID_LIGHTING_SERVER); + if (btc_ble_mesh_cb) { + btc_ble_mesh_cb(event, param); + } +} + +static void btc_ble_mesh_lighting_server_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src) +{ + esp_ble_mesh_lighting_server_cb_param_t *p_dest_data = (esp_ble_mesh_lighting_server_cb_param_t *)p_dest; + esp_ble_mesh_lighting_server_cb_param_t *p_src_data = (esp_ble_mesh_lighting_server_cb_param_t *)p_src; + u16_t length; + + if (!msg || !p_src_data || !p_dest_data) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (msg->act) { + case ESP_BLE_MESH_LIGHTING_SERVER_STATE_CHANGE_EVT: + if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET || + p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK) { + if (p_src_data->value.state_change.lc_property_set.property_value) { + length = p_src_data->value.state_change.lc_property_set.property_value->len; + p_dest_data->value.state_change.lc_property_set.property_value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.lc_property_set.property_value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.lc_property_set.property_value, + p_src_data->value.state_change.lc_property_set.property_value->data, + p_src_data->value.state_change.lc_property_set.property_value->len); + } + } + break; + case ESP_BLE_MESH_LIGHTING_SERVER_RECV_SET_MSG_EVT: + if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET || + p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK) { + if (p_src_data->value.set.lc_property.property_value) { + length = p_src_data->value.set.lc_property.property_value->len; + p_dest_data->value.set.lc_property.property_value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.set.lc_property.property_value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.set.lc_property.property_value, + p_src_data->value.set.lc_property.property_value->data, + p_src_data->value.set.lc_property.property_value->len); + } + } + break; + case ESP_BLE_MESH_LIGHTING_SERVER_RECV_STATUS_MSG_EVT: + if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS) { + if (p_src_data->value.status.sensor_status.data) { + length = p_src_data->value.status.sensor_status.data->len; + p_dest_data->value.status.sensor_status.data = bt_mesh_alloc_buf(length); + if (p_dest_data->value.status.sensor_status.data == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.status.sensor_status.data, + p_src_data->value.status.sensor_status.data->data, + p_src_data->value.status.sensor_status.data->len); + } + } + break; + default: + break; + } +} + +static void btc_ble_mesh_lighting_server_free_req_data(btc_msg_t *msg) +{ + esp_ble_mesh_lighting_server_cb_param_t *arg = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + arg = (esp_ble_mesh_lighting_server_cb_param_t *)(msg->arg); + + switch (msg->act) { + case ESP_BLE_MESH_LIGHTING_SERVER_STATE_CHANGE_EVT: + if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET || + arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK) { + bt_mesh_free_buf(arg->value.state_change.lc_property_set.property_value); + } + break; + case ESP_BLE_MESH_LIGHTING_SERVER_RECV_SET_MSG_EVT: + if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET || + arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK) { + bt_mesh_free_buf(arg->value.set.lc_property.property_value); + } + break; + case ESP_BLE_MESH_LIGHTING_SERVER_RECV_STATUS_MSG_EVT: + if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS) { + bt_mesh_free_buf(arg->value.status.sensor_status.data); + } + break; + default: + break; + } +} + +static void btc_ble_mesh_lighting_server_callback(esp_ble_mesh_lighting_server_cb_param_t *cb_params, uint8_t act) +{ + btc_msg_t msg = {0}; + + LOG_DEBUG("%s", __func__); + + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_LIGHTING_SERVER)) { + return; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_LIGHTING_SERVER; + msg.act = act; + + btc_transfer_context( + &msg, cb_params, sizeof(esp_ble_mesh_lighting_server_cb_param_t), btc_ble_mesh_lighting_server_copy_req_data); +} + +void bt_mesh_lighting_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len) +{ + esp_ble_mesh_lighting_server_cb_param_t cb_params = {0}; + size_t length; + uint8_t act; + + if (model == NULL || ctx == NULL) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (evt_type) { + case BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE: + act = ESP_BLE_MESH_LIGHTING_SERVER_STATE_CHANGE_EVT; + break; + case BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG: + act = ESP_BLE_MESH_LIGHTING_SERVER_RECV_GET_MSG_EVT; + break; + case BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG: + act = ESP_BLE_MESH_LIGHTING_SERVER_RECV_SET_MSG_EVT; + break; + case BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_STATUS_MSG: + act = ESP_BLE_MESH_LIGHTING_SERVER_RECV_STATUS_MSG_EVT; + break; + default: + LOG_ERROR("%s, Unknown Lighting Server event type", __func__); + return; + } + + cb_params.model = (esp_ble_mesh_model_t *)model; + cb_params.ctx.net_idx = ctx->net_idx; + cb_params.ctx.app_idx = ctx->app_idx; + cb_params.ctx.addr = ctx->addr; + cb_params.ctx.recv_ttl = ctx->recv_ttl; + cb_params.ctx.recv_op = ctx->recv_op; + cb_params.ctx.recv_dst = ctx->recv_dst; + + if (val && len) { + length = (len <= sizeof(cb_params.value)) ? len : sizeof(cb_params.value); + memcpy(&cb_params.value, val, length); + } + + btc_ble_mesh_lighting_server_callback(&cb_params, act); + return; +} + +void btc_ble_mesh_lighting_server_cb_handler(btc_msg_t *msg) +{ + esp_ble_mesh_lighting_server_cb_param_t *param = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + param = (esp_ble_mesh_lighting_server_cb_param_t *)(msg->arg); + + if (msg->act < ESP_BLE_MESH_LIGHTING_SERVER_EVT_MAX) { + btc_ble_mesh_lighting_server_cb_to_app(msg->act, param); + } else { + LOG_ERROR("%s, Unknown msg->act = %d", __func__, msg->act); + } + + btc_ble_mesh_lighting_server_free_req_data(msg); + return; +} \ No newline at end of file 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 2dd68e2a4..415a543a0 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 @@ -31,12 +31,15 @@ #include "mesh_proxy.h" #include "cfg_cli.h" #include "health_cli.h" +#include "cfg_srv.h" +#include "health_srv.h" #include "mesh.h" #include "access.h" #include "transport.h" -#include "proxy.h" +#include "proxy_server.h" #include "prov.h" +#include "proxy_client.h" #include "provisioner_prov.h" #include "provisioner_main.h" @@ -45,6 +48,7 @@ #include "sensor_client.h" #include "time_scene_client.h" #include "client_common.h" +#include "state_binding.h" #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_config_model.h" @@ -80,6 +84,70 @@ static inline void btc_ble_mesh_model_cb_to_app(esp_ble_mesh_model_cb_event_t ev } void btc_ble_mesh_prov_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_ble_mesh_prov_args_t *dst = (btc_ble_mesh_prov_args_t *)p_dest; + btc_ble_mesh_prov_args_t *src = (btc_ble_mesh_prov_args_t *)p_src; + + if (!msg || !dst || !src) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (msg->act) { + case BTC_BLE_MESH_ACT_PROXY_CLIENT_ADD_FILTER_ADDR: + LOG_DEBUG("%s, BTC_BLE_MESH_ACT_PROXY_CLIENT_ADD_FILTER_ADDR", __func__); + dst->proxy_client_add_filter_addr.addr = (uint16_t *)osi_calloc(src->proxy_client_add_filter_addr.addr_num << 1); + if (dst->proxy_client_add_filter_addr.addr) { + memcpy(dst->proxy_client_add_filter_addr.addr, src->proxy_client_add_filter_addr.addr, + src->proxy_client_add_filter_addr.addr_num << 1); + } else { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + } + break; + case BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR: + LOG_DEBUG("%s, BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR", __func__); + dst->proxy_client_remove_filter_addr.addr = osi_calloc(src->proxy_client_remove_filter_addr.addr_num << 1); + if (dst->proxy_client_remove_filter_addr.addr) { + memcpy(dst->proxy_client_remove_filter_addr.addr, src->proxy_client_remove_filter_addr.addr, + src->proxy_client_remove_filter_addr.addr_num << 1); + } else { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + } + break; + default: + LOG_DEBUG("%s, Unknown deep copy act %d", __func__, msg->act); + break; + } +} + +static void btc_ble_mesh_prov_arg_deep_free(btc_msg_t *msg) +{ + btc_ble_mesh_prov_args_t *arg = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + arg = (btc_ble_mesh_prov_args_t *)(msg->arg); + + switch (msg->act) { + case BTC_BLE_MESH_ACT_PROXY_CLIENT_ADD_FILTER_ADDR: + if (arg->proxy_client_add_filter_addr.addr) { + osi_free(arg->proxy_client_add_filter_addr.addr); + } + break; + case BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR: + if (arg->proxy_client_remove_filter_addr.addr) { + osi_free(arg->proxy_client_remove_filter_addr.addr); + } + break; + default: + break; + } +} + +void btc_ble_mesh_model_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) { btc_ble_mesh_model_args_t *dst = (btc_ble_mesh_model_args_t *)p_dest; btc_ble_mesh_model_args_t *src = (btc_ble_mesh_model_args_t *)p_src; @@ -109,13 +177,23 @@ void btc_ble_mesh_prov_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } + case BTC_BLE_MESH_ACT_SERVER_MODEL_UPDATE_STATE: + LOG_DEBUG("%s, BTC_BLE_MESH_ACT_SERVER_MODEL_UPDATE_STATE", __func__); + dst->model_update_state.value = osi_malloc(sizeof(esp_ble_mesh_server_state_value_t)); + if (dst->model_update_state.value) { + memcpy(dst->model_update_state.value, src->model_update_state.value, + sizeof(esp_ble_mesh_server_state_value_t)); + } else { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + } + break; default: LOG_DEBUG("%s, Unknown deep copy act %d", __func__, msg->act); break; } } -static void btc_ble_mesh_prov_arg_deep_free(btc_msg_t *msg) +static void btc_ble_mesh_model_arg_deep_free(btc_msg_t *msg) { btc_ble_mesh_model_args_t *arg = NULL; @@ -136,6 +214,11 @@ static void btc_ble_mesh_prov_arg_deep_free(btc_msg_t *msg) osi_free(arg->model_send.ctx); } break; + case BTC_BLE_MESH_ACT_SERVER_MODEL_UPDATE_STATE: + if (arg->model_update_state.value) { + osi_free(arg->model_update_state.value); + } + break; default: break; } @@ -266,13 +349,35 @@ static void btc_ble_mesh_model_free_req_data(btc_msg_t *msg) } } +static bt_status_t btc_ble_mesh_model_callback(esp_ble_mesh_model_cb_param_t *param, uint8_t act) +{ + btc_msg_t msg = {0}; + bt_status_t ret; + + LOG_DEBUG("%s", __func__); + + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_MODEL)) { + return BT_STATUS_SUCCESS; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_MODEL; + msg.act = act; + + ret = btc_transfer_context(&msg, param, + sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data); + if (ret != BT_STATUS_SUCCESS) { + LOG_ERROR("%s, btc_transfer_context failed", __func__); + } + return ret; +} + static void btc_ble_mesh_server_model_op_cb(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { esp_ble_mesh_model_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; mesh_param.model_operation.opcode = ctx->recv_op; mesh_param.model_operation.model = (esp_ble_mesh_model_t *)model; @@ -280,15 +385,7 @@ static void btc_ble_mesh_server_model_op_cb(struct bt_mesh_model *model, mesh_param.model_operation.length = buf->len; mesh_param.model_operation.msg = buf->data; - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_MODEL; - msg.act = ESP_BLE_MESH_MODEL_OPERATION_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } + btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_MODEL_OPERATION_EVT); return; } @@ -298,8 +395,6 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model, { esp_ble_mesh_model_cb_param_t mesh_param = {0}; bt_mesh_client_node_t *node = NULL; - btc_msg_t msg = {0}; - bt_status_t ret; if (!model || !model->user_data || !ctx || !buf) { LOG_ERROR("%s, Invalid parameter", __func__); @@ -308,284 +403,28 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model, bt_mesh_client_model_lock(); - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_MODEL; - node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, false); if (node == NULL) { - msg.act = ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT; mesh_param.client_recv_publish_msg.opcode = ctx->recv_op; mesh_param.client_recv_publish_msg.model = (esp_ble_mesh_model_t *)model; mesh_param.client_recv_publish_msg.ctx = (esp_ble_mesh_msg_ctx_t *)ctx; mesh_param.client_recv_publish_msg.length = buf->len; mesh_param.client_recv_publish_msg.msg = buf->data; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data); + btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT); } else { - msg.act = ESP_BLE_MESH_MODEL_OPERATION_EVT; mesh_param.model_operation.opcode = ctx->recv_op; mesh_param.model_operation.model = (esp_ble_mesh_model_t *)model; mesh_param.model_operation.ctx = (esp_ble_mesh_msg_ctx_t *)ctx; mesh_param.model_operation.length = buf->len; mesh_param.model_operation.msg = buf->data; if (!k_delayed_work_free(&node->timer)) { - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data); + btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_MODEL_OPERATION_EVT); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); - } else { - ret = BT_STATUS_SUCCESS; } } bt_mesh_client_model_unlock(); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s, btc_transfer_context failed", __func__); - } - return; -} - -static void btc_ble_mesh_model_send_comp_cb(esp_ble_mesh_model_t *model, esp_ble_mesh_msg_ctx_t *ctx, u32_t opcode, int err) -{ - esp_ble_mesh_model_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - mesh_param.model_send_comp.err_code = err; - mesh_param.model_send_comp.opcode = opcode; - mesh_param.model_send_comp.model = model; - mesh_param.model_send_comp.ctx = ctx; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_MODEL; - msg.act = ESP_BLE_MESH_MODEL_SEND_COMP_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - return; -} - -static void btc_ble_mesh_model_publish_comp_cb(esp_ble_mesh_model_t *model, int err) -{ - esp_ble_mesh_model_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - mesh_param.model_publish_comp.err_code = err; - mesh_param.model_publish_comp.model = model; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_MODEL; - msg.act = ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_model_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - return; -} - -#if CONFIG_BLE_MESH_NODE -static void btc_ble_mesh_oob_pub_key_cb(void) -{ - btc_msg_t msg = {0}; - - LOG_DEBUG("%s", __func__); - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_OOB_PUB_KEY_EVT; - - if (btc_transfer_context(&msg, NULL, 0, NULL) != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - return; -} - -static int btc_ble_mesh_output_number_cb(bt_mesh_output_action_t act, u32_t num) -{ - esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - mesh_param.node_prov_output_num.action = (esp_ble_mesh_output_action_t)act; - mesh_param.node_prov_output_num.number = num; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - return -1; - } - return 0; -} - -static int btc_ble_mesh_output_string_cb(const char *str) -{ - esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - strncpy(mesh_param.node_prov_output_str.string, str, strlen(str)); - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - return -1; - } - return 0; -} - -static int btc_ble_mesh_input_cb(bt_mesh_input_action_t act, u8_t size) -{ - esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - mesh_param.node_prov_input.action = (esp_ble_mesh_input_action_t)act; - mesh_param.node_prov_input.size = size; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_INPUT_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - return -1; - } - return 0; -} - -static void btc_ble_mesh_link_open_cb(bt_mesh_prov_bearer_t bearer) -{ - esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - mesh_param.node_prov_link_open.bearer = (esp_ble_mesh_prov_bearer_t)bearer; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - return; -} - -static void btc_ble_mesh_link_close_cb(bt_mesh_prov_bearer_t bearer) -{ - esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - mesh_param.node_prov_link_close.bearer = (esp_ble_mesh_prov_bearer_t)bearer; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - return; -} - -static void btc_ble_mesh_complete_cb(u16_t net_idx, const u8_t net_key[16], u16_t addr, u8_t flags, u32_t iv_index) -{ - esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - mesh_param.node_prov_complete.net_idx = net_idx; - memcpy(mesh_param.node_prov_complete.net_key, net_key, 16); - mesh_param.node_prov_complete.addr = addr; - mesh_param.node_prov_complete.flags = flags; - mesh_param.node_prov_complete.iv_index = iv_index; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - return; -} - -static void btc_ble_mesh_reset_cb(void) -{ - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_NODE_PROV_RESET_EVT; - ret = btc_transfer_context(&msg, NULL, 0, NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - return; -} -#endif /* CONFIG_BLE_MESH_NODE */ - -static void btc_ble_mesh_prov_register_complete_cb(int err_code) -{ - esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; - - LOG_DEBUG("%s", __func__); - - mesh_param.prov_register_comp.err_code = err_code; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROV_REGISTER_COMP_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } return; } @@ -594,8 +433,6 @@ static void btc_ble_mesh_client_model_timeout_cb(struct k_work *work) esp_ble_mesh_model_cb_param_t mesh_param = {0}; struct k_delayed_work *timer = NULL; bt_mesh_client_node_t *node = NULL; - btc_msg_t msg = {0}; - bt_status_t ret; bt_mesh_client_model_lock(); @@ -607,83 +444,220 @@ static void btc_ble_mesh_client_model_timeout_cb(struct k_work *work) mesh_param.client_send_timeout.opcode = node->opcode; mesh_param.client_send_timeout.model = (esp_ble_mesh_model_t *)node->ctx.model; mesh_param.client_send_timeout.ctx = (esp_ble_mesh_msg_ctx_t *)&node->ctx; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_MODEL; - msg.act = ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT; - - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data); - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } - + btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); } } bt_mesh_client_model_unlock(); + return; +} +static void btc_ble_mesh_model_send_comp_cb(esp_ble_mesh_model_t *model, esp_ble_mesh_msg_ctx_t *ctx, u32_t opcode, int err) +{ + esp_ble_mesh_model_cb_param_t mesh_param = {0}; + + mesh_param.model_send_comp.err_code = err; + mesh_param.model_send_comp.opcode = opcode; + mesh_param.model_send_comp.model = model; + mesh_param.model_send_comp.ctx = ctx; + + btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_MODEL_SEND_COMP_EVT); + return; +} + +static void btc_ble_mesh_model_publish_comp_cb(esp_ble_mesh_model_t *model, int err) +{ + esp_ble_mesh_model_cb_param_t mesh_param = {0}; + + mesh_param.model_publish_comp.err_code = err; + mesh_param.model_publish_comp.model = model; + + btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT); return; } static int btc_ble_mesh_model_publish_update(struct bt_mesh_model *mod) { esp_ble_mesh_model_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; bt_status_t ret; LOG_DEBUG("%s", __func__); mesh_param.model_publish_update.model = (esp_ble_mesh_model_t *)mod; - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_MODEL; - msg.act = ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_model_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - return -1; - } - return 0; + ret = btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT); + return (ret == BT_STATUS_SUCCESS) ? 0 : -1; } -static void btc_ble_mesh_prov_set_complete_cb(esp_ble_mesh_prov_cb_param_t *param, uint8_t act) +static void btc_ble_mesh_server_model_update_state_comp_cb(esp_ble_mesh_model_t *model, + esp_ble_mesh_server_state_type_t type, int err) +{ + esp_ble_mesh_model_cb_param_t mesh_param = {0}; + + mesh_param.server_model_update_state.err_code = err; + mesh_param.server_model_update_state.model = model; + mesh_param.server_model_update_state.type = type; + + btc_ble_mesh_model_callback(&mesh_param, ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_COMP_EVT); + return; +} + +static bt_status_t btc_ble_mesh_prov_callback(esp_ble_mesh_prov_cb_param_t *param, uint8_t act) { btc_msg_t msg = {0}; bt_status_t ret; LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_PROV)) { + return BT_STATUS_SUCCESS; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_PROV; msg.act = act; - ret = btc_transfer_context(&msg, param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); + ret = btc_transfer_context(&msg, param, sizeof(esp_ble_mesh_prov_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); + LOG_ERROR("%s, btc_transfer_context failed", __func__); } + return ret; +} + +#if CONFIG_BLE_MESH_NODE +static void btc_ble_mesh_oob_pub_key_cb(void) +{ + LOG_DEBUG("%s", __func__); + + btc_ble_mesh_prov_callback(NULL, ESP_BLE_MESH_NODE_PROV_OOB_PUB_KEY_EVT); + return; +} + +static int btc_ble_mesh_output_number_cb(bt_mesh_output_action_t act, u32_t num) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + bt_status_t ret; + + LOG_DEBUG("%s", __func__); + + mesh_param.node_prov_output_num.action = (esp_ble_mesh_output_action_t)act; + mesh_param.node_prov_output_num.number = num; + + ret = btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT); + return (ret == BT_STATUS_SUCCESS) ? 0 : -1; +} + +static int btc_ble_mesh_output_string_cb(const char *str) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + bt_status_t ret; + + LOG_DEBUG("%s", __func__); + + strncpy(mesh_param.node_prov_output_str.string, str, strlen(str)); + + ret = btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT); + return (ret == BT_STATUS_SUCCESS) ? 0 : -1; +} + +static int btc_ble_mesh_input_cb(bt_mesh_input_action_t act, u8_t size) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + bt_status_t ret; + + LOG_DEBUG("%s", __func__); + + mesh_param.node_prov_input.action = (esp_ble_mesh_input_action_t)act; + mesh_param.node_prov_input.size = size; + + ret = btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_NODE_PROV_INPUT_EVT); + return (ret == BT_STATUS_SUCCESS) ? 0 : -1; +} + +static void btc_ble_mesh_link_open_cb(bt_mesh_prov_bearer_t bearer) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + LOG_DEBUG("%s", __func__); + + mesh_param.node_prov_link_open.bearer = (esp_ble_mesh_prov_bearer_t)bearer; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT); + return; +} + +static void btc_ble_mesh_link_close_cb(bt_mesh_prov_bearer_t bearer) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + LOG_DEBUG("%s", __func__); + + mesh_param.node_prov_link_close.bearer = (esp_ble_mesh_prov_bearer_t)bearer; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT); + return; +} + +static void btc_ble_mesh_complete_cb(u16_t net_idx, const u8_t net_key[16], u16_t addr, u8_t flags, u32_t iv_index) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + LOG_DEBUG("%s", __func__); + + mesh_param.node_prov_complete.net_idx = net_idx; + memcpy(mesh_param.node_prov_complete.net_key, net_key, 16); + mesh_param.node_prov_complete.addr = addr; + mesh_param.node_prov_complete.flags = flags; + mesh_param.node_prov_complete.iv_index = iv_index; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT); + return; +} + +static void btc_ble_mesh_reset_cb(void) +{ + LOG_DEBUG("%s", __func__); + + btc_ble_mesh_prov_callback(NULL, ESP_BLE_MESH_NODE_PROV_RESET_EVT); + return; +} +#endif /* CONFIG_BLE_MESH_NODE */ + +static void btc_ble_mesh_prov_register_complete_cb(int err_code) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + LOG_DEBUG("%s", __func__); + + mesh_param.prov_register_comp.err_code = err_code; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROV_REGISTER_COMP_EVT); + return; +} + +static void btc_ble_mesh_prov_set_complete_cb(esp_ble_mesh_prov_cb_param_t *param, uint8_t act) +{ + LOG_DEBUG("%s", __func__); + + btc_ble_mesh_prov_callback(param, act); return; } #if CONFIG_BLE_MESH_PROVISIONER static void btc_ble_mesh_provisioner_recv_unprov_adv_pkt_cb( - const u8_t addr[6], const u8_t addr_type, - const u8_t adv_type, const u8_t dev_uuid[16], - u16_t oob_info, bt_mesh_prov_bearer_t bearer) + const u8_t addr[6], const u8_t addr_type, + const u8_t adv_type, const u8_t dev_uuid[16], + u16_t oob_info, bt_mesh_prov_bearer_t bearer) { esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; LOG_DEBUG("%s", __func__); if (addr == NULL || dev_uuid == NULL || - (bearer != BLE_MESH_PROV_ADV && bearer != BLE_MESH_PROV_GATT)) { + (bearer != BLE_MESH_PROV_ADV && bearer != BLE_MESH_PROV_GATT)) { LOG_ERROR("%s, Invalid parameter", __func__); return; } @@ -695,46 +669,27 @@ static void btc_ble_mesh_provisioner_recv_unprov_adv_pkt_cb( mesh_param.provisioner_recv_unprov_adv_pkt.adv_type = adv_type; mesh_param.provisioner_recv_unprov_adv_pkt.bearer = bearer; - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT); return; } static int btc_ble_mesh_provisioner_prov_read_oob_pub_key_cb(u8_t link_idx) { esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; bt_status_t ret; LOG_DEBUG("%s", __func__); mesh_param.provisioner_prov_read_oob_pub_key.link_idx = link_idx; - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROVISIONER_PROV_READ_OOB_PUB_KEY_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - return -1; - } - return 0; + ret = btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_PROV_READ_OOB_PUB_KEY_EVT); + return (ret == BT_STATUS_SUCCESS) ? 0 : -1; } static int btc_ble_mesh_provisioner_prov_input_cb(u8_t method, - bt_mesh_output_action_t act, u8_t size, u8_t link_idx) + bt_mesh_output_action_t act, u8_t size, u8_t link_idx) { esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; bt_status_t ret; LOG_DEBUG("%s", __func__); @@ -744,24 +699,14 @@ static int btc_ble_mesh_provisioner_prov_input_cb(u8_t method, mesh_param.provisioner_prov_input.size = size; mesh_param.provisioner_prov_input.link_idx = link_idx; - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROVISIONER_PROV_INPUT_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - return -1; - } - return 0; + ret = btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_PROV_INPUT_EVT); + return (ret == BT_STATUS_SUCCESS) ? 0 : -1; } static int btc_ble_mesh_provisioner_prov_output_cb(u8_t method, - bt_mesh_input_action_t act, void *data, u8_t size, u8_t link_idx) + bt_mesh_input_action_t act, void *data, u8_t size, u8_t link_idx) { esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; bt_status_t ret; LOG_DEBUG("%s", __func__); @@ -776,72 +721,41 @@ static int btc_ble_mesh_provisioner_prov_output_cb(u8_t method, mesh_param.provisioner_prov_output.number = sys_get_le32((u8_t *)data); } - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROVISIONER_PROV_OUTPUT_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - return -1; - } - return 0; + ret = btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_PROV_OUTPUT_EVT); + return (ret == BT_STATUS_SUCCESS) ? 0 : -1; } static void btc_ble_mesh_provisioner_link_open_cb(bt_mesh_prov_bearer_t bearer) { esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; LOG_DEBUG("%s", __func__); mesh_param.provisioner_prov_link_open.bearer = (esp_ble_mesh_prov_bearer_t)bearer; - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROVISIONER_PROV_LINK_OPEN_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_PROV_LINK_OPEN_EVT); return; } static void btc_ble_mesh_provisioner_link_close_cb(bt_mesh_prov_bearer_t bearer, u8_t reason) { esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; LOG_DEBUG("%s", __func__); mesh_param.provisioner_prov_link_close.bearer = (esp_ble_mesh_prov_bearer_t)bearer; mesh_param.provisioner_prov_link_close.reason = reason; - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT); return; } static void btc_ble_mesh_provisioner_prov_complete_cb( - int node_idx, const u8_t device_uuid[16], - u16_t unicast_addr, u8_t element_num, - u16_t netkey_idx) + int node_idx, const u8_t device_uuid[16], + u16_t unicast_addr, u8_t element_num, + u16_t netkey_idx) { esp_ble_mesh_prov_cb_param_t mesh_param = {0}; - btc_msg_t msg = {0}; - bt_status_t ret; LOG_DEBUG("%s", __func__); @@ -851,19 +765,162 @@ static void btc_ble_mesh_provisioner_prov_complete_cb( mesh_param.provisioner_prov_complete.netkey_idx = netkey_idx; memcpy(mesh_param.provisioner_prov_complete.device_uuid, device_uuid, sizeof(esp_ble_mesh_octet16_t)); - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_PROV; - msg.act = ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT; - ret = btc_transfer_context(&msg, &mesh_param, - sizeof(esp_ble_mesh_prov_cb_param_t), NULL); - - if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); - } + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT); return; } #endif /* CONFIG_BLE_MESH_PROVISIONER */ +static void btc_ble_mesh_heartbeat_msg_recv_cb(u8_t hops, u16_t feature) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + LOG_DEBUG("%s", __func__); + + mesh_param.heartbeat_msg_recv.hops = hops; + mesh_param.heartbeat_msg_recv.feature = feature; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_HEARTBEAT_MESSAGE_RECV_EVT); + return; +} + +#if CONFIG_BLE_MESH_NODE +#if CONFIG_BLE_MESH_LOW_POWER +static void btc_ble_mesh_lpn_cb(u16_t friend_addr, bool established) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + u8_t act; + + LOG_DEBUG("%s", __func__); + + if (established) { + mesh_param.lpn_friendship_establish.friend_addr = friend_addr; + act = ESP_BLE_MESH_LPN_FRIENDSHIP_ESTABLISH_EVT; + } else { + mesh_param.lpn_friendship_terminate.friend_addr = friend_addr; + act = ESP_BLE_MESH_LPN_FRIENDSHIP_TERMINATE_EVT; + } + + btc_ble_mesh_prov_callback(&mesh_param, act); + return; +} +#endif /* CONFIG_BLE_MESH_LOW_POWER */ + +#if CONFIG_BLE_MESH_FRIEND +void btc_ble_mesh_friend_cb(bool establish, u16_t lpn_addr, u8_t reason) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + u8_t act; + + LOG_DEBUG("%s", __func__); + + if (!BLE_MESH_ADDR_IS_UNICAST(lpn_addr)) { + LOG_ERROR("%s, Not a unicast address", __func__); + return; + } + + if (establish) { + mesh_param.frnd_friendship_establish.lpn_addr = lpn_addr; + act = ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT; + } else { + mesh_param.frnd_friendship_terminate.lpn_addr = lpn_addr; + mesh_param.frnd_friendship_terminate.reason = reason; + act = ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT; + } + + btc_ble_mesh_prov_callback(&mesh_param, act); + return; +} +#endif /* CONFIG_BLE_MESH_FRIEND */ +#endif /* CONFIG_BLE_MESH_NODE */ + +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT +static void btc_ble_mesh_proxy_client_adv_recv_cb(const bt_mesh_addr_t *addr, + u8_t type, bt_mesh_proxy_adv_ctx_t *ctx) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + if (!addr || !ctx || type != BLE_MESH_PROXY_ADV_NET_ID) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + LOG_DEBUG("%s", __func__); + + mesh_param.proxy_client_recv_adv_pkt.addr_type = addr->type; + memcpy(mesh_param.proxy_client_recv_adv_pkt.addr, addr->val, BD_ADDR_LEN); + mesh_param.proxy_client_recv_adv_pkt.net_idx = ctx->net_id.net_idx; + memcpy(mesh_param.proxy_client_recv_adv_pkt.net_id, ctx->net_id.net_id, 8); + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROXY_CLIENT_RECV_ADV_PKT_EVT); + return; +} + +static void btc_ble_mesh_proxy_client_connect_cb(const bt_mesh_addr_t *addr, + u8_t conn_handle, u16_t net_idx) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + if (!addr || conn_handle >= BLE_MESH_MAX_CONN) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + LOG_DEBUG("%s", __func__); + + mesh_param.proxy_client_connected.addr_type = addr->type; + memcpy(mesh_param.proxy_client_connected.addr, addr->val, BD_ADDR_LEN); + mesh_param.proxy_client_connected.conn_handle = conn_handle; + mesh_param.proxy_client_connected.net_idx = net_idx; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROXY_CLIENT_CONNECTED_EVT); + return; +} + +static void btc_ble_mesh_proxy_client_disconnect_cb(const bt_mesh_addr_t *addr, + u8_t conn_handle, u16_t net_idx, u8_t reason) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + if (!addr || conn_handle >= BLE_MESH_MAX_CONN) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + LOG_DEBUG("%s", __func__); + + mesh_param.proxy_client_disconnected.addr_type = addr->type; + memcpy(mesh_param.proxy_client_disconnected.addr, addr->val, BD_ADDR_LEN); + mesh_param.proxy_client_disconnected.conn_handle = conn_handle; + mesh_param.proxy_client_disconnected.net_idx = net_idx; + mesh_param.proxy_client_disconnected.reason = reason; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROXY_CLIENT_DISCONNECTED_EVT); + return; +} + +static void btc_ble_mesh_proxy_client_filter_status_recv_cb(u8_t conn_handle, + u16_t src, u16_t net_idx, u8_t filter_type, u16_t list_size) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + + if (conn_handle >= BLE_MESH_MAX_CONN) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + LOG_DEBUG("%s", __func__); + + mesh_param.proxy_client_recv_filter_status.conn_handle = conn_handle; + mesh_param.proxy_client_recv_filter_status.server_addr = src; + mesh_param.proxy_client_recv_filter_status.net_idx = net_idx; + mesh_param.proxy_client_recv_filter_status.filter_type = filter_type; + mesh_param.proxy_client_recv_filter_status.list_size = list_size; + + btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_PROXY_CLIENT_RECV_FILTER_STATUS_EVT); + return; +} +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + int btc_ble_mesh_client_model_init(esp_ble_mesh_model_t *model) { __ASSERT(model && model->op, "%s, Invalid parameter", __func__); @@ -943,6 +1000,45 @@ extern const struct bt_mesh_model_op sensor_cli_op[]; extern const struct bt_mesh_model_op time_cli_op[]; extern const struct bt_mesh_model_op scene_cli_op[]; extern const struct bt_mesh_model_op scheduler_cli_op[]; +/* Generic Server Models */ +extern const struct bt_mesh_model_op gen_onoff_srv_op[]; +extern const struct bt_mesh_model_op gen_level_srv_op[]; +extern const struct bt_mesh_model_op gen_def_trans_time_srv_op[]; +extern const struct bt_mesh_model_op gen_power_onoff_srv_op[]; +extern const struct bt_mesh_model_op gen_power_onoff_setup_srv_op[]; +extern const struct bt_mesh_model_op gen_power_level_srv_op[]; +extern const struct bt_mesh_model_op gen_power_level_setup_srv_op[]; +extern const struct bt_mesh_model_op gen_battery_srv_op[]; +extern const struct bt_mesh_model_op gen_location_srv_op[]; +extern const struct bt_mesh_model_op gen_location_setup_srv_op[]; +extern const struct bt_mesh_model_op gen_user_prop_srv_op[]; +extern const struct bt_mesh_model_op gen_admin_prop_srv_op[]; +extern const struct bt_mesh_model_op gen_manu_prop_srv_op[]; +extern const struct bt_mesh_model_op gen_client_prop_srv_op[]; +/* Lighting Server Models */ +extern const struct bt_mesh_model_op light_lightness_srv_op[]; +extern const struct bt_mesh_model_op light_lightness_setup_srv_op[]; +extern const struct bt_mesh_model_op light_ctl_srv_op[]; +extern const struct bt_mesh_model_op light_ctl_setup_srv_op[]; +extern const struct bt_mesh_model_op light_ctl_temp_srv_op[]; +extern const struct bt_mesh_model_op light_hsl_srv_op[]; +extern const struct bt_mesh_model_op light_hsl_hue_srv_op[]; +extern const struct bt_mesh_model_op light_hsl_sat_srv_op[]; +extern const struct bt_mesh_model_op light_hsl_setup_srv_op[]; +extern const struct bt_mesh_model_op light_xyl_srv_op[]; +extern const struct bt_mesh_model_op light_xyl_setup_srv_op[]; +extern const struct bt_mesh_model_op light_lc_srv_op[]; +extern const struct bt_mesh_model_op light_lc_setup_srv_op[]; +/* Time and Scenes Server Models */ +extern const struct bt_mesh_model_op time_srv_op[]; +extern const struct bt_mesh_model_op time_setup_srv_op[]; +extern const struct bt_mesh_model_op scene_srv_op[]; +extern const struct bt_mesh_model_op scene_setup_srv_op[]; +extern const struct bt_mesh_model_op scheduler_srv_op[]; +extern const struct bt_mesh_model_op scheduler_setup_srv_op[]; +/* Sensor Server Models */ +extern const struct bt_mesh_model_op sensor_srv_op[]; +extern const struct bt_mesh_model_op sensor_setup_srv_op[]; static void btc_ble_mesh_model_op_add(esp_ble_mesh_model_t *model) { @@ -953,8 +1049,8 @@ static void btc_ble_mesh_model_op_add(esp_ble_mesh_model_t *model) return; } - /* 1. For SIG client models, model->op will be NULL and initialized here. - * 2. The vendor model opcode is 3 bytes. + /* For SIG client and server models, model->op will be NULL and initialized here. + * For vendor models whose opcode is 3 bytes, model->op will be initialized here. */ if ((model->op != NULL) && (model->op->opcode >= 0x10000)) { goto add_model_op; @@ -963,6 +1059,10 @@ static void btc_ble_mesh_model_op_add(esp_ble_mesh_model_t *model) switch (model->model_id) { case BLE_MESH_MODEL_ID_CFG_SRV: { 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; + } break; } case BLE_MESH_MODEL_ID_CFG_CLI: { @@ -975,6 +1075,13 @@ static void btc_ble_mesh_model_op_add(esp_ble_mesh_model_t *model) } case BLE_MESH_MODEL_ID_HEALTH_SRV: { model->op = (esp_ble_mesh_model_op_t *)bt_mesh_health_srv_op; + struct bt_mesh_health_srv *srv = (struct bt_mesh_health_srv *)model->user_data; + if (srv) { + srv->cb.fault_clear = btc_ble_mesh_health_server_fault_clear; + srv->cb.fault_test = btc_ble_mesh_health_server_fault_test; + srv->cb.attn_on = btc_ble_mesh_health_server_attention_on; + srv->cb.attn_off = btc_ble_mesh_health_server_attention_off; + } break; } case BLE_MESH_MODEL_ID_HEALTH_CLI: { @@ -1121,10 +1228,221 @@ static void btc_ble_mesh_model_op_add(esp_ble_mesh_model_t *model) } break; } - default: { + case BLE_MESH_MODEL_ID_GEN_ONOFF_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_onoff_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_LEVEL_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_level_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_def_trans_time_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_power_onoff_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_power_onoff_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_power_level_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_power_level_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_BATTERY_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_battery_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_LOCATION_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_location_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_user_prop_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_admin_prop_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_manu_prop_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_client_prop_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)gen_location_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_lightness_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_lightness_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_ctl_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_ctl_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_ctl_temp_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_hsl_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_hsl_hue_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_hsl_sat_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_hsl_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_XYL_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_xyl_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_xyl_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_LC_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_lc_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)light_lc_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_TIME_SRV: + model->op = (esp_ble_mesh_model_op_t *)time_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_TIME_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)time_setup_srv_op; + if (model->pub) { + /* Time Setup Server model does not support subscribing nor publishing. */ + LOG_ERROR("%s, Time Setup Server shall not support publication", __func__); + return; + } + break; + case BLE_MESH_MODEL_ID_SCENE_SRV: + model->op = (esp_ble_mesh_model_op_t *)scene_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_SCENE_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)scene_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_SCHEDULER_SRV: + model->op = (esp_ble_mesh_model_op_t *)scheduler_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)scheduler_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_SENSOR_SRV: + model->op = (esp_ble_mesh_model_op_t *)sensor_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + case BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV: + model->op = (esp_ble_mesh_model_op_t *)sensor_setup_srv_op; + if (model->pub) { + model->pub->update = (esp_ble_mesh_cb_t)btc_ble_mesh_model_publish_update; + } + break; + default: goto add_model_op; } - } return; add_model_op: @@ -1149,6 +1467,7 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) LOG_ERROR("%s, Invalid parameter", __func__); return; } + arg = (btc_ble_mesh_prov_args_t *)(msg->arg); switch (msg->act) { @@ -1188,6 +1507,12 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) arg->mesh_init.prov->link_close_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_link_close_cb; arg->mesh_init.prov->complete_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_complete_cb; arg->mesh_init.prov->reset_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_reset_cb; +#if CONFIG_BLE_MESH_LOW_POWER + bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb); +#endif /* CONFIG_BLE_MESH_LOW_POWER */ +#if CONFIG_BLE_MESH_FRIEND + bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb); +#endif /* CONFIG_BLE_MESH_FRIEND */ #endif /* CONFIG_BLE_MESH_NODE */ #if CONFIG_BLE_MESH_PROVISIONER arg->mesh_init.prov->provisioner_prov_read_oob_pub_key = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_read_oob_pub_key_cb; @@ -1198,6 +1523,12 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) arg->mesh_init.prov->provisioner_prov_comp = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_complete_cb; bt_mesh_prov_adv_pkt_cb_register(btc_ble_mesh_provisioner_recv_unprov_adv_pkt_cb); #endif /* CONFIG_BLE_MESH_PROVISIONER */ +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + bt_mesh_proxy_client_set_adv_recv_cb(btc_ble_mesh_proxy_client_adv_recv_cb); + bt_mesh_proxy_client_set_conn_cb(btc_ble_mesh_proxy_client_connect_cb); + bt_mesh_proxy_client_set_disconn_cb(btc_ble_mesh_proxy_client_disconnect_cb); + bt_mesh_proxy_client_set_filter_status_cb(btc_ble_mesh_proxy_client_filter_status_recv_cb); +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ err_code = bt_mesh_init((struct bt_mesh_prov *)arg->mesh_init.prov, (struct bt_mesh_comp *)arg->mesh_init.comp); /* Give the semaphore when BLE Mesh initialization is finished. */ @@ -1224,8 +1555,8 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) act = ESP_BLE_MESH_NODE_PROV_SET_OOB_PUB_KEY_COMP_EVT; param.node_prov_set_oob_pub_key_comp.err_code = bt_mesh_set_oob_pub_key(arg->set_oob_pub_key.pub_key_x, - arg->set_oob_pub_key.pub_key_y, - arg->set_oob_pub_key.private_key); + arg->set_oob_pub_key.pub_key_y, + arg->set_oob_pub_key.private_key); break; case BTC_BLE_MESH_ACT_INPUT_NUMBER: act = ESP_BLE_MESH_NODE_PROV_INPUT_NUMBER_COMP_EVT; @@ -1239,7 +1570,7 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) act = ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT; param.node_set_unprov_dev_name_comp.err_code = bt_mesh_set_device_name(arg->set_device_name.name); break; -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) case BTC_BLE_MESH_ACT_PROXY_IDENTITY_ENABLE: act = ESP_BLE_MESH_NODE_PROXY_IDENTITY_ENABLE_COMP_EVT; param.node_proxy_identity_enable_comp.err_code = bt_mesh_proxy_identity_enable(); @@ -1252,27 +1583,27 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) act = ESP_BLE_MESH_NODE_PROXY_GATT_DISABLE_COMP_EVT; param.node_proxy_gatt_disable_comp.err_code = bt_mesh_proxy_gatt_disable(); break; -#endif /* CONFIG_BLE_MESH_GATT_PROXY */ +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #endif /* CONFIG_BLE_MESH_NODE */ #if CONFIG_BLE_MESH_PROVISIONER case BTC_BLE_MESH_ACT_PROVISIONER_READ_OOB_PUB_KEY: act = ESP_BLE_MESH_PROVISIONER_PROV_READ_OOB_PUB_KEY_COMP_EVT; param.provisioner_prov_read_oob_pub_key_comp.err_code = bt_mesh_prov_read_oob_pub_key(arg->provisioner_read_oob_pub_key.link_idx, - arg->provisioner_read_oob_pub_key.pub_key_x, - arg->provisioner_read_oob_pub_key.pub_key_y); + arg->provisioner_read_oob_pub_key.pub_key_x, + arg->provisioner_read_oob_pub_key.pub_key_y); break; case BTC_BLE_MESH_ACT_PROVISIONER_INPUT_STR: act = ESP_BLE_MESH_PROVISIONER_PROV_INPUT_STRING_COMP_EVT; param.provisioner_prov_input_str_comp.err_code = bt_mesh_prov_set_oob_input_data(arg->provisioner_input_str.link_idx, - (const u8_t *)&arg->provisioner_input_str.string, false); + (const u8_t *)&arg->provisioner_input_str.string, false); break; case BTC_BLE_MESH_ACT_PROVISIONER_INPUT_NUM: act = ESP_BLE_MESH_PROVISIONER_PROV_INPUT_NUMBER_COMP_EVT; param.provisioner_prov_input_num_comp.err_code = bt_mesh_prov_set_oob_input_data(arg->provisioner_input_num.link_idx, - (const u8_t *)&arg->provisioner_input_num.number, true); + (const u8_t *)&arg->provisioner_input_num.number, true); break; case BTC_BLE_MESH_ACT_PROVISIONER_ENABLE: act = ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT; @@ -1404,12 +1735,90 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) bt_mesh_set_fast_prov_action(arg->set_fast_prov_action.action); break; #endif /* CONFIG_BLE_MESH_FAST_PROV */ +#if CONFIG_BLE_MESH_LOW_POWER + case BTC_BLE_MESH_ACT_LPN_ENABLE: + act = ESP_BLE_MESH_LPN_ENABLE_COMP_EVT; + param.lpn_enable_comp.err_code = bt_mesh_lpn_set(true, false); + break; + case BTC_BLE_MESH_ACT_LPN_DISABLE: + act = ESP_BLE_MESH_LPN_DISABLE_COMP_EVT; + param.lpn_disable_comp.err_code = bt_mesh_lpn_set(false, arg->lpn_disable.force); + break; + case BTC_BLE_MESH_ACT_LPN_POLL: + act = ESP_BLE_MESH_LPN_POLL_COMP_EVT; + param.lpn_poll_comp.err_code = bt_mesh_lpn_poll(); + break; +#endif /* CONFIG_BLE_MESH_LOW_POWER */ +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + case BTC_BLE_MESH_ACT_PROXY_CLIENT_CONNECT: + act = ESP_BLE_MESH_PROXY_CLIENT_CONNECT_COMP_EVT; + memcpy(param.proxy_client_connect_comp.addr, arg->proxy_client_connect.addr, BD_ADDR_LEN); + param.proxy_client_connect_comp.addr_type = arg->proxy_client_connect.addr_type; + param.proxy_client_connect_comp.net_idx = arg->proxy_client_connect.net_idx; + param.proxy_client_connect_comp.err_code = + bt_mesh_proxy_client_connect(arg->proxy_client_connect.addr, + arg->proxy_client_connect.addr_type, + arg->proxy_client_connect.net_idx); + break; + case BTC_BLE_MESH_ACT_PROXY_CLIENT_DISCONNECT: + act = ESP_BLE_MESH_PROXY_CLIENT_DISCONNECT_COMP_EVT; + param.proxy_client_disconnect_comp.conn_handle = arg->proxy_client_disconnect.conn_handle; + param.proxy_client_disconnect_comp.err_code = + bt_mesh_proxy_client_disconnect(arg->proxy_client_disconnect.conn_handle); + break; + case BTC_BLE_MESH_ACT_PROXY_CLIENT_SET_FILTER_TYPE: { + struct bt_mesh_proxy_cfg_pdu pdu = { + .opcode = BLE_MESH_PROXY_CFG_FILTER_SET, + .set.filter_type = arg->proxy_client_set_filter_type.filter_type, + }; + act = ESP_BLE_MESH_PROXY_CLIENT_SET_FILTER_TYPE_COMP_EVT; + param.proxy_client_set_filter_type_comp.conn_handle = arg->proxy_client_set_filter_type.conn_handle; + param.proxy_client_set_filter_type_comp.net_idx = arg->proxy_client_set_filter_type.net_idx; + param.proxy_client_set_filter_type_comp.err_code = + bt_mesh_proxy_client_send_cfg(arg->proxy_client_set_filter_type.conn_handle, + arg->proxy_client_set_filter_type.net_idx, &pdu); + break; + } + case BTC_BLE_MESH_ACT_PROXY_CLIENT_ADD_FILTER_ADDR: { + struct bt_mesh_proxy_cfg_pdu pdu = { + .opcode = BLE_MESH_PROXY_CFG_FILTER_ADD, + .add.addr = arg->proxy_client_add_filter_addr.addr, + .add.addr_num = arg->proxy_client_add_filter_addr.addr_num, + }; + act = ESP_BLE_MESH_PROXY_CLIENT_ADD_FILTER_ADDR_COMP_EVT; + param.proxy_client_add_filter_addr_comp.conn_handle = arg->proxy_client_add_filter_addr.conn_handle; + param.proxy_client_add_filter_addr_comp.net_idx = arg->proxy_client_add_filter_addr.net_idx; + param.proxy_client_add_filter_addr_comp.err_code = + bt_mesh_proxy_client_send_cfg(arg->proxy_client_add_filter_addr.conn_handle, + arg->proxy_client_add_filter_addr.net_idx, &pdu); + break; + } + case BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR: { + struct bt_mesh_proxy_cfg_pdu pdu = { + .opcode = BLE_MESH_PROXY_CFG_FILTER_REMOVE, + .remove.addr = arg->proxy_client_remove_filter_addr.addr, + .remove.addr_num = arg->proxy_client_remove_filter_addr.addr_num, + }; + act = ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT; + param.proxy_client_remove_filter_addr_comp.conn_handle = arg->proxy_client_remove_filter_addr.conn_handle; + param.proxy_client_remove_filter_addr_comp.net_idx = arg->proxy_client_remove_filter_addr.net_idx; + param.proxy_client_remove_filter_addr_comp.err_code = + bt_mesh_proxy_client_send_cfg(arg->proxy_client_remove_filter_addr.conn_handle, + arg->proxy_client_remove_filter_addr.net_idx, &pdu); + break; + } +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ default: LOG_WARN("%s, Invalid msg->act %d", __func__, msg->act); return; } + /* Callback operation completion events */ btc_ble_mesh_prov_set_complete_cb(¶m, act); + + if (msg->arg) { + btc_ble_mesh_prov_arg_deep_free(msg); + } return; } @@ -1469,7 +1878,7 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg) arg->model_send.ctx->srv_send = true; err = bt_mesh_model_send((struct bt_mesh_model *)arg->model_send.model, (struct bt_mesh_msg_ctx *)arg->model_send.ctx, - buf, NULL, NULL); + buf, NULL, NULL); bt_mesh_free_buf(buf); btc_ble_mesh_model_send_comp_cb(arg->model_send.model, arg->model_send.ctx, arg->model_send.opcode, err); @@ -1492,21 +1901,28 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg) break; } err = bt_mesh_client_send_msg((struct bt_mesh_model *)arg->model_send.model, - arg->model_send.opcode, - (struct bt_mesh_msg_ctx *)arg->model_send.ctx, buf, - btc_ble_mesh_client_model_timeout_cb, arg->model_send.msg_timeout, - arg->model_send.need_rsp, NULL, NULL); + arg->model_send.opcode, + (struct bt_mesh_msg_ctx *)arg->model_send.ctx, buf, + btc_ble_mesh_client_model_timeout_cb, arg->model_send.msg_timeout, + arg->model_send.need_rsp, NULL, NULL); bt_mesh_free_buf(buf); btc_ble_mesh_model_send_comp_cb(arg->model_send.model, arg->model_send.ctx, arg->model_send.opcode, err); break; } + case BTC_BLE_MESH_ACT_SERVER_MODEL_UPDATE_STATE: + err = bt_mesh_update_binding_state( + (struct bt_mesh_model *)arg->model_update_state.model, arg->model_update_state.type, + (bt_mesh_server_state_value_t *)arg->model_update_state.value); + btc_ble_mesh_server_model_update_state_comp_cb(arg->model_update_state.model, + arg->model_update_state.type, err); + break; default: LOG_WARN("%s, Unknown msg->act %d", __func__, msg->act); break; } - btc_ble_mesh_prov_arg_deep_free(msg); + btc_ble_mesh_model_arg_deep_free(msg); return; } diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c index da03d540f..603f90586 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c @@ -450,12 +450,17 @@ static void btc_ble_mesh_sensor_client_callback(esp_ble_mesh_sensor_client_cb_pa LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_SENSOR_CLIENT)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_SENSOR_CLIENT; msg.act = act; btc_transfer_context(&msg, cb_params, - sizeof(esp_ble_mesh_sensor_client_cb_param_t), btc_ble_mesh_sensor_client_copy_req_data); + sizeof(esp_ble_mesh_sensor_client_cb_param_t), btc_ble_mesh_sensor_client_copy_req_data); } void bt_mesh_sensor_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, @@ -523,7 +528,7 @@ void btc_ble_mesh_sensor_client_publish_callback(u32_t opcode, } bt_mesh_sensor_client_cb_evt_to_btc(opcode, - BTC_BLE_MESH_EVT_SENSOR_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); + BTC_BLE_MESH_EVT_SENSOR_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); return; } @@ -562,7 +567,7 @@ void btc_ble_mesh_sensor_client_call_handler(btc_msg_t *msg) cb.params = arg->sensor_client_get_state.params; cb.error_code = bt_mesh_sensor_client_get_state(&common, - (void *)arg->sensor_client_get_state.get_state, (void *)&cb.status_cb); + (void *)arg->sensor_client_get_state.get_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_sensor_client_callback(&cb, ESP_BLE_MESH_SENSOR_CLIENT_GET_STATE_EVT); @@ -588,7 +593,7 @@ void btc_ble_mesh_sensor_client_call_handler(btc_msg_t *msg) cb.params = arg->sensor_client_set_state.params; cb.error_code = bt_mesh_sensor_client_set_state(&common, - (void *)arg->sensor_client_set_state.set_state, (void *)&cb.status_cb); + (void *)arg->sensor_client_set_state.set_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_sensor_client_callback(&cb, ESP_BLE_MESH_SENSOR_CLIENT_SET_STATE_EVT); @@ -624,3 +629,281 @@ void btc_ble_mesh_sensor_client_cb_handler(btc_msg_t *msg) return; } +/* Sensor Server Models related functions */ + +static inline void btc_ble_mesh_sensor_server_cb_to_app( + esp_ble_mesh_sensor_server_cb_event_t event, + esp_ble_mesh_sensor_server_cb_param_t *param) +{ + esp_ble_mesh_sensor_server_cb_t btc_ble_mesh_cb = + (esp_ble_mesh_sensor_server_cb_t)btc_profile_cb_get(BTC_PID_SENSOR_SERVER); + if (btc_ble_mesh_cb) { + btc_ble_mesh_cb(event, param); + } +} + +static void btc_ble_mesh_sensor_server_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src) +{ + esp_ble_mesh_sensor_server_cb_param_t *p_dest_data = (esp_ble_mesh_sensor_server_cb_param_t *)p_dest; + esp_ble_mesh_sensor_server_cb_param_t *p_src_data = (esp_ble_mesh_sensor_server_cb_param_t *)p_src; + u16_t length; + + if (!msg || !p_src_data || !p_dest_data) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (msg->act) { + case ESP_BLE_MESH_SENSOR_SERVER_STATE_CHANGE_EVT: + if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET || + p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK) { + if (p_src_data->value.state_change.sensor_cadence_set.trigger_delta_down) { + length = p_src_data->value.state_change.sensor_cadence_set.trigger_delta_down->len; + p_dest_data->value.state_change.sensor_cadence_set.trigger_delta_down = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.sensor_cadence_set.trigger_delta_down == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.sensor_cadence_set.trigger_delta_down, + p_src_data->value.state_change.sensor_cadence_set.trigger_delta_down->data, + p_src_data->value.state_change.sensor_cadence_set.trigger_delta_down->len); + } + if (p_src_data->value.state_change.sensor_cadence_set.trigger_delta_up) { + length = p_src_data->value.state_change.sensor_cadence_set.trigger_delta_up->len; + p_dest_data->value.state_change.sensor_cadence_set.trigger_delta_up = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.sensor_cadence_set.trigger_delta_up == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.sensor_cadence_set.trigger_delta_up, + p_src_data->value.state_change.sensor_cadence_set.trigger_delta_up->data, + p_src_data->value.state_change.sensor_cadence_set.trigger_delta_up->len); + } + if (p_src_data->value.state_change.sensor_cadence_set.fast_cadence_low) { + length = p_src_data->value.state_change.sensor_cadence_set.fast_cadence_low->len; + p_dest_data->value.state_change.sensor_cadence_set.fast_cadence_low = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.sensor_cadence_set.fast_cadence_low == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.sensor_cadence_set.fast_cadence_low, + p_src_data->value.state_change.sensor_cadence_set.fast_cadence_low->data, + p_src_data->value.state_change.sensor_cadence_set.fast_cadence_low->len); + } + if (p_src_data->value.state_change.sensor_cadence_set.fast_cadence_high) { + length = p_src_data->value.state_change.sensor_cadence_set.fast_cadence_high->len; + p_dest_data->value.state_change.sensor_cadence_set.fast_cadence_high = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.sensor_cadence_set.fast_cadence_high == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.sensor_cadence_set.fast_cadence_high, + p_src_data->value.state_change.sensor_cadence_set.fast_cadence_high->data, + p_src_data->value.state_change.sensor_cadence_set.fast_cadence_high->len); + } + } else if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET || + p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK) { + if (p_src_data->value.state_change.sensor_setting_set.setting_value) { + length = p_src_data->value.state_change.sensor_setting_set.setting_value->len; + p_dest_data->value.state_change.sensor_setting_set.setting_value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.state_change.sensor_setting_set.setting_value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.state_change.sensor_setting_set.setting_value, + p_src_data->value.state_change.sensor_setting_set.setting_value->data, + p_src_data->value.state_change.sensor_setting_set.setting_value->len); + } + } + break; + case ESP_BLE_MESH_SENSOR_SERVER_RECV_GET_MSG_EVT: + if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET) { + if (p_src_data->value.get.sensor_column.raw_value_x) { + length = p_src_data->value.get.sensor_column.raw_value_x->len; + p_dest_data->value.get.sensor_column.raw_value_x = bt_mesh_alloc_buf(length); + if (p_dest_data->value.get.sensor_column.raw_value_x == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.get.sensor_column.raw_value_x, + p_src_data->value.get.sensor_column.raw_value_x->data, + p_src_data->value.get.sensor_column.raw_value_x->len); + } + } else if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_GET) { + if (p_src_data->value.get.sensor_series.raw_value) { + length = p_src_data->value.get.sensor_series.raw_value->len; + p_dest_data->value.get.sensor_series.raw_value = bt_mesh_alloc_buf(length); + if (p_dest_data->value.get.sensor_series.raw_value == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.get.sensor_series.raw_value, + p_src_data->value.get.sensor_series.raw_value->data, + p_src_data->value.get.sensor_series.raw_value->len); + } + } + break; + case ESP_BLE_MESH_SENSOR_SERVER_RECV_SET_MSG_EVT: + if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET || + p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK) { + if (p_src_data->value.set.sensor_cadence.cadence) { + length = p_src_data->value.set.sensor_cadence.cadence->len; + p_dest_data->value.set.sensor_cadence.cadence = bt_mesh_alloc_buf(length); + if (p_dest_data->value.set.sensor_cadence.cadence == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.set.sensor_cadence.cadence, + p_src_data->value.set.sensor_cadence.cadence->data, + p_src_data->value.set.sensor_cadence.cadence->len); + } + } else if (p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET || + p_src_data->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK) { + if (p_src_data->value.set.sensor_setting.setting_raw) { + length = p_src_data->value.set.sensor_setting.setting_raw->len; + p_dest_data->value.set.sensor_setting.setting_raw = bt_mesh_alloc_buf(length); + if (p_dest_data->value.set.sensor_setting.setting_raw == NULL) { + LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act); + return; + } + net_buf_simple_add_mem(p_dest_data->value.set.sensor_setting.setting_raw, + p_src_data->value.set.sensor_setting.setting_raw->data, + p_src_data->value.set.sensor_setting.setting_raw->len); + } + } + break; + default: + break; + } +} + +static void btc_ble_mesh_sensor_server_free_req_data(btc_msg_t *msg) +{ + esp_ble_mesh_sensor_server_cb_param_t *arg = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + arg = (esp_ble_mesh_sensor_server_cb_param_t *)(msg->arg); + + switch (msg->act) { + case ESP_BLE_MESH_SENSOR_SERVER_STATE_CHANGE_EVT: + if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET || + arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK) { + bt_mesh_free_buf(arg->value.state_change.sensor_cadence_set.trigger_delta_down); + bt_mesh_free_buf(arg->value.state_change.sensor_cadence_set.trigger_delta_up); + bt_mesh_free_buf(arg->value.state_change.sensor_cadence_set.fast_cadence_low); + bt_mesh_free_buf(arg->value.state_change.sensor_cadence_set.fast_cadence_high); + } else if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET || + arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK) { + bt_mesh_free_buf(arg->value.state_change.sensor_setting_set.setting_value); + } + break; + case ESP_BLE_MESH_SENSOR_SERVER_RECV_GET_MSG_EVT: + if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET) { + bt_mesh_free_buf(arg->value.get.sensor_column.raw_value_x); + } else if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_GET) { + bt_mesh_free_buf(arg->value.get.sensor_series.raw_value); + } + break; + case ESP_BLE_MESH_SENSOR_SERVER_RECV_SET_MSG_EVT: + if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET || + arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK) { + bt_mesh_free_buf(arg->value.set.sensor_cadence.cadence); + } else if (arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET || + arg->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK) { + bt_mesh_free_buf(arg->value.set.sensor_setting.setting_raw); + } + break; + default: + break; + } +} + +static void btc_ble_mesh_sensor_server_callback(esp_ble_mesh_sensor_server_cb_param_t *cb_params, uint8_t act) +{ + btc_msg_t msg = {0}; + + LOG_DEBUG("%s", __func__); + + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_SENSOR_SERVER)) { + return; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_SENSOR_SERVER; + msg.act = act; + + btc_transfer_context( + &msg, cb_params, sizeof(esp_ble_mesh_sensor_server_cb_param_t), btc_ble_mesh_sensor_server_copy_req_data); +} + +void bt_mesh_sensor_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len) +{ + esp_ble_mesh_sensor_server_cb_param_t cb_params = {0}; + size_t length; + uint8_t act; + + if (model == NULL || ctx == NULL) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (evt_type) { + case BTC_BLE_MESH_EVT_SENSOR_SERVER_STATE_CHANGE: + act = ESP_BLE_MESH_SENSOR_SERVER_STATE_CHANGE_EVT; + break; + case BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG: + act = ESP_BLE_MESH_SENSOR_SERVER_RECV_GET_MSG_EVT; + break; + case BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_SET_MSG: + act = ESP_BLE_MESH_SENSOR_SERVER_RECV_SET_MSG_EVT; + break; + default: + LOG_ERROR("%s, Unknown Sensor Server event type", __func__); + return; + } + + cb_params.model = (esp_ble_mesh_model_t *)model; + cb_params.ctx.net_idx = ctx->net_idx; + cb_params.ctx.app_idx = ctx->app_idx; + cb_params.ctx.addr = ctx->addr; + cb_params.ctx.recv_ttl = ctx->recv_ttl; + cb_params.ctx.recv_op = ctx->recv_op; + cb_params.ctx.recv_dst = ctx->recv_dst; + + if (val && len) { + length = (len <= sizeof(cb_params.value)) ? len : sizeof(cb_params.value); + memcpy(&cb_params.value, val, length); + } + + btc_ble_mesh_sensor_server_callback(&cb_params, act); + return; +} + +void btc_ble_mesh_sensor_server_cb_handler(btc_msg_t *msg) +{ + esp_ble_mesh_sensor_server_cb_param_t *param = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + param = (esp_ble_mesh_sensor_server_cb_param_t *)(msg->arg); + + if (msg->act < ESP_BLE_MESH_SENSOR_SERVER_EVT_MAX) { + btc_ble_mesh_sensor_server_cb_to_app(msg->act, param); + } else { + LOG_ERROR("%s, Unknown msg->act = %d", __func__, msg->act); + } + + btc_ble_mesh_sensor_server_free_req_data(msg); + return; +} diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c index 7e29d2ea1..aeb65657e 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c @@ -207,12 +207,17 @@ static void btc_ble_mesh_time_scene_client_callback(esp_ble_mesh_time_scene_clie LOG_DEBUG("%s", __func__); + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_TIME_SCENE_CLIENT)) { + return; + } + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_TIME_SCENE_CLIENT; msg.act = act; btc_transfer_context(&msg, cb_params, - sizeof(esp_ble_mesh_time_scene_client_cb_param_t), btc_ble_mesh_time_scene_client_copy_req_data); + sizeof(esp_ble_mesh_time_scene_client_cb_param_t), btc_ble_mesh_time_scene_client_copy_req_data); } void bt_mesh_time_scene_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, @@ -280,7 +285,7 @@ void btc_ble_mesh_time_scene_client_publish_callback(u32_t opcode, } bt_mesh_time_scene_client_cb_evt_to_btc(opcode, - BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); + BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_PUBLISH, model, ctx, buf->data, buf->len); return; } @@ -319,7 +324,7 @@ void btc_ble_mesh_time_scene_client_call_handler(btc_msg_t *msg) cb.params = arg->time_scene_client_get_state.params; cb.error_code = bt_mesh_time_scene_client_get_state(&common, - (void *)arg->time_scene_client_get_state.get_state, (void *)&cb.status_cb); + (void *)arg->time_scene_client_get_state.get_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_time_scene_client_callback(&cb, ESP_BLE_MESH_TIME_SCENE_CLIENT_GET_STATE_EVT); @@ -345,7 +350,7 @@ void btc_ble_mesh_time_scene_client_call_handler(btc_msg_t *msg) cb.params = arg->time_scene_client_set_state.params; cb.error_code = bt_mesh_time_scene_client_set_state(&common, - (void *)arg->time_scene_client_set_state.set_state, (void *)&cb.status_cb); + (void *)arg->time_scene_client_set_state.set_state, (void *)&cb.status_cb); if (cb.error_code) { /* If send failed, callback error_code to app layer immediately */ btc_ble_mesh_time_scene_client_callback(&cb, ESP_BLE_MESH_TIME_SCENE_CLIENT_SET_STATE_EVT); @@ -381,3 +386,104 @@ void btc_ble_mesh_time_scene_client_cb_handler(btc_msg_t *msg) return; } +/* Time and Scenes Server Models related functions */ + +static inline void btc_ble_mesh_time_scene_server_cb_to_app( + esp_ble_mesh_time_scene_server_cb_event_t event, + esp_ble_mesh_time_scene_server_cb_param_t *param) +{ + esp_ble_mesh_time_scene_server_cb_t btc_ble_mesh_cb = + (esp_ble_mesh_time_scene_server_cb_t)btc_profile_cb_get(BTC_PID_TIME_SCENE_SERVER); + if (btc_ble_mesh_cb) { + btc_ble_mesh_cb(event, param); + } +} + +static void btc_ble_mesh_time_scene_server_callback(esp_ble_mesh_time_scene_server_cb_param_t *cb_params, uint8_t act) +{ + btc_msg_t msg = {0}; + + LOG_DEBUG("%s", __func__); + + /* If corresponding callback is not registered, event will not be posted. */ + if (!btc_profile_cb_get(BTC_PID_TIME_SCENE_SERVER)) { + return; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_TIME_SCENE_SERVER; + msg.act = act; + + btc_transfer_context( + &msg, cb_params, sizeof(esp_ble_mesh_time_scene_server_cb_param_t), NULL); +} + +void bt_mesh_time_scene_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len) +{ + esp_ble_mesh_time_scene_server_cb_param_t cb_params = {0}; + size_t length; + uint8_t act; + + if (model == NULL || ctx == NULL) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + switch (evt_type) { + case BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE: + act = ESP_BLE_MESH_TIME_SCENE_SERVER_STATE_CHANGE_EVT; + break; + case BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG: + act = ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_GET_MSG_EVT; + break; + case BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG: + act = ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_SET_MSG_EVT; + break; + case BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_STATUS_MSG: + act = ESP_BLE_MESH_TIME_SCENE_SERVER_RECV_STATUS_MSG_EVT; + break; + default: + LOG_ERROR("%s, Unknown Time Scene Server event type", __func__); + return; + } + + cb_params.model = (esp_ble_mesh_model_t *)model; + cb_params.ctx.net_idx = ctx->net_idx; + cb_params.ctx.app_idx = ctx->app_idx; + cb_params.ctx.addr = ctx->addr; + cb_params.ctx.recv_ttl = ctx->recv_ttl; + cb_params.ctx.recv_op = ctx->recv_op; + cb_params.ctx.recv_dst = ctx->recv_dst; + + if (val && len) { + length = (len <= sizeof(cb_params.value)) ? len : sizeof(cb_params.value); + memcpy(&cb_params.value, val, length); + } + + btc_ble_mesh_time_scene_server_callback(&cb_params, act); + return; +} + +void btc_ble_mesh_time_scene_server_cb_handler(btc_msg_t *msg) +{ + esp_ble_mesh_time_scene_server_cb_param_t *param = NULL; + + if (!msg || !msg->arg) { + LOG_ERROR("%s, Invalid parameter", __func__); + return; + } + + param = (esp_ble_mesh_time_scene_server_cb_param_t *)(msg->arg); + + if (msg->act < ESP_BLE_MESH_TIME_SCENE_SERVER_EVT_MAX) { + btc_ble_mesh_time_scene_server_cb_to_app(msg->act, param); + } else { + LOG_ERROR("%s, Unknown msg->act = %d", __func__, msg->act); + } + + return; +} + diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_config_model.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_config_model.h index dc81116ef..6070e7636 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_config_model.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_config_model.h @@ -63,7 +63,7 @@ void bt_mesh_config_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, void btc_ble_mesh_config_server_cb_handler(btc_msg_t *msg); typedef enum { - BTC_BLE_MESH_EVT_CONFIG_SERVER_RECV_MSG, + BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, BTC_BLE_MESH_EVT_CONFIG_SERVER_MAX, } btc_ble_mesh_config_server_evt_t; diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_generic_model.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_generic_model.h index a60f4a2b0..20c6bad09 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_generic_model.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_generic_model.h @@ -60,4 +60,18 @@ void bt_mesh_generic_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, struct bt_mesh_msg_ctx *ctx, const u8_t *val, size_t len); +typedef enum { + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, + BTC_BLE_MESH_EVT_GENERIC_SERVER_MAX, +} btc_ble_mesh_generic_server_evt_t; + +void bt_mesh_generic_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len); + +void btc_ble_mesh_generic_server_cb_handler(btc_msg_t *msg); + #endif /* _BTC_BLE_MESH_GENERIC_MODEL_H_ */ diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_health_model.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_health_model.h index d124c7d8e..5d0dcd25d 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_health_model.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_health_model.h @@ -68,7 +68,7 @@ typedef enum { typedef union { struct ble_mesh_health_server_fault_update_args { esp_ble_mesh_elem_t *element; - } fault_update; + } health_fault_update; } btc_ble_mesh_health_server_args_t; void btc_ble_mesh_health_server_call_handler(btc_msg_t *msg); @@ -77,4 +77,12 @@ void btc_ble_mesh_health_server_cb_handler(btc_msg_t *msg); void btc_ble_mesh_health_server_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_ble_mesh_health_server_fault_clear(struct bt_mesh_model *model, u16_t company_id); + +void btc_ble_mesh_health_server_fault_test(struct bt_mesh_model *model, u8_t test_id, u16_t company_id); + +void btc_ble_mesh_health_server_attention_on(struct bt_mesh_model *model, u8_t time); + +void btc_ble_mesh_health_server_attention_off(struct bt_mesh_model *model); + #endif /* _BTC_BLE_MESH_HEALTH_MODEL_H_ */ diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_lighting_model.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_lighting_model.h index 2bb33e1b3..55915bc7e 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_lighting_model.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_lighting_model.h @@ -60,5 +60,20 @@ void bt_mesh_lighting_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, struct bt_mesh_msg_ctx *ctx, const u8_t *val, size_t len); +typedef enum { + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_STATUS_MSG, + BTC_BLE_MESH_EVT_LIGHTING_SERVER_MAX, +} btc_ble_mesh_lighting_server_evt_t; + +void bt_mesh_lighting_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len); + +void btc_ble_mesh_lighting_server_cb_handler(btc_msg_t *msg); + #endif /* _BTC_BLE_MESH_LIGHTING_MODEL_H_ */ 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 a179b6203..fbe6a364d 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 @@ -55,12 +55,21 @@ typedef enum { BTC_BLE_MESH_ACT_PROVISIONER_ADD_LOCAL_NET_KEY, BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO, BTC_BLE_MESH_ACT_SET_FAST_PROV_ACTION, + BTC_BLE_MESH_ACT_LPN_ENABLE, + BTC_BLE_MESH_ACT_LPN_DISABLE, + BTC_BLE_MESH_ACT_LPN_POLL, + BTC_BLE_MESH_ACT_PROXY_CLIENT_CONNECT, + BTC_BLE_MESH_ACT_PROXY_CLIENT_DISCONNECT, + 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_prov_act_t; typedef enum { BTC_BLE_MESH_ACT_MODEL_PUBLISH, BTC_BLE_MESH_ACT_SERVER_MODEL_SEND, BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND, + BTC_BLE_MESH_ACT_SERVER_MODEL_UPDATE_STATE, } btc_ble_mesh_model_act_t; typedef union { @@ -156,6 +165,40 @@ typedef union { struct ble_mesh_set_fast_prov_action_args { uint8_t action; } set_fast_prov_action; + struct ble_mesh_lpn_enable_args { + /* RFU */ + } lpn_enable; + struct ble_mesh_lpn_disable_args { + bool force; + } lpn_disable; + struct ble_mesh_lpn_poll_args { + /* RFU */ + } lpn_poll; + struct ble_mesh_proxy_client_connect_args { + uint8_t addr[6]; + uint8_t addr_type; + uint16_t net_idx; + } proxy_client_connect; + struct ble_mesh_proxy_client_disconnect_args { + uint8_t conn_handle; + } proxy_client_disconnect; + struct ble_mesh_proxy_client_set_filter_type_args { + uint8_t conn_handle; + uint16_t net_idx; + uint8_t filter_type; + } proxy_client_set_filter_type; + struct ble_mesh_proxy_client_add_filter_addr_args { + uint8_t conn_handle; + uint16_t net_idx; + uint16_t addr_num; + uint16_t *addr; + } proxy_client_add_filter_addr; + struct ble_mesh_proxy_client_remove_filter_addr_args { + uint8_t conn_handle; + uint16_t net_idx; + uint16_t addr_num; + uint16_t *addr; + } proxy_client_remove_filter_addr; } btc_ble_mesh_prov_args_t; typedef union { @@ -173,10 +216,17 @@ typedef union { uint8_t device_role; int32_t msg_timeout; } model_send; + struct ble_mesh_server_model_update_state_args { + esp_ble_mesh_model_t *model; + esp_ble_mesh_server_state_type_t type; + esp_ble_mesh_server_state_value_t *value; + } model_update_state; } btc_ble_mesh_model_args_t; void btc_ble_mesh_prov_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_ble_mesh_model_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); + int btc_ble_mesh_client_model_init(esp_ble_mesh_model_t *model); int32_t btc_ble_mesh_model_pub_period_get(esp_ble_mesh_model_t *mod); diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_sensor_model.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_sensor_model.h index ea8cbbe22..8511fbcfa 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_sensor_model.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_sensor_model.h @@ -60,5 +60,19 @@ void bt_mesh_sensor_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, struct bt_mesh_msg_ctx *ctx, const u8_t *val, size_t len); +typedef enum { + BTC_BLE_MESH_EVT_SENSOR_SERVER_STATE_CHANGE, + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_SET_MSG, + BTC_BLE_MESH_EVT_SENSOR_SERVER_MAX, +} btc_ble_mesh_sensor_server_evt_t; + +void bt_mesh_sensor_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len); + +void btc_ble_mesh_sensor_server_cb_handler(btc_msg_t *msg); + #endif /* _BTC_BLE_MESH_SENSOR_MODEL_H_ */ diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_time_scene_model.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_time_scene_model.h index 74fe902da..e1d0d3ba7 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_time_scene_model.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_time_scene_model.h @@ -60,5 +60,20 @@ void bt_mesh_time_scene_client_cb_evt_to_btc(u32_t opcode, u8_t evt_type, struct bt_mesh_msg_ctx *ctx, const u8_t *val, size_t len); +typedef enum { + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_STATUS_MSG, + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_MAX, +} btc_ble_mesh_time_scene_server_evt_t; + +void bt_mesh_time_scene_server_cb_evt_to_btc(u8_t evt_type, + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const u8_t *val, size_t len); + +void btc_ble_mesh_time_scene_server_cb_handler(btc_msg_t *msg); + #endif /* _BTC_BLE_MESH_TIME_SCENE_MODEL_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_aes_encrypt.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_aes_encrypt.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_aes_encrypt.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_aes_encrypt.h diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_atomic.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_atomic.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_atomic.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_atomic.h diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_buf.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_buf.h similarity index 99% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_buf.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_buf.h index e6c62877e..6f1991dcc 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/mesh_buf.h +++ b/components/bt/esp_ble_mesh/mesh_common/include/mesh_buf.h @@ -544,8 +544,8 @@ struct net_buf { }; struct net_buf_data_cb { - u8_t * (*alloc)(struct net_buf *buf, size_t *size, s32_t timeout); - u8_t * (*ref)(struct net_buf *buf, u8_t *data); + u8_t *(*alloc)(struct net_buf *buf, size_t *size, s32_t timeout); + u8_t *(*ref)(struct net_buf *buf, u8_t *data); void (*unref)(struct net_buf *buf, u8_t *data); }; @@ -709,7 +709,7 @@ int net_buf_id(struct net_buf *buf); */ #if defined(CONFIG_BLE_MESH_NET_BUF_LOG) struct net_buf *net_buf_alloc_fixed_debug(struct net_buf_pool *pool, s32_t timeout, - const char *func, int line); + const char *func, int line); #define net_buf_alloc_fixed(_pool, _timeout) \ net_buf_alloc_fixed_debug(_pool, _timeout, __func__, __LINE__) #else diff --git a/components/bt/esp_ble_mesh/mesh_models/common/include/mesh_common.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_common.h similarity index 99% rename from components/bt/esp_ble_mesh/mesh_models/common/include/mesh_common.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_common.h index 2355bf0f3..dd058c70a 100644 --- a/components/bt/esp_ble_mesh/mesh_models/common/include/mesh_common.h +++ b/components/bt/esp_ble_mesh/mesh_common/include/mesh_common.h @@ -46,7 +46,7 @@ void bt_mesh_free_buf(struct net_buf_simple *buf); /** * @brief This function gets device role for stack internal use. - * + * * @Note Currently Provisioner only support client models, Node supports * client models and server models. Hence if srv_send is set to be * TRUE, then role NODE will be returned. diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_dlist.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_dlist.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_dlist.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_dlist.h diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_kernel.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_kernel.h similarity index 98% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_kernel.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_kernel.h index 785b8b8df..7d00d6426 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/mesh_kernel.h +++ b/components/bt/esp_ble_mesh/mesh_common/include/mesh_kernel.h @@ -182,6 +182,8 @@ struct k_delayed_work { */ int k_delayed_work_submit(struct k_delayed_work *work, s32_t delay); +int k_delayed_work_submit_periodic(struct k_delayed_work *work, s32_t period); + /** * @brief Get time remaining before a delayed work gets scheduled. * diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_slist.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_slist.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_slist.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_slist.h diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_trace.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_trace.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_trace.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_trace.h diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_types.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_types.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_types.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_types.h diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_util.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_util.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/include/mesh_util.h rename to components/bt/esp_ble_mesh/mesh_common/include/mesh_util.h diff --git a/components/bt/esp_ble_mesh/mesh_core/mesh_aes_encrypt.c b/components/bt/esp_ble_mesh/mesh_common/mesh_aes_encrypt.c similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/mesh_aes_encrypt.c rename to components/bt/esp_ble_mesh/mesh_common/mesh_aes_encrypt.c diff --git a/components/bt/esp_ble_mesh/mesh_core/mesh_atomic.c b/components/bt/esp_ble_mesh/mesh_common/mesh_atomic.c similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/mesh_atomic.c rename to components/bt/esp_ble_mesh/mesh_common/mesh_atomic.c diff --git a/components/bt/esp_ble_mesh/mesh_core/mesh_buf.c b/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c similarity index 96% rename from components/bt/esp_ble_mesh/mesh_core/mesh_buf.c rename to components/bt/esp_ble_mesh/mesh_common/mesh_buf.c index d6e0cd710..9e5f6c184 100644 --- a/components/bt/esp_ble_mesh/mesh_core/mesh_buf.c +++ b/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c @@ -310,7 +310,7 @@ void net_buf_unref(struct net_buf *buf) } #endif NET_BUF_DBG("buf %p ref %u pool %p frags %p", buf, buf->ref, - buf->pool, buf->frags); + buf->pool, buf->frags); /* Changed by Espressif. Add !buf->ref to avoid minus 0 */ if (!buf->ref || --buf->ref > 0) { @@ -325,7 +325,7 @@ void net_buf_unref(struct net_buf *buf) #if defined(CONFIG_BLE_MESH_NET_BUF_POOL_USAGE) pool->avail_count++; NET_BUF_DBG("%s, pool %p, avail_count %d, uninit_count %d", __func__, - pool, pool->avail_count, pool->uninit_count); + pool, pool->avail_count, pool->uninit_count); NET_BUF_ASSERT(pool->avail_count <= pool->buf_count); #endif @@ -366,10 +366,10 @@ static u8_t *data_alloc(struct net_buf *buf, size_t *size, s32_t timeout) #if defined(CONFIG_BLE_MESH_NET_BUF_LOG) struct net_buf *net_buf_alloc_len_debug(struct net_buf_pool *pool, size_t size, - s32_t timeout, const char *func, int line) + s32_t timeout, const char *func, int line) #else struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size, - s32_t timeout) + s32_t timeout) #endif { struct net_buf *buf = NULL; @@ -379,7 +379,7 @@ struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size, NET_BUF_ASSERT(pool); NET_BUF_DBG("%s, pool %p, uninit_count %d, buf_count %d", __func__, - pool, pool->uninit_count, pool->buf_count); + pool, pool->uninit_count, pool->buf_count); /* We need to lock interrupts temporarily to prevent race conditions * when accessing pool->uninit_count. @@ -436,8 +436,8 @@ success: #if defined(CONFIG_BLE_MESH_NET_BUF_LOG) struct net_buf *net_buf_alloc_fixed_debug(struct net_buf_pool *pool, - s32_t timeout, const char *func, - int line) + s32_t timeout, const char *func, + int line) { const struct net_buf_pool_fixed *fixed = pool->alloc->alloc_data; diff --git a/components/bt/esp_ble_mesh/mesh_models/common/mesh_common.c b/components/bt/esp_ble_mesh/mesh_common/mesh_common.c similarity index 100% rename from components/bt/esp_ble_mesh/mesh_models/common/mesh_common.c rename to components/bt/esp_ble_mesh/mesh_common/mesh_common.c diff --git a/components/bt/esp_ble_mesh/mesh_core/mesh_kernel.c b/components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c similarity index 86% rename from components/bt/esp_ble_mesh/mesh_core/mesh_kernel.c rename to components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c index 612d213d4..1ee0aa0d7 100644 --- a/components/bt/esp_ble_mesh/mesh_core/mesh_kernel.c +++ b/components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c @@ -39,25 +39,16 @@ typedef struct alarm_t { unsigned int bt_mesh_irq_lock(void) { -#if defined(CONFIG_BLE_MESH_IRQ_LOCK) && CONFIG_BLE_MESH_IRQ_LOCK - unsigned int key = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); - return key; -#else - /* Change by Espressif. In BLE Mesh, in order to improve the real-time - * requirements of bt controller, we use task lock to replace IRQ lock. + /* Changed by Espressif. In BLE Mesh, in order to improve the real-time + * requirements of bt controller, we use task lock instead of IRQ lock. */ osi_mutex_lock(&bm_irq_lock, OSI_MUTEX_MAX_TIMEOUT); return 0; -#endif } void bt_mesh_irq_unlock(unsigned int key) { -#if defined(CONFIG_BLE_MESH_IRQ_LOCK) && CONFIG_BLE_MESH_IRQ_LOCK - XTOS_RESTORE_INTLEVEL(key); -#else osi_mutex_unlock(&bm_irq_lock); -#endif } s64_t k_uptime_get(void) @@ -124,8 +115,7 @@ void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler) return; } -int k_delayed_work_submit(struct k_delayed_work *work, - s32_t delay) +int k_delayed_work_submit(struct k_delayed_work *work, s32_t delay) { assert(work != NULL && bm_alarm_hash_map != NULL); @@ -141,6 +131,23 @@ int k_delayed_work_submit(struct k_delayed_work *work, return 0; } +int k_delayed_work_submit_periodic(struct k_delayed_work *work, s32_t period) +{ + assert(work != NULL && bm_alarm_hash_map != NULL); + + osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work); + if (alarm == NULL) { + BT_WARN("%s, Unable to find expected alarm in hash map", __func__); + return -EINVAL; + } + + /* Cancel the alarm first before starting it. */ + osi_alarm_cancel(alarm); + osi_alarm_set_periodic(alarm, period); + + return 0; +} + int k_delayed_work_cancel(struct k_delayed_work *work) { assert(work != NULL && bm_alarm_hash_map != NULL); diff --git a/components/bt/esp_ble_mesh/mesh_core/mesh_util.c b/components/bt/esp_ble_mesh/mesh_common/mesh_util.c similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/mesh_util.c rename to components/bt/esp_ble_mesh/mesh_common/mesh_util.c diff --git a/components/bt/esp_ble_mesh/mesh_core/access.c b/components/bt/esp_ble_mesh/mesh_core/access.c index 55a6d25c3..43e6e746a 100644 --- a/components/bt/esp_ble_mesh/mesh_core/access.c +++ b/components/bt/esp_ble_mesh/mesh_core/access.c @@ -27,13 +27,18 @@ #include "transport.h" #include "access.h" #include "foundation.h" - #include "mesh_common.h" +#include "provisioner_main.h" + #include "generic_client.h" #include "sensor_client.h" #include "time_scene_client.h" #include "lighting_client.h" -#include "provisioner_main.h" + +#include "generic_server.h" +#include "sensor_server.h" +#include "time_scene_server.h" +#include "lighting_server.h" #define BLE_MESH_SDU_MAX_LEN 384 @@ -103,6 +108,41 @@ static const struct { #if defined(CONFIG_BLE_MESH_LIGHT_LC_CLI) { BLE_MESH_MODEL_ID_LIGHT_LC_CLI, bt_mesh_light_lc_cli_init }, #endif + { BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, bt_mesh_gen_onoff_srv_init }, + { BLE_MESH_MODEL_ID_GEN_LEVEL_SRV, bt_mesh_gen_level_srv_init }, + { BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV, bt_mesh_gen_def_trans_time_srv_init }, + { BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV, bt_mesh_gen_power_onoff_srv_init }, + { BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV, bt_mesh_gen_power_onoff_setup_srv_init }, + { BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV, bt_mesh_gen_power_level_srv_init }, + { BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV, bt_mesh_gen_power_level_setup_srv_init }, + { BLE_MESH_MODEL_ID_GEN_BATTERY_SRV, bt_mesh_gen_battery_srv_init }, + { BLE_MESH_MODEL_ID_GEN_LOCATION_SRV, bt_mesh_gen_location_srv_init }, + { BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV, bt_mesh_gen_location_setup_srv_init }, + { BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV, bt_mesh_gen_user_prop_srv_init }, + { BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV, bt_mesh_gen_admin_prop_srv_init }, + { BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV, bt_mesh_gen_manu_prop_srv_init }, + { BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV, bt_mesh_gen_client_prop_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, bt_mesh_light_lightness_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV, bt_mesh_light_lightness_setup_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_CTL_SRV, bt_mesh_light_ctl_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV, bt_mesh_light_ctl_setup_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV, bt_mesh_light_ctl_temp_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_HSL_SRV, bt_mesh_light_hsl_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV, bt_mesh_light_hsl_hue_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV, bt_mesh_light_hsl_sat_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV, bt_mesh_light_hsl_setup_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_XYL_SRV, bt_mesh_light_xyl_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV, bt_mesh_light_xyl_setup_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_LC_SRV, bt_mesh_light_lc_srv_init }, + { BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV, bt_mesh_light_lc_setup_srv_init }, + { BLE_MESH_MODEL_ID_TIME_SRV, bt_mesh_time_srv_init }, + { BLE_MESH_MODEL_ID_TIME_SETUP_SRV, bt_mesh_time_setup_srv_init }, + { BLE_MESH_MODEL_ID_SCENE_SRV, bt_mesh_scene_srv_init }, + { BLE_MESH_MODEL_ID_SCENE_SETUP_SRV, bt_mesh_scene_setup_srv_init }, + { BLE_MESH_MODEL_ID_SCHEDULER_SRV, bt_mesh_scheduler_srv_init }, + { BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV, bt_mesh_scheduler_setup_srv_init }, + { BLE_MESH_MODEL_ID_SENSOR_SRV, bt_mesh_sensor_srv_init }, + { BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV, bt_mesh_sensor_setup_srv_init }, }; void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, @@ -683,7 +723,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) if (buf->len < op->min_len) { BT_ERR("%s, Too short message for OpCode 0x%08x", - __func__, opcode); + __func__, opcode); continue; } diff --git a/components/bt/esp_ble_mesh/mesh_core/adv.c b/components/bt/esp_ble_mesh/mesh_core/adv.c index 05de51782..1c2fff551 100644 --- a/components/bt/esp_ble_mesh/mesh_core/adv.c +++ b/components/bt/esp_ble_mesh/mesh_core/adv.c @@ -30,10 +30,10 @@ #include "foundation.h" #include "beacon.h" #include "prov.h" -#include "proxy.h" +#include "proxy_server.h" #include "provisioner_prov.h" -#include "provisioner_proxy.h" +#include "proxy_client.h" #include "provisioner_beacon.h" /* Convert from ms to 0.625ms units */ @@ -55,7 +55,6 @@ #define ADV_STACK_SIZE 768 #endif -static xQueueHandle xBleMeshQueue; static const bt_mesh_addr_t *dev_addr; static const u8_t adv_type[] = { @@ -70,6 +69,27 @@ NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT + 3 * CONFIG_BLE static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT + 3 * CONFIG_BLE_MESH_PBA_SAME_TIME]; +static QueueHandle_t xBleMeshQueue; +#define BLE_MESH_QUEUE_SIZE 150 + +#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) +NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; + +static QueueHandle_t xBleMeshRelayQueue; +#define BLE_MESH_RELAY_QUEUE_SIZE 150 + +static QueueSetHandle_t xBleMeshQueueSet; +#define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE) + +#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) +#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF + +static bool ignore_relay_packet(u32_t timestamp); +#endif /* defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */ + static struct bt_mesh_adv *adv_alloc(int id) { return &adv_pool[id]; @@ -106,7 +126,7 @@ static inline int adv_send(struct net_buf *buf) adv_int = MAX(adv_int_min, BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit)); duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) * - (adv_int + 10); + (adv_int + 10); BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, bt_hex(buf->data, buf->len)); @@ -147,48 +167,111 @@ static inline int adv_send(struct net_buf *buf) static void adv_thread(void *p) { - struct net_buf **buf = NULL; +#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) + QueueSetMemberHandle_t handle; +#endif bt_mesh_msg_t msg = {0}; - int status; - - BT_DBG("started"); + struct net_buf **buf; buf = (struct net_buf **)(&msg.arg); + BT_DBG("%s, starts", __func__); + while (1) { *buf = NULL; +#if !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) #if CONFIG_BLE_MESH_NODE if (IS_ENABLED(CONFIG_BLE_MESH_PROXY)) { xQueueReceive(xBleMeshQueue, &msg, K_NO_WAIT); while (!(*buf)) { s32_t timeout; - BT_DBG("Proxy advertising start"); + BT_DBG("Mesh Proxy Advertising start"); timeout = bt_mesh_proxy_adv_start(); - BT_DBG("Proxy Advertising up to %d ms", timeout); + BT_DBG("Mesh Proxy Advertising up to %d ms", timeout); xQueueReceive(xBleMeshQueue, &msg, timeout); - BT_DBG("Proxy advertising stop"); + BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_adv_stop(); } } else { - xQueueReceive(xBleMeshQueue, &msg, (portTickType)portMAX_DELAY); + xQueueReceive(xBleMeshQueue, &msg, portMAX_DELAY); } #else - xQueueReceive(xBleMeshQueue, &msg, (portTickType)portMAX_DELAY); + xQueueReceive(xBleMeshQueue, &msg, portMAX_DELAY); #endif +#else /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */ +#if CONFIG_BLE_MESH_NODE + if (IS_ENABLED(CONFIG_BLE_MESH_PROXY)) { + handle = xQueueSelectFromSet(xBleMeshQueueSet, K_NO_WAIT); + if (handle) { + if (uxQueueMessagesWaiting(xBleMeshQueue)) { + xQueueReceive(xBleMeshQueue, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(xBleMeshRelayQueue)) { + xQueueReceive(xBleMeshRelayQueue, &msg, K_NO_WAIT); + } + } else { + while (!(*buf)) { + s32_t timeout; + BT_DBG("Mesh Proxy Advertising start"); + timeout = bt_mesh_proxy_adv_start(); + BT_DBG("Mesh Proxy Advertising up to %d ms", timeout); + handle = xQueueSelectFromSet(xBleMeshQueueSet, timeout); + BT_DBG("Mesh Proxy Advertising stop"); + bt_mesh_proxy_adv_stop(); + if (handle) { + if (uxQueueMessagesWaiting(xBleMeshQueue)) { + xQueueReceive(xBleMeshQueue, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(xBleMeshRelayQueue)) { + xQueueReceive(xBleMeshRelayQueue, &msg, K_NO_WAIT); + } + } + } + } + } else { + handle = xQueueSelectFromSet(xBleMeshQueueSet, portMAX_DELAY); + if (handle) { + if (uxQueueMessagesWaiting(xBleMeshQueue)) { + xQueueReceive(xBleMeshQueue, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(xBleMeshRelayQueue)) { + xQueueReceive(xBleMeshRelayQueue, &msg, K_NO_WAIT); + } + } + } +#else + handle = xQueueSelectFromSet(xBleMeshQueueSet, portMAX_DELAY); + if (handle) { + if (uxQueueMessagesWaiting(xBleMeshQueue)) { + xQueueReceive(xBleMeshQueue, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(xBleMeshRelayQueue)) { + xQueueReceive(xBleMeshRelayQueue, &msg, K_NO_WAIT); + } + } +#endif +#endif /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */ - if (!(*buf)) { + if (*buf == NULL) { continue; } /* busy == 0 means this was canceled */ if (BLE_MESH_ADV(*buf)->busy) { BLE_MESH_ADV(*buf)->busy = 0U; - status = adv_send(*buf); - if (status) { - if (xQueueSendToFront(xBleMeshQueue, &msg, K_NO_WAIT) != pdTRUE) { - BT_ERR("%s, xQueueSendToFront failed", __func__); +#if !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) + if (adv_send(*buf)) { + BT_WARN("%s, Failed to send adv packet", __func__); + } +#else /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */ + if (msg.relay && ignore_relay_packet(msg.timestamp)) { + /* If the interval between "current time - msg.timestamp" is bigger than + * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. + */ + BT_DBG("%s, Ignore relay packet", __func__); + net_buf_unref(*buf); + } else { + if (adv_send(*buf)) { + BT_WARN("%s, Failed to send adv packet", __func__); } } +#endif } else { net_buf_unref(*buf); } @@ -198,13 +281,6 @@ static void adv_thread(void *p) } } -void bt_mesh_adv_update(void) -{ - BT_DBG("%s", __func__); - bt_mesh_msg_t msg = {0}; - bt_mesh_task_post(&msg, 0); -} - struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, bt_mesh_adv_alloc_t get_id, enum bt_mesh_adv_type type, @@ -224,7 +300,7 @@ struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, } BT_DBG("%s, pool = %p, buf_count = %d, uinit_count = %d", __func__, - buf->pool, pool->buf_count, pool->uninit_count); + buf->pool, pool->buf_count, pool->uninit_count); adv = get_id(net_buf_id(buf)); BLE_MESH_ADV(buf) = adv; @@ -244,17 +320,35 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit, xmit, timeout); } -void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout) +static void bt_mesh_unref_buf(bt_mesh_msg_t *msg) +{ + struct net_buf *buf; + + if (msg->arg) { + buf = (struct net_buf *)msg->arg; + BLE_MESH_ADV(buf)->busy = 0U; + net_buf_unref(buf); + } + + return; +} + +static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout) { BT_DBG("%s", __func__); if (xQueueSend(xBleMeshQueue, msg, timeout) != pdTRUE) { - BT_ERR("%s, Failed to post msg to queue", __func__); + BT_ERR("%s, Failed to send item to queue", __func__); + bt_mesh_unref_buf(msg); } } void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, void *cb_data) { + bt_mesh_msg_t msg = { + .relay = false, + }; + BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, bt_hex(buf->data, buf->len)); @@ -262,21 +356,228 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, BLE_MESH_ADV(buf)->cb_data = cb_data; BLE_MESH_ADV(buf)->busy = 1U; - bt_mesh_msg_t msg = {0}; msg.arg = (void *)net_buf_ref(buf); bt_mesh_task_post(&msg, portMAX_DELAY); } +void bt_mesh_adv_update(void) +{ + bt_mesh_msg_t msg = { + .relay = false, + .arg = NULL, + }; + + BT_DBG("%s", __func__); + + bt_mesh_task_post(&msg, K_NO_WAIT); +} + +#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) +static bool ignore_relay_packet(u32_t timestamp) +{ + u32_t now = k_uptime_get_32(); + u32_t interval; + + if (now > timestamp) { + interval = now - timestamp; + } else if (now == timestamp) { + interval = BLE_MESH_MAX_TIME_INTERVAL; + } else { + interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; + } + + return (interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false; +} + +static struct bt_mesh_adv *relay_adv_alloc(int id) +{ + return &relay_adv_pool[id]; +} + +struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, u8_t xmit, + s32_t timeout) +{ + return bt_mesh_adv_create_from_pool(&relay_adv_buf_pool, relay_adv_alloc, type, + xmit, timeout); +} + +static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout) +{ + QueueSetMemberHandle_t handle; + bt_mesh_msg_t old_msg = {0}; + + BT_DBG("%s", __func__); + + if (xQueueSend(xBleMeshRelayQueue, msg, timeout) == pdTRUE) { + return; + } + + /** + * If failed to send packet to the relay queue(queue is full), we will + * remove the oldest packet in the queue and put the new one into it. + */ + handle = xQueueSelectFromSet(xBleMeshQueueSet, K_NO_WAIT); + if (handle && uxQueueMessagesWaiting(xBleMeshRelayQueue)) { + BT_DBG("%s, Full queue, remove the oldest relay packet", __func__); + /* Remove the oldest relay packet from queue */ + if (xQueueReceive(xBleMeshRelayQueue, &old_msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("%s, Failed to remove item from queue", __func__); + bt_mesh_unref_buf(msg); + return; + } + /* Unref buf used for the oldest relay packet */ + bt_mesh_unref_buf(&old_msg); + /* Send the latest relay packet to queue */ + if (xQueueSend(xBleMeshRelayQueue, msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("%s, Failed to send item to relay queue", __func__); + bt_mesh_unref_buf(msg); + return; + } + } else { + BT_WARN("%s, Empty queue, but failed to send the relay packet", __func__); + bt_mesh_unref_buf(msg); + } +} + +void bt_mesh_relay_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, + void *cb_data, u16_t src, u16_t dst) +{ + bt_mesh_msg_t msg = { + .relay = true, + }; + + BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, + bt_hex(buf->data, buf->len)); + + BLE_MESH_ADV(buf)->cb = cb; + BLE_MESH_ADV(buf)->cb_data = cb_data; + BLE_MESH_ADV(buf)->busy = 1U; + + msg.arg = (void *)net_buf_ref(buf); + msg.src = src; + msg.dst = dst; + msg.timestamp = k_uptime_get_32(); + /* Use K_NO_WAIT here, if xBleMeshRelayQueue is full return immediately */ + ble_mesh_relay_task_post(&msg, K_NO_WAIT); +} + +u16_t bt_mesh_get_stored_relay_count(void) +{ + return (u16_t)uxQueueMessagesWaiting(xBleMeshRelayQueue); +} +#endif /* #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */ + const bt_mesh_addr_t *bt_mesh_pba_get_addr(void) { return dev_addr; } +#if (CONFIG_BLE_MESH_PROVISIONER && COFNIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT +static bool bt_mesh_is_adv_flags_valid(struct net_buf_simple *buf) +{ + u8_t flags; + + if (buf->len != 1U) { + BT_DBG("%s, Unexpected flags length", __func__); + return false; + } + + flags = net_buf_simple_pull_u8(buf); + + BT_DBG("Received adv pkt with flags: 0x%02x", flags); + + /* Flags context will not be checked curently */ + + return true; +} + +static bool bt_mesh_is_adv_srv_uuid_valid(struct net_buf_simple *buf, u16_t *uuid) +{ + if (buf->len != 2U) { + BT_DBG("Length not match mesh service uuid"); + return false; + } + + *uuid = net_buf_simple_pull_le16(buf); + + BT_DBG("Received adv pkt with service UUID: %d", *uuid); + + if (*uuid != BLE_MESH_UUID_MESH_PROV_VAL && + *uuid != BLE_MESH_UUID_MESH_PROXY_VAL) { + return false; + } + + if (*uuid == BLE_MESH_UUID_MESH_PROV_VAL && + bt_mesh_is_provisioner_en() == false) { + return false; + } + + if (*uuid == BLE_MESH_UUID_MESH_PROXY_VAL && + !IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) { + return false; + } + + return true; +} + +#define BLE_MESH_PROV_SRV_DATA_LEN 0x12 +#define BLE_MESH_PROXY_SRV_DATA_LEN1 0x09 +#define BLE_MESH_PROXY_SRV_DATA_LEN2 0x11 + +static void bt_mesh_adv_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr, u16_t uuid) +{ + u16_t type; + + if (!buf || !addr) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + type = net_buf_simple_pull_le16(buf); + if (type != uuid) { + BT_DBG("%s, Invalid Mesh Service Data UUID 0x%04x", __func__, type); + return; + } + + switch (type) { +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + case BLE_MESH_UUID_MESH_PROV_VAL: + if (bt_mesh_is_provisioner_en()) { + if (buf->len != BLE_MESH_PROV_SRV_DATA_LEN) { + BT_WARN("%s, Invalid Mesh Prov Service Data length %d", __func__, buf->len); + return; + } + + BT_DBG("Start to handle Mesh Prov Service Data"); + provisioner_prov_adv_ind_recv(buf, addr); + } + break; +#endif +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + case BLE_MESH_UUID_MESH_PROXY_VAL: + if (buf->len != BLE_MESH_PROXY_SRV_DATA_LEN1 && + buf->len != BLE_MESH_PROXY_SRV_DATA_LEN2) { + BT_WARN("%s, Invalid Mesh Proxy Service Data length %d", __func__, buf->len); + return; + } + + BT_DBG("Start to handle Mesh Proxy Service Data"); + proxy_client_adv_ind_recv(buf, addr); + break; +#endif + default: + break; + } +} +#endif + static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi, u8_t adv_type, struct net_buf_simple *buf) { -#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT - u16_t uuid = 0; +#if (CONFIG_BLE_MESH_PROVISIONER && COFNIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT + u16_t uuid; #endif if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) { @@ -311,9 +612,9 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi, #if 0 /* TODO: Check with BLE Mesh BQB test cases */ if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE || - type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) { + type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) { BT_DBG("%s, ignore BLE Mesh packet (type 0x%02x) with adv_type 0x%02x", - __func__, type, adv_type); + __func__, type, adv_type); return; } #endif @@ -348,30 +649,24 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi, } #endif break; -#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT +#if (CONFIG_BLE_MESH_PROVISIONER && COFNIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT case BLE_MESH_DATA_FLAGS: - if (bt_mesh_is_provisioner_en()) { - if (!provisioner_flags_match(buf)) { - BT_DBG("Flags mismatch, ignore this adv pkt"); - return; - } + if (!bt_mesh_is_adv_flags_valid(buf)) { + BT_DBG("Adv Flags mismatch, ignore this adv pkt"); + return; } break; case BLE_MESH_DATA_UUID16_ALL: - if (bt_mesh_is_provisioner_en()) { - uuid = provisioner_srv_uuid_recv(buf); - if (!uuid) { - BT_DBG("Service UUID mismatch, ignore this adv pkt"); - return; - } + if (!bt_mesh_is_adv_srv_uuid_valid(buf, &uuid)) { + BT_DBG("Adv Service UUID mismatch, ignore this adv pkt"); + return; } break; case BLE_MESH_DATA_SVC_DATA16: - if (bt_mesh_is_provisioner_en()) { - provisioner_srv_data_recv(buf, addr, uuid); - } + bt_mesh_adv_srv_data_recv(buf, addr, uuid); break; -#endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */ +#endif default: break; } @@ -385,10 +680,18 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi, void bt_mesh_adv_init(void) { - xBleMeshQueue = xQueueCreate(150, sizeof(bt_mesh_msg_t)); + xBleMeshQueue = xQueueCreate(BLE_MESH_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); configASSERT(xBleMeshQueue); +#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) + xBleMeshRelayQueue = xQueueCreate(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); + configASSERT(xBleMeshRelayQueue); + xBleMeshQueueSet = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE); + configASSERT(xBleMeshQueueSet); + xQueueAddToSet(xBleMeshQueue, xBleMeshQueueSet); + xQueueAddToSet(xBleMeshRelayQueue, xBleMeshQueueSet); +#endif /* defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */ int ret = xTaskCreatePinnedToCore(adv_thread, "BLE_Mesh_ADV_Task", 3072, NULL, - configMAX_PRIORITIES - 7, NULL, ADV_TASK_CORE); + configMAX_PRIORITIES - 7, NULL, ADV_TASK_CORE); configASSERT(ret == pdTRUE); } diff --git a/components/bt/esp_ble_mesh/mesh_core/adv.h b/components/bt/esp_ble_mesh/mesh_core/adv.h index b827af59e..9762de62e 100644 --- a/components/bt/esp_ble_mesh/mesh_core/adv.h +++ b/components/bt/esp_ble_mesh/mesh_core/adv.h @@ -21,11 +21,11 @@ #define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) typedef struct bt_mesh_msg { - uint8_t sig; //event signal - uint8_t aid; //application id - uint8_t pid; //profile id - uint8_t act; //profile action, defined in seprerate header files - void *arg; //param for btc function or function param + bool relay; /* Flag indicates if the packet is a relayed one */ + void *arg; /* Pointer to the struct net_buf */ + u16_t src; /* Source address for relay packets */ + u16_t dst; /* Destination address for relay packets */ + u32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */ } bt_mesh_msg_t; enum bt_mesh_adv_type { @@ -73,6 +73,14 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, const bt_mesh_addr_t *bt_mesh_pba_get_addr(void); +struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, u8_t xmit, + s32_t timeout); + +void bt_mesh_relay_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, + void *cb_data, u16_t src, u16_t dst); + +u16_t bt_mesh_get_stored_relay_count(void); + void bt_mesh_adv_update(void); void bt_mesh_adv_init(void); @@ -81,6 +89,4 @@ int bt_mesh_scan_enable(void); int bt_mesh_scan_disable(void); -void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout); - #endif /* _ADV_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/beacon.c b/components/bt/esp_ble_mesh/mesh_core/beacon.c index a62cf073a..4ba6c0281 100644 --- a/components/bt/esp_ble_mesh/mesh_core/beacon.c +++ b/components/bt/esp_ble_mesh/mesh_core/beacon.c @@ -25,6 +25,7 @@ #include "crypto.h" #include "beacon.h" #include "foundation.h" +#include "proxy_client.h" #if CONFIG_BLE_MESH_NODE @@ -138,6 +139,18 @@ static int secure_beacon_send(void) continue; } + /** + * If a node enables the Proxy Client functionality, and it + * succeeds to send Secure Network Beacon with GATT bearer, + * here we will continue to send Secure Network Beacon of + * other subnets. + */ +#if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) + if (bt_mesh_proxy_client_beacon_send(sub)) { + continue; + } +#endif + buf = bt_mesh_adv_create(BLE_MESH_ADV_BEACON, PROV_XMIT, K_NO_WAIT); if (!buf) { diff --git a/components/bt/esp_ble_mesh/mesh_core/bluedroid_host/mesh_bearer_adapt.c b/components/bt/esp_ble_mesh/mesh_core/bluedroid_host/mesh_bearer_adapt.c index 9b5ed3ca5..bf22f102a 100644 --- a/components/bt/esp_ble_mesh/mesh_core/bluedroid_host/mesh_bearer_adapt.c +++ b/components/bt/esp_ble_mesh/mesh_core/bluedroid_host/mesh_bearer_adapt.c @@ -47,7 +47,7 @@ struct bt_mesh_dev bt_mesh_dev; #define BLE_MESH_GATT_GET_CONN_ID(conn_id) (((u16_t)(conn_id)) >> 8) #define BLE_MESH_GATT_CREATE_CONN_ID(gatt_if, conn_id) ((u16_t)((((u8_t)(conn_id)) << 8) | ((u8_t)(gatt_if)))) -/* We don't need to manage the BLE_MESH_DEV_ADVERTISING flags in the version of bluedriod, +/* We don't need to manage the BLE_MESH_DEV_ADVERTISING flags in the version of bluedriod, * it will manage it in the BTM layer. */ #define BLE_MESH_DEV 0 @@ -81,13 +81,13 @@ static future_t *future_mesh; static struct bt_mesh_gatt_attr *bt_mesh_gatts_find_attr_by_handle(u16_t handle); #endif /* defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE */ -#if defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT #define BLE_MESH_GATTC_APP_UUID_BYTE 0x97 static struct gattc_prov_info { /* Service to be found depends on the type of adv pkt received */ struct bt_mesh_conn conn; - BD_ADDR addr; - u8_t addr_type; + bt_mesh_addr_t addr; u16_t service_uuid; u16_t mtu; bool wr_desc_done; /* Indicate if write char descriptor event is received */ @@ -99,7 +99,7 @@ static struct gattc_prov_info { } bt_mesh_gattc_info[BLE_MESH_MAX_CONN]; static struct bt_mesh_prov_conn_cb *bt_mesh_gattc_conn_cb; static tBTA_GATTC_IF bt_mesh_gattc_if; -#endif /* defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER */ +#endif esp_err_t bt_mesh_host_init(void) { @@ -136,7 +136,7 @@ void bt_mesh_hci_init(void) } static void bt_mesh_scan_results_change_2_bta(tBTM_INQ_RESULTS *p_inq, u8_t *p_eir, - tBTA_DM_SEARCH_CBACK *p_scan_cback) + tBTA_DM_SEARCH_CBACK *p_scan_cback) { tBTM_INQ_INFO *p_inq_info; tBTA_DM_SEARCH result; @@ -512,9 +512,9 @@ static void bt_mesh_bta_gatts_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) if (attr != NULL && attr->write != NULL) { if ((len = attr->write(&bt_mesh_gatts_conn[index], attr, - p_data->req_data.p_data->write_req.value, - p_data->req_data.p_data->write_req.len, - p_data->req_data.p_data->write_req.offset, 0)) > 0) { + p_data->req_data.p_data->write_req.value, + p_data->req_data.p_data->write_req.len, + p_data->req_data.p_data->write_req.offset, 0)) > 0) { if (p_data->req_data.p_data->write_req.need_rsp) { BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, p_data->req_data.status, NULL); @@ -627,7 +627,7 @@ static struct bt_mesh_gatt_attr *bt_mesh_gatts_find_attr_by_handle(u16_t handle) } static void bt_mesh_gatts_foreach_attr(u16_t start_handle, u16_t end_handle, - bt_mesh_gatt_attr_func_t func, void *user_data) + bt_mesh_gatt_attr_func_t func, void *user_data) { struct bt_mesh_gatt_service *svc = NULL; @@ -694,8 +694,8 @@ struct gatts_incl { } __packed; ssize_t bt_mesh_gatts_attr_read_included(struct bt_mesh_conn *conn, - const struct bt_mesh_gatt_attr *attr, - void *buf, u16_t len, u16_t offset) + const struct bt_mesh_gatt_attr *attr, + void *buf, u16_t len, u16_t offset) { struct bt_mesh_gatt_attr *incl = attr->user_data; struct bt_mesh_uuid *uuid = incl->user_data; @@ -731,7 +731,7 @@ ssize_t bt_mesh_gatts_attr_read_service(struct bt_mesh_conn *conn, } return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, - BLE_MESH_UUID_128(uuid)->val, 16); + BLE_MESH_UUID_128(uuid)->val, 16); } struct gatts_chrc { @@ -1013,27 +1013,40 @@ int bt_mesh_gatts_service_start(struct bt_mesh_gatt_service *svc) } #endif /* defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE */ -#if defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT void bt_mesh_gattc_conn_cb_register(struct bt_mesh_prov_conn_cb *cb) { bt_mesh_gattc_conn_cb = cb; } -u16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn) +u8_t bt_mesh_gattc_get_free_conn_count(void) { - int i; + u8_t count = 0; + u8_t i; - for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (conn == &bt_mesh_gattc_info[i].conn) { - break; + for (i = 0U; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + if (bt_mesh_gattc_info[i].conn.handle == 0xFFFF && + bt_mesh_gattc_info[i].service_uuid == 0x0000) { + ++count; } } - if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { - return 0; + return count; +} + +u16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn) +{ + u8_t i; + + for (i = 0U; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + if (conn == &bt_mesh_gattc_info[i].conn) { + return bt_mesh_gattc_info[i].service_uuid; + } } - return bt_mesh_gattc_info[i].service_uuid; + BT_ERR("%s, Conn is not found", __func__); + return 0; } /** For provisioner acting as a GATT client, it may follow the procedures @@ -1052,22 +1065,22 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid) int i; if (!addr || !memcmp(addr->val, zero, BLE_MESH_ADDR_LEN) || - (addr->type > BLE_ADDR_RANDOM)) { + (addr->type > BLE_ADDR_RANDOM)) { BT_ERR("%s, Invalid remote address", __func__); return -EINVAL; } if (service_uuid != BLE_MESH_UUID_MESH_PROV_VAL && - service_uuid != BLE_MESH_UUID_MESH_PROXY_VAL) { + service_uuid != BLE_MESH_UUID_MESH_PROXY_VAL) { BT_ERR("%s, Invalid service uuid 0x%04x", __func__, service_uuid); return -EINVAL; } /* Check if already creating connection with the device */ for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (!memcmp(bt_mesh_gattc_info[i].addr, addr->val, BLE_MESH_ADDR_LEN)) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, addr->val, BLE_MESH_ADDR_LEN)) { BT_WARN("%s, Already create connection with %s", - __func__, bt_hex(addr->val, BLE_MESH_ADDR_LEN)); + __func__, bt_hex(addr->val, BLE_MESH_ADDR_LEN)); return -EALREADY; } } @@ -1075,9 +1088,9 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid) /* Find empty element in queue to store device info */ for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if ((bt_mesh_gattc_info[i].conn.handle == 0xFFFF) && - (bt_mesh_gattc_info[i].service_uuid == 0x0000)) { - memcpy(bt_mesh_gattc_info[i].addr, addr->val, BLE_MESH_ADDR_LEN); - bt_mesh_gattc_info[i].addr_type = addr->type; + (bt_mesh_gattc_info[i].service_uuid == 0x0000)) { + memcpy(bt_mesh_gattc_info[i].addr.val, addr->val, BLE_MESH_ADDR_LEN); + bt_mesh_gattc_info[i].addr.type = addr->type; /* Service to be found after exhanging mtu size */ bt_mesh_gattc_info[i].service_uuid = service_uuid; break; @@ -1104,15 +1117,12 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid) * Slave_latency: 0x0 * Supervision_timeout: 32 sec */ - BTA_DmSetBlePrefConnParams(bt_mesh_gattc_info[i].addr, 0xC8, 0xC8, 0x00, 0xC80); + BTA_DmSetBlePrefConnParams(bt_mesh_gattc_info[i].addr.val, 0xC8, 0xC8, 0x00, 0xC80); - BTA_GATTC_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr, - bt_mesh_gattc_info[i].addr_type, true, BTA_GATT_TRANSPORT_LE); + BTA_GATTC_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, + bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE); - /* Increment pbg_count */ - provisioner_pbg_count_inc(); - - return 0; + return i; } void bt_mesh_gattc_exchange_mtu(u8_t index) @@ -1149,24 +1159,16 @@ int bt_mesh_gattc_write_no_rsp(struct bt_mesh_conn *conn, const struct bt_mesh_g for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (conn == &bt_mesh_gattc_info[i].conn) { - break; + conn_id = BLE_MESH_GATT_CREATE_CONN_ID(bt_mesh_gattc_if, bt_mesh_gattc_info[i].conn.handle); + BTA_GATTC_WriteCharValue(conn_id, bt_mesh_gattc_info[i].data_in_handle, + BTA_GATTC_TYPE_WRITE_NO_RSP, len, + (u8_t *)data, BTA_GATT_AUTH_REQ_NONE); + return 0; } } - if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { - BT_ERR("%s, Conn is not found", __func__); - /** Here we return 0 for prov_send() return value check in provisioner.c - */ - return 0; - } - - conn_id = BLE_MESH_GATT_CREATE_CONN_ID(bt_mesh_gattc_if, bt_mesh_gattc_info[i].conn.handle); - - BTA_GATTC_WriteCharValue(conn_id, bt_mesh_gattc_info[i].data_in_handle, - BTA_GATTC_TYPE_WRITE_NO_RSP, len, - (u8_t *)data, BTA_GATT_AUTH_REQ_NONE); - - return 0; + BT_ERR("%s, Conn is not found", __func__); + return -EEXIST; } void bt_mesh_gattc_disconnect(struct bt_mesh_conn *conn) @@ -1184,18 +1186,14 @@ void bt_mesh_gattc_disconnect(struct bt_mesh_conn *conn) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (conn == &bt_mesh_gattc_info[i].conn) { - break; + conn_id = BLE_MESH_GATT_CREATE_CONN_ID(bt_mesh_gattc_if, bt_mesh_gattc_info[i].conn.handle); + BTA_GATTC_Close(conn_id); + return; } } - if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { - BT_ERR("%s, Conn is not found", __func__); - return; - } - - conn_id = BLE_MESH_GATT_CREATE_CONN_ID(bt_mesh_gattc_if, bt_mesh_gattc_info[i].conn.handle); - - BTA_GATTC_Close(conn_id); + BT_ERR("%s, Conn is not found", __func__); + return; } /** Mesh Provisioning Service: 0x1827 @@ -1235,25 +1233,16 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].conn.handle == handle) { bt_mesh_gattc_info[i].mtu = p_data->cfg_mtu.mtu; + + /* Search Mesh Provisioning Service or Mesh Proxy Service */ + tBT_UUID service_uuid = { + .len = sizeof(bt_mesh_gattc_info[i].service_uuid), + .uu.uuid16 = bt_mesh_gattc_info[i].service_uuid, + }; + BTA_GATTC_ServiceSearchRequest(p_data->cfg_mtu.conn_id, &service_uuid); break; } } - - /** Once mtu exchanged accomplished, start to find services, and here - * need a flag to indicate which service to find(Mesh Prov Service or - * Mesh Proxy Service) - */ - if (i != ARRAY_SIZE(bt_mesh_gattc_info)) { - tBT_UUID service_uuid; - u16_t conn_id; - - conn_id = BLE_MESH_GATT_CREATE_CONN_ID(bt_mesh_gattc_if, bt_mesh_gattc_info[i].conn.handle); - service_uuid.len = sizeof(bt_mesh_gattc_info[i].service_uuid); - service_uuid.uu.uuid16 = bt_mesh_gattc_info[i].service_uuid; - - /* Search Mesh Provisioning Service or Mesh Proxy Service */ - BTA_GATTC_ServiceSearchRequest(conn_id, &service_uuid); - } } break; } @@ -1264,17 +1253,14 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].conn.handle == handle) { + if (p_data->srvc_res.service_uuid.uuid.len == 2 && + p_data->srvc_res.service_uuid.uuid.uu.uuid16 == bt_mesh_gattc_info[i].service_uuid) { + bt_mesh_gattc_info[i].start_handle = p_data->srvc_res.start_handle; + bt_mesh_gattc_info[i].end_handle = p_data->srvc_res.end_handle; + } break; } } - - if (i != ARRAY_SIZE(bt_mesh_gattc_info)) { - if (p_data->srvc_res.service_uuid.uuid.len == 2 && - p_data->srvc_res.service_uuid.uuid.uu.uuid16 == bt_mesh_gattc_info[i].service_uuid) { - bt_mesh_gattc_info[i].start_handle = p_data->srvc_res.start_handle; - bt_mesh_gattc_info[i].end_handle = p_data->srvc_res.end_handle; - } - } break; } case BTA_GATTC_SEARCH_CMPL_EVT: { @@ -1285,37 +1271,35 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].conn.handle == handle) { + conn = &bt_mesh_gattc_info[i].conn; break; } } - if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + if (conn == NULL) { BT_ERR("%s, Conn handle is not found", __func__); return; } - conn = &bt_mesh_gattc_info[i].conn; - if (bt_mesh_gattc_info[i].start_handle == 0x00 || - bt_mesh_gattc_info[i].end_handle == 0x00 || + bt_mesh_gattc_info[i].end_handle == 0x00 || (bt_mesh_gattc_info[i].start_handle > bt_mesh_gattc_info[i].end_handle)) { bt_mesh_gattc_disconnect(conn); return; } + u16_t notify_en = BLE_MESH_GATT_CCC_NOTIFY; + btgatt_db_element_t *result = NULL; + tBT_UUID char_uuid = {0}; + tBTA_GATT_STATUS status; + tBTA_GATT_UNFMT write; int count = 0; int num = 0; - u16_t conn_id; - tBT_UUID char_uuid; - btgatt_db_element_t *result = NULL; - tBTA_GATT_STATUS status; - u16_t notify_en = BLE_MESH_GATT_CCC_NOTIFY; - tBTA_GATT_UNFMT write; /* Get the characteristic num within Mesh Provisioning/Proxy Service */ - conn_id = BLE_MESH_GATT_CREATE_CONN_ID(bt_mesh_gattc_if, bt_mesh_gattc_info[i].conn.handle); - BTA_GATTC_GetDBSizeByType(conn_id, BTGATT_DB_CHARACTERISTIC, bt_mesh_gattc_info[i].start_handle, - bt_mesh_gattc_info[i].end_handle, BTA_GATTC_INVALID_HANDLE, &count); + BTA_GATTC_GetDBSizeByType(p_data->search_cmpl.conn_id, BTGATT_DB_CHARACTERISTIC, + bt_mesh_gattc_info[i].start_handle, bt_mesh_gattc_info[i].end_handle, + BTA_GATTC_INVALID_HANDLE, &count); if (count != 2) { bt_mesh_gattc_disconnect(conn); return; @@ -1333,7 +1317,7 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) char_uuid.uu.uuid16 = BLE_MESH_UUID_MESH_PROXY_DATA_IN_VAL + j; } - BTA_GATTC_GetCharByUUID(conn_id, bt_mesh_gattc_info[i].start_handle, + BTA_GATTC_GetCharByUUID(p_data->search_cmpl.conn_id, bt_mesh_gattc_info[i].start_handle, bt_mesh_gattc_info[i].end_handle, char_uuid, &result, &num); if (!result) { @@ -1362,12 +1346,13 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) } bt_mesh_gattc_info[i].data_out_handle = result[0].attribute_handle; } + osi_free(result); result = NULL; } /* Register Notification fot Mesh Provisioning/Proxy Data Out Characteristic */ - status = BTA_GATTC_RegisterForNotifications(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr, + status = BTA_GATTC_RegisterForNotifications(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, bt_mesh_gattc_info[i].data_out_handle); if (status != BTA_GATT_OK) { bt_mesh_gattc_disconnect(conn); @@ -1377,8 +1362,9 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) /** After notification is registered, get descriptor number of the * Mesh Provisioning/Proxy Data Out Characteristic */ - BTA_GATTC_GetDBSizeByType(conn_id, BTGATT_DB_DESCRIPTOR, bt_mesh_gattc_info[i].start_handle, - bt_mesh_gattc_info[i].end_handle, bt_mesh_gattc_info[i].data_out_handle, &num); + BTA_GATTC_GetDBSizeByType(p_data->search_cmpl.conn_id, BTGATT_DB_DESCRIPTOR, + bt_mesh_gattc_info[i].start_handle, bt_mesh_gattc_info[i].end_handle, + bt_mesh_gattc_info[i].data_out_handle, &num); if (!num) { bt_mesh_gattc_disconnect(conn); return; @@ -1387,9 +1373,8 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) /* Get CCC of Mesh Provisioning/Proxy Data Out Characteristic */ char_uuid.len = 2; char_uuid.uu.uuid16 = BLE_MESH_UUID_GATT_CCC_VAL; - BTA_GATTC_GetDescrByCharHandle(conn_id, bt_mesh_gattc_info[i].data_out_handle, + BTA_GATTC_GetDescrByCharHandle(p_data->search_cmpl.conn_id, bt_mesh_gattc_info[i].data_out_handle, char_uuid, &result, &num); - if (!result) { bt_mesh_gattc_disconnect(conn); return; @@ -1408,7 +1393,7 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) */ write.len = sizeof(notify_en); write.p_value = (u8_t *)¬ify_en; - BTA_GATTC_WriteCharDescr(conn_id, result[0].attribute_handle, + BTA_GATTC_WriteCharDescr(p_data->search_cmpl.conn_id, result[0].attribute_handle, BTA_GATTC_TYPE_WRITE, &write, BTA_GATT_AUTH_REQ_NONE); osi_free(result); @@ -1426,17 +1411,16 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].conn.handle == handle) { + conn = &bt_mesh_gattc_info[i].conn; break; } } - if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + if (conn == NULL) { BT_ERR("%s, Conn handle is not found", __func__); return; } - conn = &bt_mesh_gattc_info[i].conn; - if (bt_mesh_gattc_info[i].ccc_handle != p_data->write.handle) { BT_WARN("%s, gattc ccc_handle is not matched", __func__); bt_mesh_gattc_disconnect(conn); @@ -1445,7 +1429,7 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->prov_write_descr != NULL) { - len = bt_mesh_gattc_conn_cb->prov_write_descr(&bt_mesh_gattc_info[i].conn, bt_mesh_gattc_info[i].addr); + len = bt_mesh_gattc_conn_cb->prov_write_descr(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn); if (len < 0) { BT_ERR("%s, prov_write_descr failed", __func__); bt_mesh_gattc_disconnect(conn); @@ -1455,12 +1439,13 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) } } else if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROXY_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->proxy_write_descr != NULL) { - len = bt_mesh_gattc_conn_cb->proxy_write_descr(&bt_mesh_gattc_info[i].conn); + len = bt_mesh_gattc_conn_cb->proxy_write_descr(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn); if (len < 0) { BT_ERR("%s, proxy_write_descr failed", __func__); bt_mesh_gattc_disconnect(conn); return; } + bt_mesh_gattc_info[i].wr_desc_done = true; } } } @@ -1473,18 +1458,22 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].conn.handle == handle) { + if (bt_mesh_gattc_info[i].wr_desc_done == false) { + BT_DBG("Receive notification before finishing to write ccc"); + return; + } + + conn = &bt_mesh_gattc_info[i].conn; break; } } - if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + if (conn == NULL) { BT_ERR("%s, Conn handle is not found", __func__); return; } - conn = &bt_mesh_gattc_info[i].conn; - - if (memcmp(bt_mesh_gattc_info[i].addr, p_data->notify.bda, BLE_MESH_ADDR_LEN) || + if (memcmp(bt_mesh_gattc_info[i].addr.val, p_data->notify.bda, BLE_MESH_ADDR_LEN) || bt_mesh_gattc_info[i].data_out_handle != p_data->notify.handle || p_data->notify.is_notify == false) { BT_ERR("%s, Notification error", __func__); @@ -1495,7 +1484,7 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->prov_notify != NULL) { len = bt_mesh_gattc_conn_cb->prov_notify(&bt_mesh_gattc_info[i].conn, - p_data->notify.value, p_data->notify.len); + p_data->notify.value, p_data->notify.len); if (len < 0) { BT_ERR("%s, prov_notify failed", __func__); bt_mesh_gattc_disconnect(conn); @@ -1505,7 +1494,7 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) } else if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROXY_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->proxy_notify != NULL) { len = bt_mesh_gattc_conn_cb->proxy_notify(&bt_mesh_gattc_info[i].conn, - p_data->notify.value, p_data->notify.len); + p_data->notify.value, p_data->notify.len); if (len < 0) { BT_ERR("%s, proxy_notify failed", __func__); bt_mesh_gattc_disconnect(conn); @@ -1560,9 +1549,9 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->connected != NULL) { for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (!memcmp(bt_mesh_gattc_info[i].addr, p_data->connect.remote_bda, BLE_MESH_ADDR_LEN)) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, p_data->connect.remote_bda, BLE_MESH_ADDR_LEN)) { bt_mesh_gattc_info[i].conn.handle = BLE_MESH_GATT_GET_CONN_ID(p_data->connect.conn_id); - (bt_mesh_gattc_conn_cb->connected)(bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn, i); + (bt_mesh_gattc_conn_cb->connected)(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn, i); break; } } @@ -1581,24 +1570,36 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->disconnected != NULL) { for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (!memcmp(bt_mesh_gattc_info[i].addr, p_data->disconnect.remote_bda, BLE_MESH_ADDR_LEN)) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, p_data->disconnect.remote_bda, BLE_MESH_ADDR_LEN)) { if (bt_mesh_gattc_info[i].conn.handle == handle) { - (bt_mesh_gattc_conn_cb->disconnected)(&bt_mesh_gattc_info[i].conn, p_data->disconnect.reason); + (bt_mesh_gattc_conn_cb->disconnected)(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn, p_data->disconnect.reason); if (!bt_mesh_gattc_info[i].wr_desc_done) { /* Add this in case connection is established, connected event comes, but * connection is terminated before server->filter_type is set to PROV. */ - provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr); +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { + provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr.val); + } +#endif } } else { /* Add this in case connection is failed to be established, and here we * need to clear some provision link info, like connecting flag, device * uuid, address info, etc. */ - provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr); +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { + provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr.val); + } +#endif } - /* Decrease prov pbg_count */ - provisioner_pbg_count_dec(); +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { + /* Decrease provisioner pbg_count */ + provisioner_pbg_count_dec(); + } +#endif /* Reset corresponding gattc info */ memset(&bt_mesh_gattc_info[i], 0, sizeof(bt_mesh_gattc_info[i])); bt_mesh_gattc_info[i].conn.handle = 0xFFFF; @@ -1618,7 +1619,7 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) break; } } -#endif /* defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ struct bt_mesh_conn *bt_mesh_conn_ref(struct bt_mesh_conn *conn) { @@ -1648,7 +1649,8 @@ void bt_mesh_gatt_init(void) BTA_GATTS_AppRegister(&app_uuid, bt_mesh_bta_gatts_cb); #endif -#if CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { bt_mesh_gattc_info[i].conn.handle = 0xFFFF; bt_mesh_gattc_info[i].mtu = GATT_DEF_BLE_MTU_SIZE; /* Default MTU_SIZE 23 */ @@ -1874,7 +1876,7 @@ int bt_mesh_update_exceptional_list(u8_t sub_code, u8_t type, void *info) BD_ADDR value = {0}; if ((sub_code > BLE_MESH_EXCEP_LIST_CLEAN) || - (type > BLE_MESH_EXCEP_INFO_MESH_PROXY_ADV)) { + (type > BLE_MESH_EXCEP_INFO_MESH_PROXY_ADV)) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c b/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c index c975b5600..c3e73c23f 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_cli.c @@ -120,7 +120,7 @@ static void timeout_handler(struct k_work *work) node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work); if (node) { bt_mesh_config_client_cb_evt_to_btc(node->opcode, - BTC_BLE_MESH_EVT_CONFIG_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); + BTC_BLE_MESH_EVT_CONFIG_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); } diff --git a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c index 82e098900..c7f72a07d 100644 --- a/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/cfg_srv.c @@ -29,7 +29,7 @@ #include "crypto.h" #include "access.h" #include "beacon.h" -#include "proxy.h" +#include "proxy_server.h" #include "foundation.h" #include "friend.h" #include "settings.h" @@ -96,7 +96,7 @@ static int comp_get_page_0(struct net_buf_simple *buf) feat |= BLE_MESH_FEAT_RELAY; } - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { feat |= BLE_MESH_FEAT_PROXY; } @@ -472,10 +472,14 @@ static void app_key_add(struct bt_mesh_model *model, return; } -#if defined(CONFIG_BLE_MESH_FAST_PROV) - bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_RECV_MSG, - model, ctx, (u8_t *)&key_app_idx, sizeof(u16_t)); -#endif + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_appkey_add.net_idx = key_net_idx; + change.cfg_appkey_add.app_idx = key_app_idx; + memcpy(change.cfg_appkey_add.app_key, buf->data, 16); + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } static void app_key_update(struct bt_mesh_model *model, @@ -501,6 +505,15 @@ static void app_key_update(struct bt_mesh_model *model, if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { BT_ERR("%s, Unable to send Config AppKey Status", __func__); } + + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_appkey_update.net_idx = key_net_idx; + change.cfg_appkey_update.app_idx = key_app_idx; + memcpy(change.cfg_appkey_update.app_key, buf->data, 16); + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } struct unbind_data { @@ -577,6 +590,14 @@ send_status: if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { BT_ERR("%s, Unable to send Config AppKey Status", __func__); } + + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_appkey_delete.net_idx = key_net_idx; + change.cfg_appkey_delete.app_idx = key_app_idx; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } /* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */ @@ -797,7 +818,7 @@ static void gatt_proxy_set(struct bt_mesh_model *model, return; } - if (!IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) || + if (!IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) || bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_NOT_SUPPORTED) { goto send_status; } @@ -1124,6 +1145,21 @@ static void mod_pub_set(struct bt_mesh_model *model, send_status: send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, status, mod_id); + + if (status == STATUS_SUCCESS && mod->pub) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_mod_pub_set.elem_addr = elem_addr; + change.cfg_mod_pub_set.pub_addr = mod->pub->addr; + change.cfg_mod_pub_set.app_idx = mod->pub->key; + change.cfg_mod_pub_set.cred_flag = mod->pub->cred; + change.cfg_mod_pub_set.ttl = mod->pub->ttl; + change.cfg_mod_pub_set.period = mod->pub->period; + change.cfg_mod_pub_set.transmit = mod->pub->retransmit; + change.cfg_mod_pub_set.cid = vnd ? mod->vnd.company : 0xFFFF; + change.cfg_mod_pub_set.mod_id = vnd ? mod->vnd.id : mod->id; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } #if CONFIG_BLE_MESH_LABEL_COUNT > 0 @@ -1447,6 +1483,16 @@ static void mod_sub_add(struct bt_mesh_model *model, send_status: send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); + + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_mod_sub_add.elem_addr = elem_addr; + change.cfg_mod_sub_add.sub_addr = sub_addr; + change.cfg_mod_sub_add.cid = vnd ? mod->vnd.company : 0xFFFF; + change.cfg_mod_sub_add.mod_id = vnd ? mod->vnd.id : mod->id; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } static void mod_sub_del(struct bt_mesh_model *model, @@ -1513,6 +1559,16 @@ static void mod_sub_del(struct bt_mesh_model *model, send_status: send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); + + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_mod_sub_delete.elem_addr = elem_addr; + change.cfg_mod_sub_delete.sub_addr = sub_addr; + change.cfg_mod_sub_delete.cid = vnd ? mod->vnd.company : 0xFFFF; + change.cfg_mod_sub_delete.mod_id = vnd ? mod->vnd.id : mod->id; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } static void mod_sub_overwrite(struct bt_mesh_model *model, @@ -2166,7 +2222,7 @@ static void net_key_add(struct bt_mesh_model *model, /* Make sure we have valid beacon data to be sent */ bt_mesh_net_beacon_update(sub); - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED; #if CONFIG_BLE_MESH_NODE bt_mesh_proxy_beacon_send(sub); @@ -2177,6 +2233,12 @@ static void net_key_add(struct bt_mesh_model *model, } send_net_key_status(model, ctx, idx, STATUS_SUCCESS); + + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_netkey_add.net_idx = sub->net_idx; + memcpy(change.cfg_netkey_add.net_key, sub->keys[0].net, 16); + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); } static void net_key_update(struct bt_mesh_model *model, @@ -2246,6 +2308,12 @@ static void net_key_update(struct bt_mesh_model *model, bt_mesh_net_beacon_update(sub); send_net_key_status(model, ctx, idx, STATUS_SUCCESS); + + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_netkey_update.net_idx = sub->net_idx; + memcpy(change.cfg_netkey_update.net_key, sub->keys[1].net, 16); + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); } static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg) @@ -2298,6 +2366,13 @@ static void net_key_del(struct bt_mesh_model *model, send_status: send_net_key_status(model, ctx, del_idx, status); + + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_netkey_delete.net_idx = sub->net_idx; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } static void net_key_get(struct bt_mesh_model *model, @@ -2416,7 +2491,7 @@ static void node_identity_set(struct bt_mesh_model *model, * 0x00, the Node Identity state for all subnets shall be set * to 0x00 and shall not be changed." */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { if (node_id) { bt_mesh_proxy_identity_start(sub); @@ -2503,6 +2578,16 @@ send_status: if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { BT_ERR("%s, Unable to send Config Model App Bind Status", __func__); } + + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_mod_app_bind.elem_addr = elem_addr; + change.cfg_mod_app_bind.app_idx = key_app_idx; + change.cfg_mod_app_bind.cid = vnd ? mod->vnd.company : 0xFFFF; + change.cfg_mod_app_bind.mod_id = vnd ? mod->vnd.id : mod->id; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } static void mod_app_unbind(struct bt_mesh_model *model, @@ -2549,6 +2634,16 @@ send_status: if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { BT_ERR("%s, Unable to send Config Model App Unbind Status", __func__); } + + if (status == STATUS_SUCCESS) { + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_mod_app_unbind.elem_addr = elem_addr; + change.cfg_mod_app_unbind.app_idx = key_app_idx; + change.cfg_mod_app_unbind.cid = vnd ? mod->vnd.company : 0xFFFF; + change.cfg_mod_app_unbind.mod_id = vnd ? mod->vnd.id : mod->id; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); + } } #define KEY_LIST_LEN (CONFIG_BLE_MESH_MODEL_KEY_COUNT * 2) @@ -2857,6 +2952,12 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, } send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS); + + bt_mesh_cfg_server_state_change_t change = {0}; + change.cfg_kr_phase_set.net_idx = idx; + change.cfg_kr_phase_set.kr_phase = phase; + bt_mesh_config_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_CONFIG_SERVER_STATE_CHANGE, + model, ctx, (const u8_t *)&change, sizeof(change)); } static u8_t hb_log(u16_t val) @@ -3129,7 +3230,7 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, * MESH/NODE/CFG/HBS/BV-02-C. */ if (sub_src == BLE_MESH_ADDR_UNASSIGNED || - sub_dst == BLE_MESH_ADDR_UNASSIGNED) { + sub_dst == BLE_MESH_ADDR_UNASSIGNED) { cfg->hb_sub.src = BLE_MESH_ADDR_UNASSIGNED; cfg->hb_sub.dst = BLE_MESH_ADDR_UNASSIGNED; cfg->hb_sub.min_hops = BLE_MESH_TTL_MAX; @@ -3295,7 +3396,7 @@ int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary) cfg->frnd = BLE_MESH_FRIEND_NOT_SUPPORTED; } - if (!IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (!IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { cfg->gatt_proxy = BLE_MESH_GATT_PROXY_NOT_SUPPORTED; } diff --git a/components/bt/esp_ble_mesh/mesh_core/friend.c b/components/bt/esp_ble_mesh/mesh_core/friend.c index 3d637d9bd..1830a17e7 100644 --- a/components/bt/esp_ble_mesh/mesh_core/friend.c +++ b/components/bt/esp_ble_mesh/mesh_core/friend.c @@ -65,6 +65,18 @@ static struct friend_adv { u64_t seq_auth; } adv_pool[FRIEND_BUF_COUNT]; +enum { + BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL, + BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT, + BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_REQ, + BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR, + BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE, +}; + +static void (*friend_cb)(bool establish, u16_t lpn_addr, u8_t reason); + + + static struct bt_mesh_adv *adv_alloc(int id) { return &adv_pool[id].adv; @@ -137,7 +149,7 @@ static s32_t recv_delay(struct bt_mesh_friend *frnd) #endif } -static void friend_clear(struct bt_mesh_friend *frnd) +static void friend_clear(struct bt_mesh_friend *frnd, u8_t reason) { int i; @@ -145,6 +157,12 @@ static void friend_clear(struct bt_mesh_friend *frnd) k_delayed_work_cancel(&frnd->timer); + if (frnd->established) { + if (friend_cb) { + friend_cb(false, frnd->lpn, reason); + } + } + friend_cred_del(frnd->net_idx, frnd->lpn); if (frnd->last) { @@ -189,7 +207,7 @@ void bt_mesh_friend_clear_net_idx(u16_t net_idx) } if (net_idx == BLE_MESH_KEY_ANY || frnd->net_idx == net_idx) { - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE); } } } @@ -262,7 +280,7 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm, sizeof(cfm), NULL, NULL, NULL); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR); return 0; } @@ -568,6 +586,9 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) if (!frnd->established) { BT_DBG("Friendship established with 0x%04x", frnd->lpn); frnd->established = 1U; + if (friend_cb) { + friend_cb(true, frnd->lpn, 0); + } } if (msg->fsn == frnd->fsn && frnd->last) { @@ -828,7 +849,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false); if (frnd) { BT_WARN("%s, Existing LPN re-requesting Friendship", __func__); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_REQ); goto init_friend; } @@ -857,6 +878,13 @@ init_friend: BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums", frnd->lpn, rx->rssi, frnd->recv_delay, frnd->poll_to); + /** + * Spec says: + * After a friendship has been established, if the PreviousAddress field + * of the Friend Request message contains a valid unicast address that is + * not the Friend node’s own unicast address, then the Friend node shall + * begin sending Friend Clear messages to that unicast address. + */ if (BLE_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) && !bt_mesh_elem_find(frnd->clear.frnd)) { clear_procedure_start(frnd); @@ -874,8 +902,8 @@ init_friend: } static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, - u16_t src, u64_t *seq_auth, - u8_t seg_count) + u16_t src, u64_t *seq_auth, + u8_t seg_count) { struct bt_mesh_friend_seg *unassigned = NULL; int i; @@ -923,7 +951,7 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, seg = get_seg(frnd, BLE_MESH_ADV(buf)->addr, &adv->seq_auth, seg_count); if (!seg) { BT_ERR("%s, No free friend segment RX contexts for 0x%04x", - __func__, BLE_MESH_ADV(buf)->addr); + __func__, BLE_MESH_ADV(buf)->addr); net_buf_unref(buf); return; } @@ -1010,14 +1038,14 @@ static void friend_timeout(struct k_work *work) if (frnd->established && !frnd->pending_req) { BT_WARN("%s, Friendship lost with 0x%04x", __func__, frnd->lpn); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT); return; } frnd->last = (void *)sys_slist_get(&frnd->queue); if (!frnd->last) { BT_WARN("%s, Friendship not established with 0x%04x", __func__, frnd->lpn); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL); return; } @@ -1035,6 +1063,11 @@ send_last: bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd); } +void bt_mesh_friend_set_cb(void (*cb)(bool establish, u16_t lpn_addr, u8_t reason)) +{ + friend_cb = cb; +} + int bt_mesh_friend_init(void) { int i; @@ -1242,7 +1275,7 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr, */ buf = (void *)sys_slist_peek_head(&seg->queue); if (buf && BLE_MESH_ADV(buf)->addr == addr && - FRIEND_ADV(buf)->seq_auth == *seq_auth) { + FRIEND_ADV(buf)->seq_auth == *seq_auth) { return true; } } @@ -1350,7 +1383,7 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; if (!friend_lpn_matches(frnd, rx->sub->net_idx, - rx->ctx.recv_dst)) { + rx->ctx.recv_dst)) { continue; } diff --git a/components/bt/esp_ble_mesh/mesh_core/health_cli.c b/components/bt/esp_ble_mesh/mesh_core/health_cli.c index 363e95c55..0d5d5c813 100644 --- a/components/bt/esp_ble_mesh/mesh_core/health_cli.c +++ b/components/bt/esp_ble_mesh/mesh_core/health_cli.c @@ -76,7 +76,7 @@ static void timeout_handler(struct k_work *work) node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work); if (node) { bt_mesh_health_client_cb_evt_to_btc(node->opcode, - BTC_BLE_MESH_EVT_HEALTH_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); + BTC_BLE_MESH_EVT_HEALTH_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); } diff --git a/components/bt/esp_ble_mesh/mesh_core/health_srv.c b/components/bt/esp_ble_mesh/mesh_core/health_srv.c index 96e16692d..344b62d10 100644 --- a/components/bt/esp_ble_mesh/mesh_core/health_srv.c +++ b/components/bt/esp_ble_mesh/mesh_core/health_srv.c @@ -27,130 +27,112 @@ #include "foundation.h" #include "mesh_common.h" -#define HEALTH_TEST_STANDARD 0x00 +#include "btc_ble_mesh_health_model.h" -/* Maximum message length is 384 in BLE Mesh. Here for health fault status, - * due to 1 octet opcode and 4 octets TransMIC, 379 octets can be used to - * store health fault status. - */ -#define HEALTH_FAULT_MAX_LEN 379 +#define HEALTH_TEST_STANDARD 0x00 + +#define HEALTH_NO_FAULT 0x00 /* Health Server context of the primary element */ struct bt_mesh_health_srv *health_srv; -static void health_get_registered(struct bt_mesh_model *mod, - u16_t company_id, - struct net_buf_simple *msg) +/** + * When an Element receives a Health Fault Get, or a Health Fault Test, or + * a Health Fault Test Unacknowledged, or a Health Fault Clear, or a Health + * Fault Clear Unacknowledged message that is not successfully processed + * (i.e. the Company ID field that does not identify any Health Fault state + * present in the node), it shall ignore the message. + * The Health Fault state is identified by Company ID and may be present in + * the node for more than one Company ID. + */ + +static u8_t health_get_curr_fault_count(struct bt_mesh_model *model) { - struct bt_mesh_health_srv *srv = mod->user_data; - u8_t *test_id; + struct bt_mesh_health_srv *srv = model->user_data; + u8_t count = 0; + size_t i; - BT_DBG("Company ID 0x%04x", company_id); - - if (!srv) { - BT_ERR("%s, No Health Server context provided", __func__); - return; + for (i = 0U; i < ARRAY_SIZE(srv->test.curr_faults); i++) { + if (srv->test.curr_faults[i] != HEALTH_NO_FAULT) { + count++; + } } - bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS); + return count; +} - test_id = net_buf_simple_add(msg, 1); - net_buf_simple_add_le16(msg, company_id); +static void health_get_fault_value(struct bt_mesh_model *model, + struct net_buf_simple *msg, + bool current) +{ + struct bt_mesh_health_srv *srv = model->user_data; + size_t array_size; + size_t i; - if (srv->cb && srv->cb->fault_get_reg) { - u8_t fault_count = net_buf_simple_tailroom(msg) - 4; - int err; + array_size = current ? ARRAY_SIZE(srv->test.curr_faults) : ARRAY_SIZE(srv->test.reg_faults); - err = srv->cb->fault_get_reg(mod, company_id, test_id, - net_buf_simple_tail(msg), - &fault_count); - if (err) { - BT_ERR("%s, Failed to get faults (err %d)", __func__, err); - *test_id = HEALTH_TEST_STANDARD; - } else { - net_buf_simple_add(msg, fault_count); + for (i = 0U; i < array_size; i++) { + if (net_buf_simple_tailroom(msg) == 0) { + return; + } + + u8_t fault = current ? srv->test.curr_faults[i] : srv->test.reg_faults[i]; + if (fault != HEALTH_NO_FAULT) { + net_buf_simple_add_u8(msg, fault); } - } else { - BT_WARN("No callback for getting faults"); - *test_id = HEALTH_TEST_STANDARD; } } -static size_t health_get_current(struct bt_mesh_model *mod, - struct net_buf_simple *msg) +static bool health_is_test_id_exist(struct bt_mesh_model *model, u8_t test_id) { - struct bt_mesh_health_srv *srv = mod->user_data; - const struct bt_mesh_comp *comp; - u8_t *test_id, *company_ptr; - u16_t company_id; - u8_t fault_count; + struct bt_mesh_health_srv *srv = model->user_data; + u8_t i; + + for (i = 0U; i < srv->test.id_count; i++) { + if (srv->test.test_ids[i] == test_id) { + return true; + } + } + + return false; +} + +static int health_send_fault_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx) +{ + struct bt_mesh_health_srv *srv = model->user_data; + struct net_buf_simple *msg = NULL; int err; - if (!srv) { - BT_ERR("%s, No Health Server context provided", __func__); - return 0; + msg = bt_mesh_alloc_buf(4 + ARRAY_SIZE(srv->test.reg_faults) + 4); + if (!msg) { + BT_ERR("%s, Failed to allocate memory", __func__); + return -ENOMEM; } - bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS); - - test_id = net_buf_simple_add(msg, 1); - company_ptr = net_buf_simple_add(msg, sizeof(company_id)); - comp = bt_mesh_comp_get(); - - if (srv->cb && srv->cb->fault_get_cur) { - fault_count = net_buf_simple_tailroom(msg); - err = srv->cb->fault_get_cur(mod, test_id, &company_id, - net_buf_simple_tail(msg), - &fault_count); - if (err) { - BT_ERR("%s, Failed to get faults (err %d)", __func__, err); - sys_put_le16(comp->cid, company_ptr); - *test_id = HEALTH_TEST_STANDARD; - fault_count = 0U; - } else { - sys_put_le16(company_id, company_ptr); - net_buf_simple_add(msg, fault_count); - } - } else { - BT_WARN("No callback for getting faults"); - sys_put_le16(comp->cid, company_ptr); - *test_id = HEALTH_TEST_STANDARD; - fault_count = 0U; + bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS); + net_buf_simple_add_u8(msg, srv->test.prev_test_id); + net_buf_simple_add_le16(msg, srv->test.company_id); + if (ctx->recv_op != OP_HEALTH_FAULT_CLEAR) { + /** + * For Health Fault Clear, the FaultArray field in Health Fault Status + * shall be empty. + */ + health_get_fault_value(model, msg, false); } - return fault_count; + err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (err) { + BT_ERR("%s, Failed to send Health Fault Status response", __func__); + } + + bt_mesh_free_buf(msg); + return err; } static void health_fault_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) -{ - struct net_buf_simple *sdu = NULL; - u16_t company_id; - - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("company_id 0x%04x", company_id); - - sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, HEALTH_FAULT_MAX_LEN)); - if (!sdu) { - BT_ERR("%s, Failed to allocate memory", __func__); - return; - } - - health_get_registered(model, company_id, sdu); - - if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) { - BT_ERR("%s, Unable to send Health Current Status", __func__); - } - - bt_mesh_free_buf(sdu); - return; -} - -static void health_fault_clear_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf) { struct bt_mesh_health_srv *srv = model->user_data; u16_t company_id; @@ -161,12 +143,14 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model, } company_id = net_buf_simple_pull_le16(buf); + if (company_id != srv->test.company_id) { + BT_ERR("%s, Unknown Company ID 0x%04x", __func__, company_id); + return; + } BT_DBG("company_id 0x%04x", company_id); - if (srv->cb && srv->cb->fault_clear) { - srv->cb->fault_clear(model, company_id); - } + health_send_fault_status(model, ctx); } static void health_fault_clear(struct bt_mesh_model *model, @@ -174,7 +158,6 @@ static void health_fault_clear(struct bt_mesh_model *model, struct net_buf_simple *buf) { struct bt_mesh_health_srv *srv = model->user_data; - struct net_buf_simple *sdu = NULL; u16_t company_id; if (!srv) { @@ -183,49 +166,21 @@ static void health_fault_clear(struct bt_mesh_model *model, } company_id = net_buf_simple_pull_le16(buf); + if (company_id != srv->test.company_id) { + BT_ERR("%s, Unknown Company ID 0x%04x", __func__, company_id); + return; + } BT_DBG("company_id 0x%04x", company_id); - if (srv->cb && srv->cb->fault_clear) { - srv->cb->fault_clear(model, company_id); + memset(srv->test.reg_faults, HEALTH_NO_FAULT, ARRAY_SIZE(srv->test.reg_faults)); + + if (srv->cb.fault_clear) { + srv->cb.fault_clear(model, company_id); } - sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, HEALTH_FAULT_MAX_LEN)); - if (!sdu) { - BT_ERR("%s, Failed to allocate memory", __func__); - return; - } - - health_get_registered(model, company_id, sdu); - - if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) { - BT_ERR("%s, Unable to send Health Current Status", __func__); - } - - bt_mesh_free_buf(sdu); - return; -} - -static void health_fault_test_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf) -{ - struct bt_mesh_health_srv *srv = model->user_data; - u16_t company_id; - u8_t test_id; - - if (!srv) { - BT_ERR("%s, No Health Server context provided", __func__); - return; - } - - test_id = net_buf_simple_pull_u8(buf); - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); - - if (srv->cb && srv->cb->fault_test) { - srv->cb->fault_test(model, test_id, company_id); + if (ctx->recv_op == OP_HEALTH_FAULT_CLEAR) { + health_send_fault_status(model, ctx); } } @@ -234,7 +189,6 @@ static void health_fault_test(struct bt_mesh_model *model, struct net_buf_simple *buf) { struct bt_mesh_health_srv *srv = model->user_data; - struct net_buf_simple *sdu = NULL; u16_t company_id; u8_t test_id; @@ -246,34 +200,28 @@ static void health_fault_test(struct bt_mesh_model *model, } test_id = net_buf_simple_pull_u8(buf); - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); - - if (srv->cb && srv->cb->fault_test) { - int err; - - err = srv->cb->fault_test(model, test_id, company_id); - if (err) { - BT_WARN("Running fault test failed with err %d", err); - return; - } - } - - sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, HEALTH_FAULT_MAX_LEN)); - if (!sdu) { - BT_ERR("%s, Failed to allocate memory", __func__); + if (health_is_test_id_exist(model, test_id) == false) { + BT_ERR("%s, Unknown Test ID 0x%02x", __func__, test_id); return; } - health_get_registered(model, company_id, sdu); - - if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) { - BT_ERR("%s, Unable to send Health Current Status", __func__); + company_id = net_buf_simple_pull_le16(buf); + if (company_id != srv->test.company_id) { + BT_ERR("%s, Unknown Company ID 0x%04x", __func__, company_id); + return; } - bt_mesh_free_buf(sdu); - return; + BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); + + srv->test.prev_test_id = test_id; + + if (srv->cb.fault_test) { + srv->cb.fault_test(model, test_id, company_id); + } + + if (ctx->recv_op == OP_HEALTH_FAULT_TEST) { + health_send_fault_status(model, ctx); + } } static void send_attention_status(struct bt_mesh_model *model, @@ -293,7 +241,6 @@ static void send_attention_status(struct bt_mesh_model *model, BT_DBG("%u second%s", time, (time == 1U) ? "" : "s"); bt_mesh_model_msg_init(&msg, OP_ATTENTION_STATUS); - net_buf_simple_add_u8(&msg, time); if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { @@ -310,9 +257,9 @@ static void attention_get(struct bt_mesh_model *model, send_attention_status(model, ctx); } -static void attention_set_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf) +static void health_set_attention(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) { u8_t time; @@ -329,9 +276,11 @@ static void attention_set(struct bt_mesh_model *model, { BT_DBG("%s", __func__); - attention_set_unrel(model, ctx, buf); + health_set_attention(model, ctx, buf); - send_attention_status(model, ctx); + if (ctx->recv_op == OP_ATTENTION_SET) { + send_attention_status(model, ctx); + } } static void send_health_period_status(struct bt_mesh_model *model, @@ -341,7 +290,6 @@ static void send_health_period_status(struct bt_mesh_model *model, NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4); bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_STATUS); - net_buf_simple_add_u8(&msg, model->pub->period_div); if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { @@ -358,9 +306,9 @@ static void health_period_get(struct bt_mesh_model *model, send_health_period_status(model, ctx); } -static void health_period_set_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf) +static void health_set_period(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) { u8_t period; @@ -381,34 +329,64 @@ static void health_period_set(struct bt_mesh_model *model, { BT_DBG("%s", __func__); - health_period_set_unrel(model, ctx, buf); + health_set_period(model, ctx, buf); - send_health_period_status(model, ctx); + if (ctx->recv_op == OP_HEALTH_PERIOD_SET) { + send_health_period_status(model, ctx); + } } const struct bt_mesh_model_op bt_mesh_health_srv_op[] = { - { OP_HEALTH_FAULT_GET, 2, health_fault_get }, + { OP_HEALTH_FAULT_GET, 2, health_fault_get }, { OP_HEALTH_FAULT_CLEAR, 2, health_fault_clear }, - { OP_HEALTH_FAULT_CLEAR_UNREL, 2, health_fault_clear_unrel }, - { OP_HEALTH_FAULT_TEST, 3, health_fault_test }, - { OP_HEALTH_FAULT_TEST_UNREL, 3, health_fault_test_unrel }, - { OP_HEALTH_PERIOD_GET, 0, health_period_get }, - { OP_HEALTH_PERIOD_SET, 1, health_period_set }, - { OP_HEALTH_PERIOD_SET_UNREL, 1, health_period_set_unrel }, - { OP_ATTENTION_GET, 0, attention_get }, - { OP_ATTENTION_SET, 1, attention_set }, - { OP_ATTENTION_SET_UNREL, 1, attention_set_unrel }, + { OP_HEALTH_FAULT_CLEAR_UNREL, 2, health_fault_clear }, + { OP_HEALTH_FAULT_TEST, 3, health_fault_test }, + { OP_HEALTH_FAULT_TEST_UNREL, 3, health_fault_test }, + { OP_HEALTH_PERIOD_GET, 0, health_period_get }, + { OP_HEALTH_PERIOD_SET, 1, health_period_set }, + { OP_HEALTH_PERIOD_SET_UNREL, 1, health_period_set }, + { OP_ATTENTION_GET, 0, attention_get }, + { OP_ATTENTION_SET, 1, attention_set }, + { OP_ATTENTION_SET_UNREL, 1, attention_set }, BLE_MESH_MODEL_OP_END, }; -static int health_pub_update(struct bt_mesh_model *mod) +static size_t health_get_current(struct bt_mesh_model *model, + struct net_buf_simple *msg) { - struct bt_mesh_model_pub *pub = mod->pub; + struct bt_mesh_health_srv *srv = model->user_data; + + if (!srv) { + BT_ERR("%s, No Health Server context provided", __func__); + return 0; + } + + if (msg->size < 4) { + BT_ERR("%s, Too small health publication msg size %d", __func__, msg->size); + return 0; + } + + bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS); + net_buf_simple_add_u8(msg, srv->test.prev_test_id); + net_buf_simple_add_le16(msg, srv->test.company_id); + health_get_fault_value(model, msg, true); + + return health_get_curr_fault_count(model); +} + +static int health_pub_update(struct bt_mesh_model *model) +{ + struct bt_mesh_model_pub *pub = model->pub; size_t count; BT_DBG("%s", __func__); - count = health_get_current(mod, pub->msg); + if (!pub || !pub->msg) { + BT_ERR("%s, Invalid health publication context", __func__); + return -EINVAL; + } + + count = health_get_current(model, pub->msg); if (count) { pub->fast_period = 1U; } else { @@ -420,29 +398,29 @@ static int health_pub_update(struct bt_mesh_model *mod) int bt_mesh_fault_update(struct bt_mesh_elem *elem) { - struct bt_mesh_model *mod; + struct bt_mesh_model *model; - mod = bt_mesh_model_find(elem, BLE_MESH_MODEL_ID_HEALTH_SRV); - if (!mod) { + model = bt_mesh_model_find(elem, BLE_MESH_MODEL_ID_HEALTH_SRV); + if (!model) { BT_ERR("%s, Health Server does not exist", __func__); return -EINVAL; } - if (!mod->pub) { + if (!model->pub) { BT_ERR("%s, Health Server has no publication support", __func__); - return -EIO; + return -EINVAL; } /* Let periodic publishing, if enabled, take care of sending the * Health Current Status. */ - if (bt_mesh_model_pub_period_get(mod)) { + if (bt_mesh_model_pub_period_get(model)) { return 0; } - health_pub_update(mod); + health_pub_update(model); - return bt_mesh_model_publish(mod); + return bt_mesh_model_publish(model); } static void attention_off(struct k_work *work) @@ -457,17 +435,23 @@ static void attention_off(struct k_work *work) return; } - if (srv->cb && srv->cb->attn_off) { - srv->cb->attn_off(srv->model); + if (srv->cb.attn_off) { + srv->cb.attn_off(srv->model); } + srv->attn_timer_start = false; } int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary) { struct bt_mesh_health_srv *srv = model->user_data; + /* Health Server Model shall be supported by a primary element and may be + * supported by any secondary elements. + */ + if (!srv) { if (!primary) { + /* If Health Server is in the secondary element with NULL user_data. */ return 0; } @@ -475,6 +459,11 @@ int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary) return -EINVAL; } + if (srv->test.id_count == 0 || !srv->test.test_ids) { + BT_ERR("%s, No Health Test ID provided", __func__); + return -EINVAL; + } + if (!model->pub) { BT_ERR("%s, Health Server has no publication support", __func__); return -EINVAL; @@ -485,6 +474,10 @@ int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary) k_delayed_work_init(&srv->attn_timer, attention_off); srv->model = model; + srv->attn_timer_start = false; + + memset(srv->test.curr_faults, HEALTH_NO_FAULT, ARRAY_SIZE(srv->test.curr_faults)); + memset(srv->test.reg_faults, HEALTH_NO_FAULT, ARRAY_SIZE(srv->test.reg_faults)); if (primary) { health_srv = srv; @@ -514,16 +507,20 @@ void bt_mesh_attention(struct bt_mesh_model *model, u8_t time) } if (time) { - if (srv->cb && srv->cb->attn_on) { - srv->cb->attn_on(model); + if (srv->cb.attn_on) { + srv->cb.attn_on(model, time); } k_delayed_work_submit(&srv->attn_timer, time * 1000U); + srv->attn_timer_start = true; } else { k_delayed_work_cancel(&srv->attn_timer); - if (srv->cb && srv->cb->attn_off) { - srv->cb->attn_off(model); + if (srv->attn_timer_start == true) { + if (srv->cb.attn_off) { + srv->cb.attn_off(model); + } + srv->attn_timer_start = false; } } } diff --git a/components/bt/esp_ble_mesh/mesh_core/include/cfg_srv.h b/components/bt/esp_ble_mesh/mesh_core/include/cfg_srv.h index d5f77e7b0..91f07fa4b 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/cfg_srv.h +++ b/components/bt/esp_ble_mesh/mesh_core/include/cfg_srv.h @@ -65,6 +65,149 @@ extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[]; BLE_MESH_MODEL(BLE_MESH_MODEL_ID_CFG_SRV, \ bt_mesh_cfg_srv_op, NULL, srv_data) +typedef union { + struct { + u8_t beacon; + } cfg_beacon_set; + struct { + u8_t ttl; + } cfg_default_ttl_set; + struct { + u8_t gatt_proxy; + } cfg_gatt_proxy_set; + struct { + u8_t relay; + u8_t retransmit; + } cfg_relay_set; + struct { + u16_t elem_addr; + u16_t pub_addr; + u16_t app_idx; + bool cred_flag; + u8_t ttl; + u8_t period; + u8_t transmit; + u16_t cid; + u16_t mod_id; + } cfg_mod_pub_set; + struct { + u16_t elem_addr; + u8_t pub_addr[16]; + u16_t app_idx; + bool cred_flag; + u8_t ttl; + u8_t period; + u8_t transmit; + u16_t cid; + u16_t mod_id; + } cfg_mod_pub_va_set; + struct { + u16_t elem_addr; + u16_t sub_addr; + u16_t cid; + u16_t mod_id; + } cfg_mod_sub_add; + struct { + u16_t elem_addr; + u8_t sub_addr[16]; + u16_t cid; + u16_t mod_id; + } cfg_mod_sub_va_add; + struct { + u16_t elem_addr; + u16_t sub_addr; + u16_t cid; + u16_t mod_id; + } cfg_mod_sub_delete; + struct { + u16_t elem_addr; + u8_t sub_addr[16]; + u16_t cid; + u16_t mod_id; + } cfg_mod_sub_va_delete; + struct { + u16_t elem_addr; + u16_t sub_addr; + u16_t cid; + u16_t mod_id; + } cfg_mod_sub_overwrite; + struct { + u16_t elem_addr; + u8_t sub_addr[16]; + u16_t cid; + u16_t mod_id; + } cfg_mod_sub_va_overwrite; + struct { + u16_t elem_addr; + u16_t cid; + u16_t mod_id; + } cfg_mod_sub_delete_all; + struct { + u16_t net_idx; + u8_t net_key[16]; + } cfg_netkey_add; + struct { + u16_t net_idx; + u8_t net_key[16]; + } cfg_netkey_update; + struct { + u16_t net_idx; + } cfg_netkey_delete; + struct { + u16_t net_idx; + u16_t app_idx; + u8_t app_key[16]; + } cfg_appkey_add; + struct { + u16_t net_idx; + u16_t app_idx; + u8_t app_key[16]; + } cfg_appkey_update; + struct { + u16_t net_idx; + u16_t app_idx; + } cfg_appkey_delete; + struct { + u16_t net_idx; + u8_t identity; + } cfg_node_identity_set; + struct { + u16_t elem_addr; + u16_t app_idx; + u16_t cid; + u16_t mod_id; + } cfg_mod_app_bind; + struct { + u16_t elem_addr; + u16_t app_idx; + u16_t cid; + u16_t mod_id; + } cfg_mod_app_unbind; + struct { + u8_t frnd; + } cfg_friend_set; + struct { + u16_t net_idx; + u8_t kr_phase; + } cfg_kr_phase_set; + struct { + u16_t dst; + u8_t count; + u8_t period; + u8_t ttl; + u16_t feat; + u16_t net_idx; + } cfg_hb_pub_set; + struct { + u16_t src; + u16_t dst; + u8_t period; + } cfg_hb_sub_set; + struct { + u8_t transmit; + } cfg_net_transmit_set; +} bt_mesh_cfg_server_state_change_t; + /** * @} */ diff --git a/components/bt/esp_ble_mesh/mesh_core/include/health_srv.h b/components/bt/esp_ble_mesh/mesh_core/include/health_srv.h index 4e9b84077..0aa262153 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/health_srv.h +++ b/components/bt/esp_ble_mesh/mesh_core/include/health_srv.h @@ -21,25 +21,15 @@ */ struct bt_mesh_health_srv_cb { - /* Fetch current faults */ - int (*fault_get_cur)(struct bt_mesh_model *model, u8_t *test_id, - u16_t *company_id, u8_t *faults, - u8_t *fault_count); - - /* Fetch registered faults */ - int (*fault_get_reg)(struct bt_mesh_model *model, u16_t company_id, - u8_t *test_id, u8_t *faults, - u8_t *fault_count); - /* Clear registered faults */ - int (*fault_clear)(struct bt_mesh_model *model, u16_t company_id); + void (*fault_clear)(struct bt_mesh_model *model, u16_t company_id); /* Run a specific test */ - int (*fault_test)(struct bt_mesh_model *model, u8_t test_id, - u16_t company_id); + void (*fault_test)(struct bt_mesh_model *model, u8_t test_id, + u16_t company_id); /* Attention on */ - void (*attn_on)(struct bt_mesh_model *model); + void (*attn_on)(struct bt_mesh_model *model, u8_t time); /* Attention off */ void (*attn_off)(struct bt_mesh_model *model); @@ -55,15 +45,30 @@ struct bt_mesh_health_srv_cb { #define BLE_MESH_HEALTH_PUB_DEFINE(_name, _max_faults) \ BLE_MESH_MODEL_PUB_DEFINE(_name, NULL, (1 + 3 + (_max_faults))) +struct bt_mesh_health_test { + u8_t id_count; /* Number of Health self-test ID */ + const u8_t *test_ids; /* Array of Health self-test IDs */ + u16_t company_id; /* Company ID used to identify the Health Fault state */ + u8_t prev_test_id; /* Most currently performed test id */ + u8_t curr_faults[32]; /* Array of current faults */ + u8_t reg_faults[32]; /* Array of registered faults */ +} __attribute__((packed)); + /** Mesh Health Server Model Context */ struct bt_mesh_health_srv { struct bt_mesh_model *model; /* Optional callback struct */ - const struct bt_mesh_health_srv_cb *cb; + struct bt_mesh_health_srv_cb cb; /* Attention Timer state */ struct k_delayed_work attn_timer; + + /* Attention Timer start flag */ + bool attn_timer_start; + + /* Health Server fault test */ + struct bt_mesh_health_test test; }; extern const struct bt_mesh_model_op bt_mesh_health_srv_op[]; diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_bearer_adapt.h b/components/bt/esp_ble_mesh/mesh_core/include/mesh_bearer_adapt.h index 0d8ecd96d..2c54005d1 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/mesh_bearer_adapt.h +++ b/components/bt/esp_ble_mesh/mesh_core/include/mesh_bearer_adapt.h @@ -17,7 +17,8 @@ /* BLE Mesh Max Connection Count */ #ifdef CONFIG_BT_BLUEDROID_ENABLED -#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS +#define BLE_MESH_MAX_CONN \ + MIN(CONFIG_BT_ACL_CONNECTIONS, CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN) #define ADV_TASK_CORE TASK_PINNED_TO_CORE #endif @@ -445,7 +446,7 @@ typedef void (*bt_mesh_dh_key_cb_t)(const u8_t key[32], const u8_t idx); * or BLE_MESH_GATT_ITER_STOP to stop. */ typedef u8_t (*bt_mesh_gatt_attr_func_t)(const struct bt_mesh_gatt_attr *attr, - void *user_data); + void *user_data); /** @brief Connection callback structure. * @@ -481,15 +482,15 @@ struct bt_mesh_conn_cb { }; struct bt_mesh_prov_conn_cb { - void (*connected)(const u8_t addr[6], struct bt_mesh_conn *conn, int id); + void (*connected)(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int id); - void (*disconnected)(struct bt_mesh_conn *conn, u8_t reason); + void (*disconnected)(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, u8_t reason); - ssize_t (*prov_write_descr)(struct bt_mesh_conn *conn, u8_t *addr); + ssize_t (*prov_write_descr)(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn); ssize_t (*prov_notify)(struct bt_mesh_conn *conn, u8_t *data, u16_t len); - ssize_t (*proxy_write_descr)(struct bt_mesh_conn *conn); + ssize_t (*proxy_write_descr)(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn); ssize_t (*proxy_notify)(struct bt_mesh_conn *conn, u8_t *data, u16_t len); }; @@ -656,20 +657,20 @@ int bt_mesh_gatts_service_register(struct bt_mesh_gatt_service *svc); int bt_mesh_gatts_service_unregister(struct bt_mesh_gatt_service *svc); ssize_t bt_mesh_gatts_attr_read_included(struct bt_mesh_conn *conn, - const struct bt_mesh_gatt_attr *attr, - void *buf, u16_t len, u16_t offset); + const struct bt_mesh_gatt_attr *attr, + void *buf, u16_t len, u16_t offset); ssize_t bt_mesh_gatts_attr_read(struct bt_mesh_conn *conn, const struct bt_mesh_gatt_attr *attr, void *buf, u16_t buf_len, u16_t offset, const void *value, u16_t value_len); ssize_t bt_mesh_gatts_attr_read_service(struct bt_mesh_conn *conn, - const struct bt_mesh_gatt_attr *attr, - void *buf, u16_t len, u16_t offset); + const struct bt_mesh_gatt_attr *attr, + void *buf, u16_t len, u16_t offset); ssize_t bt_mesh_gatts_attr_read_chrc(struct bt_mesh_conn *conn, - const struct bt_mesh_gatt_attr *attr, void *buf, - u16_t len, u16_t offset); + const struct bt_mesh_gatt_attr *attr, void *buf, + u16_t len, u16_t offset); int bt_mesh_gatts_notify(struct bt_mesh_conn *conn, const struct bt_mesh_gatt_attr *attr, const void *data, u16_t len); @@ -682,6 +683,8 @@ int bt_mesh_gatts_service_start(struct bt_mesh_gatt_service *svc); void bt_mesh_gattc_conn_cb_register(struct bt_mesh_prov_conn_cb *cb); +u8_t bt_mesh_gattc_get_free_conn_count(void); + u16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn); int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid); @@ -716,10 +719,10 @@ bool bt_mesh_check_public_key(const uint8_t key[64]); int bt_mesh_dh_key_gen(const u8_t remote_pk[64], bt_mesh_dh_key_cb_t cb, const u8_t idx); int bt_mesh_encrypt_le(const u8_t key[16], const u8_t plaintext[16], - u8_t enc_data[16]); + u8_t enc_data[16]); int bt_mesh_encrypt_be(const u8_t key[16], const u8_t plaintext[16], - u8_t enc_data[16]); + u8_t enc_data[16]); enum { BLE_MESH_EXCEP_LIST_ADD = 0, diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h b/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h index 1a79a7a1e..08f7908ef 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h +++ b/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h @@ -280,7 +280,6 @@ struct bt_mesh_prov { * * @param bearer Provisioning bearer. * @param reason Provisioning link close reason(disconnect reason) - * 0xFF: disconnect due to provisioner_pb_gatt_disable() */ void (*prov_link_close)(bt_mesh_prov_bearer_t bearer, u8_t reason); @@ -555,10 +554,13 @@ bool bt_mesh_iv_update(void); * from a battery power source. * * @param enable true to enable LPN functionality, false to disable it. + * @param force when disable LPN functionality, use this flag to indicate + * whether directly clear corresponding information or sending + * friend clear to disable it. * * @return Zero on success or (negative) error code otherwise. */ -int bt_mesh_lpn_set(bool enable); +int bt_mesh_lpn_set(bool enable, bool force); /** @brief Send out a Friend Poll message. * @@ -578,6 +580,15 @@ int bt_mesh_lpn_poll(void); */ void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established)); +/** @brief Register a callback for Friendship changes of friend node. + * + * Registers a callback that will be called whenever Friendship gets + * established or is terminated. + * + * @param cb Function to call when the Friendship status of friend node changes. + */ +void bt_mesh_friend_set_cb(void (*cb)(bool establish, u16_t lpn_addr, u8_t reason)); + /** * @} */ diff --git a/components/bt/esp_ble_mesh/mesh_core/lpn.c b/components/bt/esp_ble_mesh/mesh_core/lpn.c index ad301db06..06358cac4 100644 --- a/components/bt/esp_ble_mesh/mesh_core/lpn.c +++ b/components/bt/esp_ble_mesh/mesh_core/lpn.c @@ -55,8 +55,11 @@ #define POLL_TIMEOUT_MAX(lpn) ((CONFIG_BLE_MESH_LPN_POLL_TIMEOUT * 100) - \ REQ_RETRY_DURATION(lpn)) -/* Update 4 to 20 for BQB test case MESH/NODE/FRND/LPM/BI-02-C */ -#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4) +/** + * 1. Should use 20 attempts for BQB test case MESH/NODE/FRND/LPM/BI-02-C. + * 2. We should use more specific value for each PollTimeout range. + */ +#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 6) #define CLEAR_ATTEMPTS 2 @@ -70,9 +73,10 @@ /* 2 transmissions, 20ms interval */ #define POLL_XMIT BLE_MESH_TRANSMIT(1, 20) +#define FIRST_POLL_ATTEMPTS 6 + static void (*lpn_cb)(u16_t friend_addr, bool established); -#if defined(CONFIG_BLE_MESH_DEBUG_LOW_POWER) static const char *state2str(int state) { switch (state) { @@ -94,17 +98,16 @@ static const char *state2str(int state) return "recv delay"; case BLE_MESH_LPN_WAIT_UPDATE: return "wait update"; + case BLE_MESH_LPN_OFFER_RECV: + return "offer recv"; default: return "(unknown)"; } } -#endif /* CONFIG_BLE_MESH_DEBUG_LOW_POWER */ static inline void lpn_set_state(int state) { -#if defined(CONFIG_BLE_MESH_DEBUG_LOW_POWER) BT_DBG("%s -> %s", state2str(bt_mesh.lpn.state), state2str(state)); -#endif bt_mesh.lpn.state = state; } @@ -149,6 +152,8 @@ static inline void group_clear(bt_mesh_atomic_t *target, bt_mesh_atomic_t *sourc static void clear_friendship(bool force, bool disable); +static bool scan_after_clear; + static void friend_clear_sent(int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; @@ -156,7 +161,10 @@ static void friend_clear_sent(int err, void *user_data) /* We're switching away from Low Power behavior, so permanently * enable scanning. */ - bt_mesh_scan_enable(); + if (scan_after_clear == false) { + bt_mesh_scan_enable(); + scan_after_clear = true; + } lpn->req_attempts++; @@ -261,6 +269,11 @@ static void clear_friendship(bool force, bool disable) lpn_set_state(BLE_MESH_LPN_ENABLED); k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); + + scan_after_clear = false; + if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) { + bt_mesh_scan_disable(); + } } static void friend_req_sent(u16_t duration, int err, void *user_data) @@ -269,6 +282,10 @@ static void friend_req_sent(u16_t duration, int err, void *user_data) if (err) { BT_ERR("%s, Sending Friend Request failed (err %d)", __func__, err); + + if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) { + bt_mesh_scan_enable(); + } return; } @@ -322,10 +339,8 @@ static void req_sent(u16_t duration, int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; -#if defined(CONFIG_BLE_MESH_DEBUG_LOW_POWER) BT_DBG("req 0x%02x duration %u err %d state %s", lpn->sent_req, duration, err, state2str(lpn->state)); -#endif if (err) { BT_ERR("%s, Sending request failed (err %d)", __func__, err); @@ -346,6 +361,12 @@ static void req_sent(u16_t duration, int err, void *user_data) LPN_RECV_DELAY - SCAN_LATENCY); } else { lpn_set_state(BLE_MESH_LPN_OFFER_RECV); + /** + * Friend Update is replied by Friend Node with TTL set to 0 and Network + * Transmit set to 30ms which will cause the packet easy to be missed. + * Regarding this situation, here we can reduce the duration of receiving + * the first Friend Update. + */ k_delayed_work_submit(&lpn->timer, LPN_RECV_DELAY + duration + lpn->recv_win); @@ -404,7 +425,7 @@ void bt_mesh_lpn_disable(bool force) clear_friendship(force, true); } -int bt_mesh_lpn_set(bool enable) +int bt_mesh_lpn_set(bool enable, bool force) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; @@ -442,7 +463,7 @@ int bt_mesh_lpn_set(bool enable) k_delayed_work_cancel(&lpn->timer); lpn_set_state(BLE_MESH_LPN_DISABLED); } else { - bt_mesh_lpn_disable(false); + bt_mesh_lpn_disable(force); } } @@ -543,6 +564,10 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, lpn->counter++; + if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) { + bt_mesh_scan_disable(); + } + return 0; } @@ -720,7 +745,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn) bt_mesh_scan_disable(); } - if (lpn->req_attempts < 6) { + if (lpn->req_attempts < FIRST_POLL_ATTEMPTS) { BT_WARN("Retrying first Friend Poll"); lpn->sent_req = 0U; if (send_friend_poll() == 0) { @@ -737,9 +762,7 @@ static void lpn_timeout(struct k_work *work) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; -#if defined(CONFIG_BLE_MESH_DEBUG_LOW_POWER) BT_DBG("state: %s", state2str(lpn->state)); -#endif switch (lpn->state) { case BLE_MESH_LPN_DISABLED: @@ -774,9 +797,15 @@ static void lpn_timeout(struct k_work *work) k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); break; case BLE_MESH_LPN_OFFER_RECV: - BT_WARN("No Friend Update received after the first Friend Poll"); - lpn->sent_req = 0U; - send_friend_poll(); + if (lpn->req_attempts < FIRST_POLL_ATTEMPTS) { + BT_WARN("Retrying the first Friend Poll, %d attempts", lpn->req_attempts); + lpn->sent_req = 0U; + send_friend_poll(); + break; + } + + BT_ERR("Timeout waiting for the first Friend Update"); + clear_friendship(true, false); break; case BLE_MESH_LPN_ESTABLISHED: if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { @@ -1047,9 +1076,7 @@ int bt_mesh_lpn_init(void) k_delayed_work_init(&lpn->timer, lpn_timeout); if (lpn->state == BLE_MESH_LPN_ENABLED) { - if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } else { + if (!IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) { bt_mesh_scan_enable(); } diff --git a/components/bt/esp_ble_mesh/mesh_core/mesh_main.c b/components/bt/esp_ble_mesh/mesh_core/main.c similarity index 95% rename from components/bt/esp_ble_mesh/mesh_core/mesh_main.c rename to components/bt/esp_ble_mesh/mesh_core/main.c index 03760d957..13dc03610 100644 --- a/components/bt/esp_ble_mesh/mesh_core/mesh_main.c +++ b/components/bt/esp_ble_mesh/mesh_core/main.c @@ -28,11 +28,11 @@ #include "transport.h" #include "access.h" #include "foundation.h" -#include "proxy.h" +#include "proxy_server.h" #include "settings.h" #include "mesh.h" #include "provisioner_prov.h" -#include "provisioner_proxy.h" +#include "proxy_client.h" #include "provisioner_main.h" static volatile bool provisioner_en = false; @@ -127,7 +127,7 @@ void bt_mesh_reset(void) bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY); } - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { bt_mesh_proxy_gatt_disable(); } @@ -296,7 +296,7 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, #if CONFIG_BLE_MESH_NODE extern struct bt_mesh_gatt_service proxy_svc; - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { bt_mesh_gatts_service_register(&proxy_svc); } @@ -340,8 +340,9 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, #if CONFIG_BLE_MESH_NODE bt_mesh_proxy_init(); #endif -#if CONFIG_BLE_MESH_PROVISIONER - provisioner_proxy_init(); +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT + bt_mesh_proxy_prov_client_init(); #endif } @@ -390,18 +391,13 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers) if (IS_ENABLED(CONFIG_BLE_MESH_PB_ADV) && (bearers & BLE_MESH_PROV_ADV)) { bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD, - BLE_MESH_EXCEP_INFO_MESH_BEACON, NULL); + BLE_MESH_EXCEP_INFO_MESH_BEACON, NULL); } if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) && (bearers & BLE_MESH_PROV_GATT)) { bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD, - BLE_MESH_EXCEP_INFO_MESH_PROV_ADV, NULL); - } - - if (IS_ENABLED(CONFIG_BLE_MESH_PROXY)) { - bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD, - BLE_MESH_EXCEP_INFO_MESH_PROXY_ADV, NULL); + BLE_MESH_EXCEP_INFO_MESH_PROV_ADV, NULL); } #endif @@ -469,7 +465,7 @@ u8_t bt_mesh_set_fast_prov_action(u8_t action) * here. The node needs to send some status messages to the phone * while it is connected. */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { bt_mesh_proxy_gatt_disable(); } #endif @@ -490,7 +486,7 @@ u8_t bt_mesh_set_fast_prov_action(u8_t action) } #if 0 /* Mesh Proxy GATT will be re-enabled on application layer */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && bt_mesh_gatt_proxy_get() != BLE_MESH_GATT_PROXY_NOT_SUPPORTED) { bt_mesh_proxy_gatt_enable(); bt_mesh_adv_update(); diff --git a/components/bt/esp_ble_mesh/mesh_core/net.c b/components/bt/esp_ble_mesh/mesh_core/net.c index 63d875f35..2bfba51d4 100644 --- a/components/bt/esp_ble_mesh/mesh_core/net.c +++ b/components/bt/esp_ble_mesh/mesh_core/net.c @@ -26,7 +26,7 @@ #include "net.h" #include "lpn.h" #include "friend.h" -#include "proxy.h" +#include "proxy_server.h" #include "transport.h" #include "access.h" #include "foundation.h" @@ -34,6 +34,7 @@ #include "settings.h" #include "prov.h" #include "provisioner_main.h" +#include "proxy_client.h" /* Minimum valid Mesh Network PDU length. The Network headers * themselves take up 9 bytes. After that there is a minumum of 1 byte @@ -89,6 +90,10 @@ struct bt_mesh_net bt_mesh = { static u32_t dup_cache[4]; static int dup_cache_next; +#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) +#define BLE_MESH_MAX_STORED_RELAY_COUNT (CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT / 2) +#endif + static bool check_dup(struct net_buf_simple *data) { const u8_t *tail = net_buf_simple_tail(data); @@ -187,7 +192,7 @@ int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys, BT_DBG("NetID %s", bt_hex(keys->net_id, 8)); -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) err = bt_mesh_identity_key(key, keys->identity); if (err) { BT_ERR("%s, Unable to generate IdentityKey", __func__); @@ -469,7 +474,7 @@ int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16], sub->net_idx = idx; - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED; } else { sub->node_id = BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED; @@ -477,7 +482,7 @@ int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16], bt_mesh.iv_index = iv_index; bt_mesh_atomic_set_bit_to(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS, - BLE_MESH_IV_UPDATE(flags)); + BLE_MESH_IV_UPDATE(flags)); /* Set minimum required hours, since the 96-hour minimum requirement * doesn't apply straight after provisioning (since we can't know how @@ -609,7 +614,7 @@ void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub) bt_mesh_friend_sec_update(sub ? sub->net_idx : BLE_MESH_KEY_ANY); } - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { #if CONFIG_BLE_MESH_NODE bt_mesh_proxy_beacon_send(sub); @@ -724,8 +729,8 @@ u32_t bt_mesh_next_seq(void) } if (!bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS) && - bt_mesh.seq > IV_UPDATE_SEQ_LIMIT && - bt_mesh_subnet_get(BLE_MESH_KEY_PRIMARY)) { + bt_mesh.seq > IV_UPDATE_SEQ_LIMIT && + bt_mesh_subnet_get(BLE_MESH_KEY_PRIMARY)) { #if CONFIG_BLE_MESH_NODE bt_mesh_beacon_ivu_initiator(true); #endif @@ -785,8 +790,8 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, } if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && - bt_mesh_proxy_relay(&buf->b, dst)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_proxy_relay(&buf->b, dst)) { send_cb_finalize(cb, cb_data); return 0; } @@ -897,12 +902,29 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, */ #if CONFIG_BLE_MESH_NODE if (bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && - tx->ctx->send_ttl != 1U) { - if (bt_mesh_proxy_relay(&buf->b, tx->ctx->addr) && - BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* Notify completion if this only went - * through the Mesh Proxy. + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + tx->ctx->send_ttl != 1U) { + if (bt_mesh_proxy_relay(&buf->b, tx->ctx->addr) && + BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + /* Notify completion if this only went + * through the Mesh Proxy. + */ + send_cb_finalize(cb, cb_data); + + err = 0; + goto done; + } + } + } +#endif + +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + if (tx->ctx->send_ttl != 1U) { + if (bt_mesh_proxy_client_send(&buf->b, tx->ctx->addr)) { + /* If Proxy Client succeeds to send messages with GATT bearer, + * we can directly finish here. And if not, which means no + * connection has been created with Proxy Client, here we will + * use advertising bearer for the messages. */ send_cb_finalize(cb, cb_data); @@ -910,7 +932,6 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, goto done; } } - } #endif /* Deliver to local network interface if necessary */ @@ -1028,11 +1049,11 @@ static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc, #if CONFIG_BLE_MESH_NODE if (bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_PROXY) && - rx->net_if == BLE_MESH_NET_IF_PROXY_CFG) { - return bt_mesh_net_decrypt(enc, buf, BLE_MESH_NET_IVI_RX(rx), - true); - } + if (IS_ENABLED(CONFIG_BLE_MESH_PROXY) && + rx->net_if == BLE_MESH_NET_IF_PROXY_CFG) { + return bt_mesh_net_decrypt(enc, buf, BLE_MESH_NET_IVI_RX(rx), + true); + } } #endif @@ -1202,7 +1223,25 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, transmit = bt_mesh_net_transmit_get(); } + /** + * When the node tries to relay a Segment ACK message, in this case + * the corresponding segment packets (if exist) can be removed from + * the relay queue. + */ + +#if !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA, transmit, K_NO_WAIT); +#else + /** + * Check if the number of relay packets in queue is too large, if so + * use minimum relay retransmit value for later relay packets. + */ + if (bt_mesh_get_stored_relay_count() >= BLE_MESH_MAX_STORED_RELAY_COUNT) { + transmit = BLE_MESH_TRANSMIT(0, 20); + } + buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_DATA, transmit, K_NO_WAIT); +#endif + if (!buf) { BT_ERR("%s, Out of relay buffers", __func__); return; @@ -1246,7 +1285,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, /* Sending to the GATT bearer should only happen if GATT Proxy * is enabled or the message originates from the local node. */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED || rx->net_if == BLE_MESH_NET_IF_LOCAL)) { if (bt_mesh_proxy_relay(&buf->b, rx->ctx.recv_dst) && @@ -1256,7 +1295,11 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, } if (relay_to_adv(rx->net_if)) { +#if !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) bt_mesh_adv_send(buf, NULL, NULL); +#else + bt_mesh_relay_adv_send(buf, NULL, NULL, rx->ctx.addr, rx->ctx.recv_dst); +#endif } done: @@ -1373,7 +1416,7 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi, #if CONFIG_BLE_MESH_NODE if (bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && net_if == BLE_MESH_NET_IF_PROXY) { bt_mesh_proxy_addr_add(data, rx.ctx.addr); } @@ -1402,11 +1445,11 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi, */ #if CONFIG_BLE_MESH_NODE if (bt_mesh_is_provisioned()) { - if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) || - (!rx.local_match && !rx.friend_match)) { - net_buf_simple_restore(&buf, &state); - bt_mesh_net_relay(&buf, &rx); - } + if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) || + (!rx.local_match && !rx.friend_match)) { + net_buf_simple_restore(&buf, &state); + bt_mesh_net_relay(&buf, &rx); + } } #endif } @@ -1448,7 +1491,7 @@ void bt_mesh_net_start(void) bt_mesh_beacon_disable(); } - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && bt_mesh_gatt_proxy_get() != BLE_MESH_GATT_PROXY_NOT_SUPPORTED) { bt_mesh_proxy_gatt_enable(); bt_mesh_adv_update(); @@ -1457,7 +1500,7 @@ void bt_mesh_net_start(void) #if defined(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN) /* Add Mesh beacon type (Secure Network Beacon) to the exceptional list */ bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD, - BLE_MESH_EXCEP_INFO_MESH_BEACON, NULL); + BLE_MESH_EXCEP_INFO_MESH_BEACON, NULL); #endif if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { diff --git a/components/bt/esp_ble_mesh/mesh_core/net.h b/components/bt/esp_ble_mesh/mesh_core/net.h index 150e2ff36..bc600cfd1 100644 --- a/components/bt/esp_ble_mesh/mesh_core/net.h +++ b/components/bt/esp_ble_mesh/mesh_core/net.h @@ -67,7 +67,7 @@ struct bt_mesh_subnet { u8_t nid; /* NID */ u8_t enc[16]; /* EncKey */ u8_t net_id[8]; /* Network ID */ -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) u8_t identity[16]; /* IdentityKey */ #endif u8_t privacy[16]; /* PrivacyKey */ @@ -393,7 +393,7 @@ void friend_cred_clear(struct friend_cred *cred); int friend_cred_del(u16_t net_idx, u16_t addr); static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb, - void *cb_data) + void *cb_data) { if (!cb) { return; diff --git a/components/bt/esp_ble_mesh/mesh_core/nimble_host/mesh_bearer_adapt.c b/components/bt/esp_ble_mesh/mesh_core/nimble_host/mesh_bearer_adapt.c index a19f957d5..e9ff95019 100644 --- a/components/bt/esp_ble_mesh/mesh_core/nimble_host/mesh_bearer_adapt.c +++ b/components/bt/esp_ble_mesh/mesh_core/nimble_host/mesh_bearer_adapt.c @@ -37,11 +37,11 @@ /** @def BT_UUID_MESH_PROV * @brief Mesh Provisioning Service - */ + */ #define BT_UUID_MESH_PROV_VAL 0x1827 /** @def BT_UUID_MESH_PROXY * @brief Mesh Proxy Service - */ + */ #define BT_UUID_MESH_PROXY_VAL 0x1828 /** @def BT_UUID_GATT_CCC * @brief GATT Client Characteristic Configuration @@ -128,12 +128,12 @@ void bt_mesh_hci_init(void) } static struct ble_gap_disc_params scan_param; -#if defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT static struct gattc_prov_info { /* Service to be found depends on the type of adv pkt received */ struct bt_mesh_conn conn; - BD_ADDR addr; - u8_t addr_type; + bt_mesh_addr_t addr; u16_t service_uuid; u16_t mtu; bool wr_desc_done; /* Indicate if write char descriptor event is received */ @@ -147,18 +147,18 @@ static struct gattc_prov_info { static struct bt_mesh_prov_conn_cb *bt_mesh_gattc_conn_cb; static int ble_on_subscribe(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) { struct bt_mesh_conn *conn = NULL; uint8_t value[2] = {0x01, 0x00}; int i = (int)arg, j, len; MODLOG_DFLT(INFO, "Subscribe complete; status=%d conn_handle=%d " - "attr_handle=%d\n", + "attr_handle=%d\n", error->status, conn_handle, attr->handle); - for (j = i+1; j < ARRAY_SIZE(bt_mesh_gattc_info); j++) { + for (j = i + 1; j < ARRAY_SIZE(bt_mesh_gattc_info); j++) { if ((bt_mesh_gattc_info[j].conn.handle == conn_handle) && bt_mesh_gattc_info[j].ccc_handle) { break; } @@ -175,7 +175,7 @@ static int ble_on_subscribe(uint16_t conn_handle, if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->prov_write_descr != NULL) { - len = bt_mesh_gattc_conn_cb->prov_write_descr(&bt_mesh_gattc_info[i].conn, bt_mesh_gattc_info[i].addr); + len = bt_mesh_gattc_conn_cb->prov_write_descr(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn); if (len < 0) { BT_ERR("%s, prov_write_descr failed", __func__); bt_mesh_gattc_disconnect(conn); @@ -185,12 +185,13 @@ static int ble_on_subscribe(uint16_t conn_handle, } } else if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROXY_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->proxy_write_descr != NULL) { - len = bt_mesh_gattc_conn_cb->proxy_write_descr(&bt_mesh_gattc_info[i].conn); + len = bt_mesh_gattc_conn_cb->proxy_write_descr(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn); if (len < 0) { BT_ERR("%s, proxy_write_descr failed", __func__); bt_mesh_gattc_disconnect(conn); return 0; } + bt_mesh_gattc_info[i].wr_desc_done = true; } } @@ -203,8 +204,8 @@ static int ble_on_subscribe(uint16_t conn_handle, } static int dsc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, - uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, - void *arg) + uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, + void *arg) { int rc = 0, j, i = (int)arg; /* char index */ uint8_t value[2] = {0x01, 0x00}; @@ -218,9 +219,9 @@ static int dsc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, /* All descriptors in this characteristic discovered; start discovering * descriptors in the next characteristic. */ - for (j = i+1; j < ARRAY_SIZE(bt_mesh_gattc_info); j++) { + for (j = i + 1; j < ARRAY_SIZE(bt_mesh_gattc_info); j++) { if ((bt_mesh_gattc_info[j].conn.handle == conn_handle) && bt_mesh_gattc_info[j].data_out_handle) { - break; + break; } } if (j == ARRAY_SIZE(bt_mesh_gattc_info)) { @@ -251,7 +252,7 @@ static int dsc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, static int chr_disced(uint16_t conn_handle, const struct ble_gatt_error *error, - const struct ble_gatt_chr *chr, void *arg) + const struct ble_gatt_chr *chr, void *arg) { int rc = 0, j; uint16_t uuid16 = 0; @@ -284,9 +285,9 @@ static int chr_disced(uint16_t conn_handle, const struct ble_gatt_error *error, /* All characteristics in this service discovered; start discovering * characteristics in the next service. */ - for (j = i+1; j < ARRAY_SIZE(bt_mesh_gattc_info); j++) { + for (j = i + 1; j < ARRAY_SIZE(bt_mesh_gattc_info); j++) { if ((bt_mesh_gattc_info[j].conn.handle == conn_handle) && (bt_mesh_gattc_info[j].start_handle > bt_mesh_gattc_info[j].end_handle)) { - break; + break; } } if (j == ARRAY_SIZE(bt_mesh_gattc_info)) { @@ -298,7 +299,7 @@ static int chr_disced(uint16_t conn_handle, const struct ble_gatt_error *error, ble_gattc_disc_all_dscs(conn_handle, bt_mesh_gattc_info[j].data_out_handle, 0xffff, dsc_disced, (void *)j); } else { ble_gattc_disc_all_chrs(conn_handle, bt_mesh_gattc_info[j].start_handle, bt_mesh_gattc_info[j].end_handle, - chr_disced, (void *)j); + chr_disced, (void *)j); } break; @@ -312,7 +313,7 @@ static int chr_disced(uint16_t conn_handle, const struct ble_gatt_error *error, static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, - const struct ble_gatt_svc *service, void *arg) + const struct ble_gatt_svc *service, void *arg) { struct bt_mesh_conn *conn = NULL; int rc = 0, i; @@ -326,7 +327,7 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, uuid = &service->uuid; uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); if (uuid_length != 2) { - return 0; + return 0; } for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].service_uuid == (uint16_t)BLE_UUID16(uuid)->value) { @@ -358,10 +359,10 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, /* Get the characteristic num within Mesh Provisioning/Proxy Service */ ble_gattc_disc_all_chrs(conn_handle, bt_mesh_gattc_info[i].start_handle, bt_mesh_gattc_info[i].end_handle, - chr_disced, (void *)i); + chr_disced, (void *)i); break; - default: + default: rc = error->status; break; } @@ -370,13 +371,14 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, } -#endif /* defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ static int disc_cb(struct ble_gap_event *event, void *arg) { struct ble_gap_disc_desc *desc; -#if defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT int rc, i; uint8_t notif_data[100]; uint16_t notif_len; @@ -401,7 +403,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) } osi_free(buf); break; -#if defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT case BLE_GAP_EVENT_CONNECT: if (event->connect.status == 0) { /* Connection successfully established. */ @@ -412,9 +415,9 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->connected != NULL) { for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (!memcmp(bt_mesh_gattc_info[i].addr, conn_desc.peer_id_addr.val, BLE_MESH_ADDR_LEN)) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, conn_desc.peer_id_addr.val, BLE_MESH_ADDR_LEN)) { bt_mesh_gattc_info[i].conn.handle = event->connect.conn_handle; - (bt_mesh_gattc_conn_cb->connected)(bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn, i); + (bt_mesh_gattc_conn_cb->connected)(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn, i); break; } } @@ -441,24 +444,36 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->disconnected != NULL) { for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { memcpy(&conn_desc, &event->disconnect.conn, sizeof(conn_desc)); - if (!memcmp(bt_mesh_gattc_info[i].addr, conn_desc.peer_ota_addr.val, BLE_MESH_ADDR_LEN)) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, conn_desc.peer_ota_addr.val, BLE_MESH_ADDR_LEN)) { if (bt_mesh_gattc_info[i].conn.handle == event->disconnect.conn.conn_handle) { - (bt_mesh_gattc_conn_cb->disconnected)(&bt_mesh_gattc_info[i].conn, event->disconnect.reason); + (bt_mesh_gattc_conn_cb->disconnected)(&bt_mesh_gattc_info[i].addr, &bt_mesh_gattc_info[i].conn, event->disconnect.reason); if (!bt_mesh_gattc_info[i].wr_desc_done) { /* Add this in case connection is established, connected event comes, but * connection is terminated before server->filter_type is set to PROV. */ - provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr); +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { + provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr.val); + } +#endif } } else { /* Add this in case connection is failed to be established, and here we * need to clear some provision link info, like connecting flag, device * uuid, address info, etc. */ - provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr); +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { + provisioner_clear_link_conn_info(bt_mesh_gattc_info[i].addr.val); + } +#endif } - /* Decrease prov pbg_count */ - provisioner_pbg_count_dec(); +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { + /* Decrease prov pbg_count */ + provisioner_pbg_count_dec(); + } +#endif /* Reset corresponding gattc info */ memset(&bt_mesh_gattc_info[i], 0, sizeof(bt_mesh_gattc_info[i])); bt_mesh_gattc_info[i].conn.handle = 0xFFFF; @@ -514,8 +529,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) /* Data isn't populated yet */ return 0; } - - if (memcmp(bt_mesh_gattc_info[i].addr, conn_desc.peer_id_addr.val, BLE_MESH_ADDR_LEN) || + + if (memcmp(bt_mesh_gattc_info[i].addr.val, conn_desc.peer_id_addr.val, BLE_MESH_ADDR_LEN) || (bt_mesh_gattc_info[i].data_out_handle != event->notify_rx.attr_handle) || (event->notify_rx.indication != 0)) { BT_ERR("%s, Notification error", __func__); @@ -693,7 +708,7 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) u16_t len = 0; uint16_t ccc_val = 0; - if (event->subscribe.prev_notify != event->subscribe.cur_notify) { + if (event->subscribe.prev_notify != event->subscribe.cur_notify) { ccc_val = event->subscribe.cur_notify; } else if (event->subscribe.prev_indicate != event->subscribe.cur_indicate) { if (event->subscribe.cur_indicate) { @@ -705,12 +720,12 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) if (attr != NULL && attr->write != NULL) { if ((len = attr->write(&bt_mesh_gatts_conn[index], attr, - &ccc_val, - sizeof(ccc_val), - 0 /* offset */, 0)) > 0) { + &ccc_val, + sizeof(ccc_val), + 0 /* offset */, 0)) > 0) { } } - + return 0; case BLE_GAP_EVENT_MTU: @@ -917,7 +932,7 @@ static struct bt_mesh_gatt_attr *bt_mesh_gatts_find_attr_by_handle(u16_t handle) } static void bt_mesh_gatts_foreach_attr(u16_t start_handle, u16_t end_handle, - bt_mesh_gatt_attr_func_t func, void *user_data) + bt_mesh_gatt_attr_func_t func, void *user_data) { struct bt_mesh_gatt_service *svc = NULL; @@ -984,8 +999,8 @@ struct gatts_incl { } __packed; ssize_t bt_mesh_gatts_attr_read_included(struct bt_mesh_conn *conn, - const struct bt_mesh_gatt_attr *attr, - void *buf, u16_t len, u16_t offset) + const struct bt_mesh_gatt_attr *attr, + void *buf, u16_t len, u16_t offset) { struct bt_mesh_gatt_attr *incl = attr->user_data; struct bt_mesh_uuid *uuid = incl->user_data; @@ -1021,7 +1036,7 @@ ssize_t bt_mesh_gatts_attr_read_service(struct bt_mesh_conn *conn, } return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, - BLE_MESH_UUID_128(uuid)->val, 16); + BLE_MESH_UUID_128(uuid)->val, 16); } struct gatts_chrc { @@ -1186,12 +1201,28 @@ int bt_mesh_gatts_service_start(struct bt_mesh_gatt_service *svc) } #endif /* defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE */ -#if defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT void bt_mesh_gattc_conn_cb_register(struct bt_mesh_prov_conn_cb *cb) { bt_mesh_gattc_conn_cb = cb; } +u8_t bt_mesh_gattc_get_free_conn_count(void) +{ + u8_t count = 0; + u8_t i; + + for (i = 0U; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + if (bt_mesh_gattc_info[i].conn.handle == 0xFFFF && + bt_mesh_gattc_info[i].service_uuid == 0x0000) { + ++count; + } + } + + return count; +} + u16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn) { int i; @@ -1225,22 +1256,22 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid) int i, rc; if (!addr || !memcmp(addr->val, zero, BLE_MESH_ADDR_LEN) || - (addr->type > BLE_ADDR_RANDOM)) { + (addr->type > BLE_ADDR_RANDOM)) { BT_ERR("%s, Invalid remote address", __func__); return -EINVAL; } if (service_uuid != BLE_MESH_UUID_MESH_PROV_VAL && - service_uuid != BLE_MESH_UUID_MESH_PROXY_VAL) { + service_uuid != BLE_MESH_UUID_MESH_PROXY_VAL) { BT_ERR("%s, Invalid service uuid 0x%04x", __func__, service_uuid); return -EINVAL; } /* Check if already creating connection with the device */ for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (!memcmp(bt_mesh_gattc_info[i].addr, addr->val, BLE_MESH_ADDR_LEN)) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, addr->val, BLE_MESH_ADDR_LEN)) { BT_WARN("%s, Already create connection with %s", - __func__, bt_hex(addr->val, BLE_MESH_ADDR_LEN)); + __func__, bt_hex(addr->val, BLE_MESH_ADDR_LEN)); return -EALREADY; } } @@ -1248,9 +1279,9 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid) /* Find empty element in queue to store device info */ for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if ((bt_mesh_gattc_info[i].conn.handle == 0xFFFF) && - (bt_mesh_gattc_info[i].service_uuid == 0x0000)) { - memcpy(bt_mesh_gattc_info[i].addr, addr->val, BLE_MESH_ADDR_LEN); - bt_mesh_gattc_info[i].addr_type = addr->type; + (bt_mesh_gattc_info[i].service_uuid == 0x0000)) { + memcpy(bt_mesh_gattc_info[i].addr.val, addr->val, BLE_MESH_ADDR_LEN); + bt_mesh_gattc_info[i].addr.type = addr->type; /* Service to be found after exhanging mtu size */ bt_mesh_gattc_info[i].service_uuid = service_uuid; break; @@ -1270,10 +1301,10 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid) } } #else - rc = ble_gap_disc_cancel(); - if (rc != 0) { - return -1; - } + rc = ble_gap_disc_cancel(); + if (rc != 0) { + return -1; + } #endif /* BLE_MESH_DEV */ BT_DBG("%s, create conn with %s", __func__, bt_hex(addr->val, BLE_MESH_ADDR_LEN)); @@ -1296,19 +1327,17 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, u16_t service_uuid) ble_addr_t peer_addr; memcpy(peer_addr.val, addr->val, 6); - peer_addr.type = addr->type; + peer_addr.type = addr->type; rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &peer_addr, BLE_HS_FOREVER, &conn_params, disc_cb, NULL); - /* Increment pbg_count */ - provisioner_pbg_count_inc(); - return 0; + return i; } static int mtu_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - uint16_t mtu, void *arg) + const struct ble_gatt_error *error, + uint16_t mtu, void *arg) { int i; if (error->status == 0) { @@ -1417,7 +1446,7 @@ void bt_mesh_gattc_disconnect(struct bt_mesh_conn *conn) * Mesh Proxy Data In: 0x2ADD * Mesh PROXY Data Out: 0x2ADE */ -#endif /* defined(CONFIG_BLE_MESH_PROVISIONER) && CONFIG_BLE_MESH_PROVISIONER */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ struct bt_mesh_conn *bt_mesh_conn_ref(struct bt_mesh_conn *conn) { @@ -1437,7 +1466,7 @@ void bt_mesh_conn_unref(struct bt_mesh_conn *conn) #if defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE static int proxy_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) + struct ble_gatt_access_ctxt *ctxt, void *arg) { if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR || ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) { struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(attr_handle); @@ -1445,14 +1474,14 @@ static int proxy_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, u16_t len = 0; BT_DBG("%s, write: handle = %d, len = %d, data = %s", __func__, attr_handle, - ctxt->om->om_len, - bt_hex(ctxt->om->om_data, ctxt->om->om_len)); + ctxt->om->om_len, + bt_hex(ctxt->om->om_data, ctxt->om->om_len)); if (attr != NULL && attr->write != NULL) { if ((len = attr->write(&bt_mesh_gatts_conn[index], attr, - ctxt->om->om_data, - ctxt->om->om_len, - 0 /* offset */, 0)) > 0) { + ctxt->om->om_data, + ctxt->om->om_len, + 0 /* offset */, 0)) > 0) { } } } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR || ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) { @@ -1462,7 +1491,7 @@ static int proxy_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, } static int dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) + struct ble_gatt_access_ctxt *ctxt, void *arg) { /* * We should never never enter this callback - it's attached to notify-only @@ -1474,50 +1503,54 @@ static int dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, } static const struct ble_gatt_svc_def svc_defs [] = { -#ifdef CONFIG_BLE_MESH_GATT_PROXY - { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), +#ifdef CONFIG_BLE_MESH_GATT_PROXY_SERVER + { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), .includes = NULL, - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), - .access_cb = proxy_char_access_cb, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, + .characteristics = (struct ble_gatt_chr_def[]) + { { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), + .access_cb = proxy_char_access_cb, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, + }, { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), + .access_cb = dummy_access_cb, + .flags = BLE_GATT_CHR_F_NOTIFY, + }, { + 0, /* No more characteristics in this service. */ + } + }, + }, #endif #ifdef CONFIG_BLE_MESH_PB_GATT { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), .includes = NULL, - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - .access_cb = proxy_char_access_cb, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, + .characteristics = (struct ble_gatt_chr_def[]) + { { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), + .access_cb = proxy_char_access_cb, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, + }, { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), + .access_cb = dummy_access_cb, + .flags = BLE_GATT_CHR_F_NOTIFY, + }, { + 0, /* No more characteristics in this service. */ + } + }, + }, #endif { - 0, /* No more services. */ - }, + 0, /* No more services. */ + }, }; #endif void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt, - void * arg ) + void *arg ) { if (ctxt->op == BLE_GATT_REGISTER_OP_SVC) { if (ble_uuid_cmp(ctxt->svc.svc_def->uuid, BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL)) == 0) { @@ -1551,7 +1584,8 @@ void bt_mesh_gatt_init(void) ble_gatts_svc_set_visibility(proxy_svc_start_handle, 0); #endif -#if CONFIG_BLE_MESH_PROVISIONER +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { bt_mesh_gattc_info[i].conn.handle = 0xFFFF; bt_mesh_gattc_info[i].mtu = BLE_ATT_MTU_DFLT; @@ -1665,7 +1699,7 @@ exit: } int ble_sm_alg_gen_dhkey(uint8_t *peer_pub_key_x, uint8_t *peer_pub_key_y, - uint8_t *our_priv_key, uint8_t *out_dhkey); + uint8_t *our_priv_key, uint8_t *out_dhkey); int bt_mesh_dh_key_gen(const u8_t remote_pk[64], bt_mesh_dh_key_cb_t cb, const u8_t idx) { diff --git a/components/bt/esp_ble_mesh/mesh_core/prov.c b/components/bt/esp_ble_mesh/mesh_core/prov.c index 63ba90acb..c1b7bbcd5 100644 --- a/components/bt/esp_ble_mesh/mesh_core/prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/prov.c @@ -24,7 +24,7 @@ #include "net.h" #include "access.h" #include "foundation.h" -#include "proxy.h" +#include "proxy_server.h" #include "prov.h" #if CONFIG_BLE_MESH_NODE @@ -292,7 +292,7 @@ static void reset_adv_link(void) #if defined(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN) /* Remove the link id from exceptional list */ bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_REMOVE, - BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link.id); + BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link.id); #endif reset_state(); @@ -1000,7 +1000,7 @@ static int bt_mesh_calc_dh_key(void) } int bt_mesh_set_oob_pub_key(const u8_t pub_key_x[32], const u8_t pub_key_y[32], - const u8_t pri_key[32]) + const u8_t pri_key[32]) { if (!pub_key_x || !pub_key_y || !pri_key) { BT_ERR("%s, Invalid parameter", __func__); @@ -1203,7 +1203,7 @@ static void prov_data(const u8_t *data) link.expect = 0U; /* Store info, since bt_mesh_provision() will end up clearing it */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { identity_enable = is_pb_gatt(); } else { identity_enable = false; @@ -1218,7 +1218,7 @@ static void prov_data(const u8_t *data) /* After PB-GATT provisioning we should start advertising * using Node Identity. */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY) && identity_enable) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && identity_enable) { bt_mesh_proxy_identity_enable(); } } @@ -1333,7 +1333,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf) #if defined(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN) /* Add the link id into exceptional list */ bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD, - BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link.id); + BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link.id); #endif bearer_ctl_send(LINK_ACK, NULL, 0); @@ -1416,7 +1416,7 @@ static void prov_msg_recv(void) if (1 + prov_handlers[type].len != link.rx.buf->len) { BT_ERR("%s, Invalid length %u for type 0x%02x", - __func__, link.rx.buf->len, type); + __func__, link.rx.buf->len, type); prov_send_fail_msg(PROV_ERR_NVAL_FMT); return; } @@ -1466,7 +1466,7 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf) ((link.rx.last_seg - 1) * 23U)); if (expect_len != buf->len) { BT_ERR("%s, Incorrect last seg len: %u != %u", - __func__, expect_len, buf->len); + __func__, expect_len, buf->len); prov_send_fail_msg(PROV_ERR_NVAL_FMT); return; } @@ -1526,7 +1526,7 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf) if (link.rx.buf->len > link.rx.buf->size) { BT_ERR("%s, Too large provisioning PDU (%u bytes)", - __func__, link.rx.buf->len); + __func__, link.rx.buf->len); /* Zephyr uses prov_send_fail_msg() here */ return; } diff --git a/components/bt/esp_ble_mesh/mesh_core/prov.h b/components/bt/esp_ble_mesh/mesh_core/prov.h index 610e55c6d..756cd011f 100644 --- a/components/bt/esp_ble_mesh/mesh_core/prov.h +++ b/components/bt/esp_ble_mesh/mesh_core/prov.h @@ -22,7 +22,7 @@ int bt_mesh_pb_gatt_close(struct bt_mesh_conn *conn); int bt_mesh_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_simple *buf); int bt_mesh_set_oob_pub_key(const u8_t pub_key_x[32], const u8_t pub_key_y[32], - const u8_t pri_key[32]); + const u8_t pri_key[32]); const struct bt_mesh_prov *bt_mesh_prov_get(void); diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c index 44049fd0c..7b40331a0 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c @@ -30,7 +30,7 @@ #include "access.h" #include "provisioner_prov.h" -#include "provisioner_proxy.h" +#include "proxy_client.h" #include "provisioner_main.h" #if CONFIG_BLE_MESH_PROVISIONER @@ -240,7 +240,7 @@ int provisioner_upper_init(void) which has been initialized in the application layer */ bt_mesh.iv_index = prov->iv_index; bt_mesh_atomic_set_bit_to(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS, - BLE_MESH_IV_UPDATE(prov->flags)); + BLE_MESH_IV_UPDATE(prov->flags)); /* Set minimum required hours, since the 96-hour minimum requirement * doesn't apply straight after provisioning (since we can't know how @@ -256,7 +256,9 @@ int provisioner_upper_init(void) BT_DBG("netkey: %s, nid: 0x%x", bt_hex(sub->keys[0].net, 16), sub->keys[0].nid); BT_DBG("enckey: %s", bt_hex(sub->keys[0].enc, 16)); BT_DBG("network id: %s", bt_hex(sub->keys[0].net_id, 8)); +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) BT_DBG("identity: %s", bt_hex(sub->keys[0].identity, 16)); +#endif BT_DBG("privacy: %s", bt_hex(sub->keys[0].privacy, 16)); BT_DBG("beacon: %s", bt_hex(sub->keys[0].beacon, 16)); diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c index e07be193a..94cbccba7 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c @@ -27,15 +27,13 @@ #include "adv.h" #include "mesh.h" #include "provisioner_prov.h" -#include "provisioner_proxy.h" +#include "proxy_client.h" #include "provisioner_main.h" #if CONFIG_BLE_MESH_PROVISIONER -/* Service data length has minus 1 type length & 2 uuid length*/ -#define BLE_MESH_PROV_SRV_DATA_LEN 0x12 -#define BLE_MESH_PROXY_SRV_DATA_LEN1 0x09 -#define BLE_MESH_PROXY_SRV_DATA_LEN2 0x11 +_Static_assert(BLE_MESH_MAX_CONN >= CONFIG_BLE_MESH_PBG_SAME_TIME, + "Too large BLE Mesh PB-GATT count"); /* 3 transmissions, 20ms interval */ #define PROV_XMIT BLE_MESH_TRANSMIT(2, 20) @@ -378,14 +376,14 @@ void provisioner_pbg_count_dec(void) } } -void provisioner_pbg_count_inc(void) +static inline void provisioner_pbg_count_inc(void) { prov_ctx.pbg_count++; } +#if defined(CONFIG_BLE_MESH_PB_GATT) void provisioner_clear_link_conn_info(const u8_t addr[6]) { -#if defined(CONFIG_BLE_MESH_PB_GATT) u8_t i; if (!addr) { @@ -411,9 +409,9 @@ void provisioner_clear_link_conn_info(const u8_t addr[6]) } BT_WARN("%s, Address %s is not found", __func__, bt_hex(addr, BLE_MESH_ADDR_LEN)); -#endif return; } +#endif const struct bt_mesh_prov *provisioner_get_prov_info(void) { @@ -522,7 +520,7 @@ static bool is_unprov_dev_being_provision(const u8_t uuid[16]) for (i = 0U; i < BLE_MESH_PROV_SAME_TIME; i++) { #if defined(CONFIG_BLE_MESH_PB_ADV) && defined(CONFIG_BLE_MESH_PB_GATT) if (link[i].linking || link[i].connecting || - bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) { + bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) { #elif defined(CONFIG_BLE_MESH_PB_ADV) && !defined(CONFIG_BLE_MESH_PB_GATT) if (link[i].linking || bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) { #else @@ -542,7 +540,7 @@ static bool is_unprov_dev_uuid_match(const u8_t uuid[16]) { if (prov_ctx.match_length && prov_ctx.match_value) { if (memcmp(uuid + prov_ctx.match_offset, - prov_ctx.match_value, prov_ctx.match_length)) { + prov_ctx.match_value, prov_ctx.match_length)) { return false; } } @@ -601,7 +599,7 @@ static int provisioner_check_unprov_dev_info(const u8_t uuid[16]) #if defined(CONFIG_BLE_MESH_PB_ADV) static int provisioner_start_prov_pb_adv(const u8_t uuid[16], - const bt_mesh_addr_t *addr, u16_t oob_info) + const bt_mesh_addr_t *addr, u16_t oob_info) { u8_t zero[6] = {0}; int addr_cmp; @@ -643,7 +641,7 @@ static int provisioner_start_prov_pb_adv(const u8_t uuid[16], #if defined(CONFIG_BLE_MESH_PB_GATT) static int provisioner_start_prov_pb_gatt(const u8_t uuid[16], - const bt_mesh_addr_t *addr, u16_t oob_info) + const bt_mesh_addr_t *addr, u16_t oob_info) { u8_t zero[6] = {0}; int addr_cmp; @@ -671,7 +669,7 @@ static int provisioner_start_prov_pb_gatt(const u8_t uuid[16], link[i].addr.type = addr->type; memcpy(link[i].addr.val, addr->val, BLE_MESH_ADDR_LEN); } - if (bt_mesh_gattc_conn_create(&link[i].addr, BLE_MESH_UUID_MESH_PROV_VAL)) { + if (bt_mesh_gattc_conn_create(&link[i].addr, BLE_MESH_UUID_MESH_PROV_VAL) < 0) { memset(link[i].uuid, 0, 16); link[i].oob_info = 0x0; memset(&link[i].addr, 0, sizeof(bt_mesh_addr_t)); @@ -680,6 +678,7 @@ static int provisioner_start_prov_pb_gatt(const u8_t uuid[16], } /* If creating connection successfully, set connecting flag to 1 */ link[i].connecting = true; + provisioner_pbg_count_inc(); osi_mutex_unlock(&prov_ctx.pb_gatt_lock); return 0; } @@ -709,7 +708,7 @@ int bt_mesh_provisioner_add_unprov_dev(struct bt_mesh_unprov_dev_add *add_dev, u uuid_cmp = memcmp(add_dev->uuid, zero, 16); if (add_dev->bearer == 0x0 || ((uuid_cmp == 0) && - ((addr_cmp == 0) || add_dev->addr_type > BLE_MESH_ADDR_RANDOM))) { + ((addr_cmp == 0) || add_dev->addr_type > BLE_MESH_ADDR_RANDOM))) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } @@ -805,7 +804,7 @@ start: /* Check if current provisioned node count + active link reach max limit */ if (prov_ctx.node_count + prov_ctx.pba_count + \ - prov_ctx.pbg_count >= ARRAY_SIZE(prov_nodes)) { + prov_ctx.pbg_count >= ARRAY_SIZE(prov_nodes)) { BT_WARN("%s, Node count + active link count reach max limit", __func__); return -EIO; } @@ -821,7 +820,7 @@ start: return -EIO; } if ((err = provisioner_start_prov_pb_adv( - add_dev->uuid, &add_addr, add_dev->oob_info))) { + add_dev->uuid, &add_addr, add_dev->oob_info))) { return err; } #endif @@ -832,7 +831,7 @@ start: return -EIO; } if ((err = provisioner_start_prov_pb_gatt( - add_dev->uuid, &add_addr, add_dev->oob_info))) { + add_dev->uuid, &add_addr, add_dev->oob_info))) { return err; } #endif @@ -1135,7 +1134,7 @@ static void reset_link(const u8_t idx, u8_t reason) #if defined(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN) /* Remove the link id from exceptional list */ bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_REMOVE, - BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link[idx].link_id); + BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link[idx].link_id); #endif /* Clear everything except the retransmit delayed work config */ @@ -1295,7 +1294,7 @@ static void send_link_open(const u8_t idx) #if defined(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN) /* Add the link id into exceptional list */ bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD, - BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link[idx].link_id); + BLE_MESH_EXCEP_INFO_MESH_LINK_ID, &link[idx].link_id); #endif bearer_ctl_send(idx, LINK_OPEN, link[idx].uuid, 16); @@ -1424,7 +1423,7 @@ static int prov_send_gatt(const u8_t idx, struct net_buf_simple *msg) return -ENOTCONN; } - err = provisioner_proxy_send(link[idx].conn, BLE_MESH_PROXY_PROV, msg); + err = bt_mesh_proxy_prov_client_send(link[idx].conn, BLE_MESH_PROXY_PROV, msg); if (err) { BT_ERR("%s, Failed to send PB-GATT pdu", __func__); return err; @@ -1449,9 +1448,9 @@ static inline int prov_send(const u8_t idx, struct net_buf_simple *buf) #if defined(CONFIG_BLE_MESH_PB_GATT) if (idx < BLE_MESH_PROV_SAME_TIME #if defined(CONFIG_BLE_MESH_PB_ADV) - && idx >= CONFIG_BLE_MESH_PBA_SAME_TIME + && idx >= CONFIG_BLE_MESH_PBA_SAME_TIME #endif - ) { + ) { return prov_send_gatt(idx, buf); } #endif @@ -1961,12 +1960,12 @@ static void prov_dh_key_cb(const u8_t key[32], const u8_t idx) * to output a value, and wait for prov input complete pdu. */ if (prov_auth(idx, link[idx].auth_method, - link[idx].auth_action, link[idx].auth_size) < 0) { + link[idx].auth_action, link[idx].auth_size) < 0) { BT_ERR("%s, Failed to authenticate", __func__); goto fail; } if (link[idx].auth_method == AUTH_METHOD_OUTPUT || - link[idx].auth_method == AUTH_METHOD_INPUT) { + link[idx].auth_method == AUTH_METHOD_INPUT) { return; } @@ -2091,7 +2090,7 @@ static void prov_input_complete(const u8_t idx, const u8_t *data) static void prov_confirm(const u8_t idx, const u8_t *data) { - /** + /** * Zephyr uses PROV_BUF(16). Currently test with PROV_BUF(16) * and PROV_BUF(17) on branch feature/btdm_ble_mesh_debug both * work fine. @@ -2398,9 +2397,9 @@ static void prov_complete(const u8_t idx, const u8_t *data) prov_ctx.node_count++; err = provisioner_node_provision(j, prov_nodes[j].uuid, prov_nodes[j].oob_info, - prov_nodes[j].unicast_addr, prov_nodes[j].element_num, - prov_nodes[j].net_idx, prov_nodes[j].flags, - prov_nodes[j].iv_index, device_key); + prov_nodes[j].unicast_addr, prov_nodes[j].element_num, + prov_nodes[j].net_idx, prov_nodes[j].flags, + prov_nodes[j].iv_index, device_key); if (err) { BT_ERR("%s, Failed to store node info", __func__); close_link(idx, CLOSE_REASON_FAILED); @@ -2461,9 +2460,9 @@ static void close_link(const u8_t idx, u8_t reason) #if defined(CONFIG_BLE_MESH_PB_GATT) if (idx < BLE_MESH_PROV_SAME_TIME #if defined(CONFIG_BLE_MESH_PB_ADV) - && idx >= CONFIG_BLE_MESH_PBA_SAME_TIME + && idx >= CONFIG_BLE_MESH_PBA_SAME_TIME #endif - ) { + ) { if (link[idx].conn) { bt_mesh_gattc_disconnect(link[idx].conn); } @@ -2660,7 +2659,7 @@ static void gen_prov_cont(const u8_t idx, struct prov_rx *rx, struct net_buf_sim if (rx->xact_id != link[idx].rx.trans_id) { BT_WARN("%s, Data for unknown transaction (%u != %u)", - __func__, rx->xact_id, link[idx].rx.trans_id); + __func__, rx->xact_id, link[idx].rx.trans_id); /** * If Provisioner receives a Provisioning PDU with a mismatch * transaction number, it just ignore it. @@ -2678,7 +2677,7 @@ static void gen_prov_cont(const u8_t idx, struct prov_rx *rx, struct net_buf_sim (23 * (link[idx].rx.last_seg - 1))); if (expect_len != buf->len) { BT_ERR("%s, Incorrect last seg len: %u != %u", - __func__, expect_len, buf->len); + __func__, expect_len, buf->len); goto fail; } } @@ -2763,7 +2762,7 @@ static void gen_prov_start(const u8_t idx, struct prov_rx *rx, struct net_buf_si if (link[idx].rx.buf->len > link[idx].rx.buf->size) { BT_ERR("%s, Too large provisioning PDU (%u bytes)", - __func__, link[idx].rx.buf->len); + __func__, link[idx].rx.buf->len); // close_link(i, CLOSE_REASON_FAILED); return; } @@ -2951,7 +2950,7 @@ int provisioner_pb_gatt_open(struct bt_mesh_conn *conn, u8_t *addr) BT_DBG("conn %p", conn); - /** + /** * Double check if the device is currently being provisioned using PB-ADV. * Provisioner binds conn with proper device when proxy_prov_connected() * is invoked, and here after proper GATT procedures are completed, we just @@ -3088,7 +3087,7 @@ int provisioner_prov_init(const struct bt_mesh_prov *prov_info) } static bool is_unprov_dev_info_callback_to_app(bt_mesh_prov_bearer_t bearer, - const u8_t uuid[16], const bt_mesh_addr_t *addr, u16_t oob_info) + const u8_t uuid[16], const bt_mesh_addr_t *addr, u16_t oob_info) { u16_t index; @@ -3106,7 +3105,7 @@ static bool is_unprov_dev_info_callback_to_app(bt_mesh_prov_bearer_t bearer, if (!(unprov_dev[index].bearer & bearer)) { BT_WARN("Device in queue not support PB-%s", - (bearer == BLE_MESH_PROV_ADV) ? "ADV" : "GATT"); + (bearer == BLE_MESH_PROV_ADV) ? "ADV" : "GATT"); if (notify_unprov_adv_pkt_cb) { notify_unprov_adv_pkt_cb(addr->val, addr->type, adv_type, uuid, oob_info, bearer); } @@ -3145,7 +3144,7 @@ void provisioner_unprov_beacon_recv(struct net_buf_simple *buf) } if (is_unprov_dev_info_callback_to_app( - BLE_MESH_PROV_ADV, uuid, addr, oob_info)) { + BLE_MESH_PROV_ADV, uuid, addr, oob_info)) { return; } @@ -3153,85 +3152,7 @@ void provisioner_unprov_beacon_recv(struct net_buf_simple *buf) #endif /* CONFIG_BLE_MESH_PB_ADV */ } -bool provisioner_flags_match(struct net_buf_simple *buf) -{ - u8_t flags; - - if (buf->len != 1) { - BT_DBG("%s, Unexpected flags length", __func__); - return false; - } - - flags = net_buf_simple_pull_u8(buf); - - BT_DBG("Received adv pkt with flags: 0x%02x", flags); - - /* Flags context will not be checked curently */ - - return true; -} - -u16_t provisioner_srv_uuid_recv(struct net_buf_simple *buf) -{ - u16_t uuid; - - if (buf->len != 2) { - BT_DBG("Length not match mesh service uuid"); - return false; - } - - uuid = net_buf_simple_pull_le16(buf); - - BT_DBG("Received adv pkt with service UUID: %d", uuid); - - if ((uuid != BLE_MESH_UUID_MESH_PROV_VAL) && (uuid != BLE_MESH_UUID_MESH_PROXY_VAL)) { - return false; - } - - return uuid; -} - -static void provisioner_prov_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr); - -void provisioner_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr, u16_t uuid) -{ - u16_t uuid_type; - - if (!buf || !addr) { - BT_ERR("%s, Invalid parameter", __func__); - return; - } - - uuid_type = net_buf_simple_pull_le16(buf); - if (uuid_type != uuid) { - BT_DBG("%s, Invalid Mesh Service Data UUID 0x%04x", __func__, uuid_type); - return; - } - - switch (uuid) { - case BLE_MESH_UUID_MESH_PROV_VAL: - if (buf->len != BLE_MESH_PROV_SRV_DATA_LEN) { - BT_WARN("%s, Invalid Mesh Prov Service Data length %d", __func__, buf->len); - return; - } - BT_DBG("Start to deal with Mesh Prov Service Data"); - provisioner_prov_srv_data_recv(buf, addr); - break; - case BLE_MESH_UUID_MESH_PROXY_VAL: - if (buf->len != BLE_MESH_PROXY_SRV_DATA_LEN1 && - buf->len != BLE_MESH_PROXY_SRV_DATA_LEN2) { - BT_ERR("%s, Invalid Mesh Proxy Service Data length %d", __func__, buf->len); - return; - } - BT_DBG("Start to deal with Mesh Proxy Service Data"); - provisioner_proxy_srv_data_recv(buf); - break; - default: - break; - } -} - -static void provisioner_prov_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr) +void provisioner_prov_adv_ind_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr) { #if defined(CONFIG_BLE_MESH_PB_GATT) const u8_t *uuid = NULL; @@ -3242,6 +3163,11 @@ static void provisioner_prov_srv_data_recv(struct net_buf_simple *buf, const bt_ return; } + if (bt_mesh_gattc_get_free_conn_count() == 0) { + BT_WARN("%s, max connections", __func__); + return; + } + uuid = buf->data; net_buf_simple_pull(buf, 16); /* Mesh beacon uses big-endian to send beacon data */ @@ -3252,7 +3178,7 @@ static void provisioner_prov_srv_data_recv(struct net_buf_simple *buf, const bt_ } if (is_unprov_dev_info_callback_to_app( - BLE_MESH_PROV_GATT, uuid, addr, oob_info)) { + BLE_MESH_PROV_GATT, uuid, addr, oob_info)) { return; } diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.h b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.h index 13360598e..6fea1df16 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.h +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.h @@ -75,13 +75,6 @@ struct bt_mesh_prov_data_info { */ void provisioner_pbg_count_dec(void); -/** - * @brief This function increments the current PB-GATT count. - * - * @return None - */ -void provisioner_pbg_count_inc(void); - /** * @brief This function clears the part of the link info of the proper device. * @@ -165,37 +158,7 @@ int provisioner_prov_init(const struct bt_mesh_prov *prov_info); */ void provisioner_unprov_beacon_recv(struct net_buf_simple *buf); -/** - * @brief This function parses the flags part of the - * received connectable mesh provisioning advertising packets. - * - * @param[in] buf: Pointer to the buffer containing advertising flags part - * - * @return True - success, False - fail - */ -bool provisioner_flags_match(struct net_buf_simple *buf); - -/** - * @brief This function parses the service UUID part of the - * received connectable mesh provisioning advertising packets. - * - * @param[in] buf: Pointer to the buffer containing service UUID part - * - * @return Zero - fail, otherwise - Service UUID(0x1827 or 0x1828) - */ -u16_t provisioner_srv_uuid_recv(struct net_buf_simple *buf); - -/** - * @brief This function parses the service data part of the - * received connectable mesh provisioning advertising packets. - * - * @param[in] buf: Pointer to the buffer containing the remianing service data part - * @param[in] addr: Pointer to the received device address - * @param[in] uuid: Service UUID contained in the service UUID part - * - * @return None - */ -void provisioner_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr, u16_t uuid); +void provisioner_prov_adv_ind_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr); /** * @brief This function gets the bt_mesh_prov pointer. diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_proxy.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_proxy.c deleted file mode 100644 index 022994f38..000000000 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_proxy.c +++ /dev/null @@ -1,608 +0,0 @@ -// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include "sdkconfig.h" - -#include "mesh_bearer_adapt.h" -#include "mesh_trace.h" - -#include "net.h" -#include "beacon.h" -#include "foundation.h" -#include "provisioner_prov.h" -#include "provisioner_proxy.h" -#include "provisioner_beacon.h" - -#if CONFIG_BLE_MESH_PROVISIONER - -#define PDU_TYPE(data) (data[0] & BIT_MASK(6)) -#define PDU_SAR(data) (data[0] >> 6) - -#define SAR_COMPLETE 0x00 -#define SAR_FIRST 0x01 -#define SAR_CONT 0x02 -#define SAR_LAST 0x03 - -#define CFG_FILTER_SET 0x00 -#define CFG_FILTER_ADD 0x01 -#define CFG_FILTER_REMOVE 0x02 -#define CFG_FILTER_STATUS 0x03 - -#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) - -#define SERVER_BUF_SIZE 68 - -#define ID_TYPE_NET 0x00 -#define ID_TYPE_NODE 0x01 - -#define NODE_ID_LEN 19 -#define NET_ID_LEN 11 - -#define CLOSE_REASON_PROXY 0xFF - -static int conn_count; - -static struct bt_mesh_proxy_server { - struct bt_mesh_conn *conn; - /* Provisioner can use filter to double check the dst within mesh messages */ - u16_t filter[CONFIG_BLE_MESH_PROXY_FILTER_SIZE]; - enum __packed { - NONE, - WHITELIST, - BLACKLIST, - PROV, - } filter_type; - u8_t msg_type; - struct net_buf_simple buf; -} servers[BLE_MESH_MAX_CONN]; - -static u8_t server_buf_data[SERVER_BUF_SIZE * BLE_MESH_MAX_CONN]; - -static struct bt_mesh_proxy_server *find_server(struct bt_mesh_conn *conn) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(servers); i++) { - if (servers[i].conn == conn) { - return &servers[i]; - } - } - - return NULL; -} - -static int filter_status(struct bt_mesh_proxy_server *server, - struct net_buf_simple *buf) -{ - /* TODO: Deal with received proxy configuration status messages */ - return 0; -} - -#if 0 -static void send_filter_set(struct bt_mesh_proxy_server *server, - struct bt_mesh_net_rx *rx, - struct net_buf_simple *buf) -{ - /* TODO: Act as proxy client, send proxy configuration set messages */ -} - -static void send_filter_add(struct bt_mesh_proxy_server *server, - struct bt_mesh_net_rx *rx, - struct net_buf_simple *buf) -{ - /* TODO: Act as proxy client, send proxy configuration add messages */ -} - -static void send_filter_remove(struct bt_mesh_proxy_server *server, - struct bt_mesh_net_rx *rx, - struct net_buf_simple *buf) -{ - /* TODO: Act as proxy client, send proxy configuration remove messages */ -} -#endif - -static void proxy_cfg(struct bt_mesh_proxy_server *server) -{ - NET_BUF_SIMPLE_DEFINE(buf, 29); - struct bt_mesh_net_rx rx; - u8_t opcode; - int err; - - /** In order to deal with proxy configuration messages, provisioner should - * do sth. like create mesh network after each device is provisioned. - */ - err = bt_mesh_net_decode(&server->buf, BLE_MESH_NET_IF_PROXY_CFG, - &rx, &buf); - if (err) { - BT_ERR("%s, Failed to decode Proxy Configuration (err %d)", __func__, err); - return; - } - - /* Remove network headers */ - net_buf_simple_pull(&buf, BLE_MESH_NET_HDR_LEN); - - BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len)); - - if (buf.len < 1) { - BT_WARN("Too short proxy configuration PDU"); - return; - } - - opcode = net_buf_simple_pull_u8(&buf); - switch (opcode) { - case CFG_FILTER_STATUS: - filter_status(server, &buf); - break; - default: - BT_WARN("Unhandled configuration OpCode 0x%02x", opcode); - break; - } -} - -static void proxy_complete_pdu(struct bt_mesh_proxy_server *server) -{ - switch (server->msg_type) { -#if defined(CONFIG_BLE_MESH_GATT_PROXY) - case BLE_MESH_PROXY_NET_PDU: - BT_DBG("Mesh Network PDU"); - bt_mesh_net_recv(&server->buf, 0, BLE_MESH_NET_IF_PROXY); - break; - case BLE_MESH_PROXY_BEACON: - BT_DBG("Mesh Beacon PDU"); - provisioner_beacon_recv(&server->buf); - break; - case BLE_MESH_PROXY_CONFIG: - BT_DBG("Mesh Configuration PDU"); - proxy_cfg(server); - break; -#endif -#if defined(CONFIG_BLE_MESH_PB_GATT) - case BLE_MESH_PROXY_PROV: - BT_DBG("Mesh Provisioning PDU"); - provisioner_pb_gatt_recv(server->conn, &server->buf); - break; -#endif - default: - BT_WARN("Unhandled Message Type 0x%02x", server->msg_type); - break; - } - - net_buf_simple_reset(&server->buf); -} - -#define ATTR_IS_PROV(uuid) (uuid == BLE_MESH_UUID_MESH_PROV_VAL) - -static ssize_t proxy_recv(struct bt_mesh_conn *conn, - const struct bt_mesh_gatt_attr *attr, const void *buf, - u16_t len, u16_t offset, u8_t flags) -{ - struct bt_mesh_proxy_server *server = find_server(conn); - const u8_t *data = buf; - u16_t srvc_uuid = 0; - - if (!server) { - return -ENOTCONN; - } - - if (len < 1) { - BT_WARN("Too small Proxy PDU"); - return -EINVAL; - } - - srvc_uuid = bt_mesh_gattc_get_service_uuid(conn); - if (!srvc_uuid) { - BT_ERR("%s, No service uuid found", __func__); - return -ENOTCONN; - } - - if (ATTR_IS_PROV(srvc_uuid) != (PDU_TYPE(data) == BLE_MESH_PROXY_PROV)) { - BT_WARN("Proxy PDU type doesn't match GATT service uuid"); - return -EINVAL; - } - - if (len - 1 > net_buf_simple_tailroom(&server->buf)) { - BT_WARN("Too big proxy PDU"); - return -EINVAL; - } - - switch (PDU_SAR(data)) { - case SAR_COMPLETE: - if (server->buf.len) { - BT_WARN("Complete PDU while a pending incomplete one"); - return -EINVAL; - } - - server->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(&server->buf, data + 1, len - 1); - proxy_complete_pdu(server); - break; - - case SAR_FIRST: - if (server->buf.len) { - BT_WARN("First PDU while a pending incomplete one"); - return -EINVAL; - } - - server->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(&server->buf, data + 1, len - 1); - break; - - case SAR_CONT: - if (!server->buf.len) { - BT_WARN("Continuation with no prior data"); - return -EINVAL; - } - - if (server->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in continuation"); - return -EINVAL; - } - - net_buf_simple_add_mem(&server->buf, data + 1, len - 1); - break; - - case SAR_LAST: - if (!server->buf.len) { - BT_WARN("Last SAR PDU with no prior data"); - return -EINVAL; - } - - if (server->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in last SAR PDU"); - return -EINVAL; - } - - net_buf_simple_add_mem(&server->buf, data + 1, len - 1); - proxy_complete_pdu(server); - break; - } - - return len; -} - -static void proxy_prov_connected(const u8_t addr[6], struct bt_mesh_conn *conn, int id) -{ - struct bt_mesh_proxy_server *server = NULL; - - conn_count++; - - if (!servers[id].conn) { - server = &servers[id]; - } - - if (!server) { - BT_ERR("%s, No matching Proxy Client objects", __func__); - /** Disconnect current connection, clear part of prov_link - * information, like uuid, dev_addr, linking flag, etc. - */ - - return; - } - - server->conn = bt_mesh_conn_ref(conn); - server->filter_type = NONE; - memset(server->filter, 0, sizeof(server->filter)); - net_buf_simple_reset(&server->buf); - -#if defined(CONFIG_BLE_MESH_PB_GATT) - if (provisioner_set_prov_conn(addr, server->conn)) { - BT_ERR("%s, provisioner_set_prov_conn failed", __func__); - bt_mesh_gattc_disconnect(server->conn); - return; - } -#endif - - bt_mesh_gattc_exchange_mtu(id); -} - -static void proxy_prov_disconnected(struct bt_mesh_conn *conn, u8_t reason) -{ - struct bt_mesh_proxy_server *server = NULL; - int i; - - BT_DBG("conn %p, handle is %d, reason 0x%02x", conn, conn->handle, reason); - - if (conn_count) { - conn_count--; - } - - for (i = 0; i < ARRAY_SIZE(servers); i++) { - server = &servers[i]; - if (server->conn == conn) { - if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) && - server->filter_type == PROV) { - provisioner_pb_gatt_close(conn, reason); - } - server->conn = NULL; - break; - } - } -} - -#if defined(CONFIG_BLE_MESH_PB_GATT) -static ssize_t prov_write_ccc_descr(struct bt_mesh_conn *conn, u8_t *addr) -{ - struct bt_mesh_proxy_server *server; - - server = find_server(conn); - - if (!server) { - BT_ERR("%s, No Proxy Server found", __func__); - return -ENOTCONN; - } - - if (server->filter_type == NONE) { - server->filter_type = PROV; - return provisioner_pb_gatt_open(conn, addr); - } - - return -EINVAL; -} - -static ssize_t prov_notification(struct bt_mesh_conn *conn, u8_t *data, u16_t len) -{ - struct bt_mesh_proxy_server *server; - - server = find_server(conn); - - if (!server) { - BT_ERR("%s, No Proxy Server found", __func__); - return -ENOTCONN; - } - - if (server->filter_type == PROV) { - return proxy_recv(conn, NULL, data, len, 0, 0); - } - - return -EINVAL; -} - -int provisioner_pb_gatt_enable(void) -{ - int i; - - BT_DBG("%s", __func__); - - for (i = 0; i < ARRAY_SIZE(servers); i++) { - if (servers[i].conn) { - servers[i].filter_type = PROV; - } - } - - return 0; -} - -int provisioner_pb_gatt_disable(void) -{ - int i; - - BT_DBG("%s", __func__); - - for (i = 0; i < ARRAY_SIZE(servers); i++) { - struct bt_mesh_proxy_server *server = &servers[i]; - - if (server->conn && server->filter_type == PROV) { - bt_mesh_gattc_disconnect(server->conn); - server->filter_type = NONE; - } - } - - return 0; -} - -#endif /* CONFIG_BLE_MESH_PB_GATT */ - -#if defined(CONFIG_BLE_MESH_GATT_PROXY) -static ssize_t proxy_write_ccc_descr(struct bt_mesh_conn *conn) -{ - struct bt_mesh_proxy_server *server; - - server = find_server(conn); - - if (!server) { - BT_ERR("%s, No Proxy Server found", __func__); - return -ENOTCONN; - } - - if (server->filter_type == NONE) { - server->filter_type = WHITELIST; - return 0; - } - - return -EINVAL; -} - -static ssize_t proxy_notification(struct bt_mesh_conn *conn, u8_t *data, u16_t len) -{ - return proxy_recv(conn, NULL, data, len, 0, 0); -} - -/** Currently provisioner does't need bt_mesh_provisioner_proxy_enable() - * and bt_mesh_provisioner_proxy_disable() functions, and once they are - * used, provisioner can be enabled to parse node_id_adv and net_id_adv - * in order to support proxy client role. - * And if gatt_proxy is disabled, provisioner can stop dealing with - * these two kinds of connectable advertising packets. - */ -int bt_mesh_provisioner_proxy_enable(void) -{ - int i; - - BT_DBG("%s", __func__); - - for (i = 0; i < ARRAY_SIZE(servers); i++) { - if (servers[i].conn) { - servers[i].filter_type = WHITELIST; - } - } - - /** TODO: Once at leat one device has been provisioned, provisioner - * can be set to allow receiving and parsing node_id & net_id adv - * packets, and we may use a global flag to indicate this. - */ - - return 0; -} - -static void bt_mesh_proxy_gatt_proxy_disconnect(void) -{ - int i; - - BT_DBG("%s", __func__); - - for (i = 0; i < ARRAY_SIZE(servers); i++) { - struct bt_mesh_proxy_server *server = &servers[i]; - - if (server->conn && (server->filter_type == WHITELIST || - server->filter_type == BLACKLIST)) { - server->filter_type = NONE; - bt_mesh_gattc_disconnect(server->conn); - } - } -} - -int bt_mesh_provisioner_proxy_disable(void) -{ - BT_DBG("%s", __func__); - - /** TODO: Once this function is invoked, provisioner shall stop - * receiving and parsing node_id & net_id adv packets, and if - * proxy connection exists, we should disconnect it. - */ - - bt_mesh_proxy_gatt_proxy_disconnect(); - - return 0; -} - -#endif /* CONFIG_BLE_MESH_GATT_PROXY */ - -static int proxy_send(struct bt_mesh_conn *conn, const void *data, u16_t len) -{ - BT_DBG("%u bytes: %s", len, bt_hex(data, len)); - -#if defined(CONFIG_BLE_MESH_GATT_PROXY) || defined(CONFIG_BLE_MESH_PB_GATT) - return bt_mesh_gattc_write_no_rsp(conn, NULL, data, len); -#endif - - return 0; -} - -static int proxy_prov_segment_and_send(struct bt_mesh_conn *conn, u8_t type, - struct net_buf_simple *msg) -{ - u16_t mtu; - - if (conn == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return -EINVAL; - } - - BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len, - bt_hex(msg->data, msg->len)); - - mtu = bt_mesh_gattc_get_mtu_info(conn); - if (!mtu) { - BT_ERR("%s, Conn used to get mtu does not exist", __func__); - return -ENOTCONN; - } - - /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ - mtu -= 3; - if (mtu > msg->len) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); - return proxy_send(conn, msg->data, msg->len); - } - - net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - proxy_send(conn, msg->data, mtu); - net_buf_simple_pull(msg, mtu); - - while (msg->len) { - if (msg->len + 1 < mtu) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - proxy_send(conn, msg->data, msg->len); - break; - } - - net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - proxy_send(conn, msg->data, mtu); - net_buf_simple_pull(msg, mtu); - } - - return 0; -} - -int provisioner_proxy_send(struct bt_mesh_conn *conn, u8_t type, - struct net_buf_simple *msg) -{ - struct bt_mesh_proxy_server *server = find_server(conn); - - if (!server) { - BT_ERR("$%s, No Proxy Server found", __func__); - return -ENOTCONN; - } - - if ((server->filter_type == PROV) != (type == BLE_MESH_PROXY_PROV)) { - BT_ERR("%s, Invalid PDU type for Proxy Client", __func__); - return -EINVAL; - } - - return proxy_prov_segment_and_send(conn, type, msg); -} - -static struct bt_mesh_prov_conn_cb conn_callbacks = { - .connected = proxy_prov_connected, - .disconnected = proxy_prov_disconnected, -#if defined(CONFIG_BLE_MESH_PB_GATT) - .prov_write_descr = prov_write_ccc_descr, - .prov_notify = prov_notification, -#endif /* CONFIG_BLE_MESH_PB_GATT */ -#if defined(CONFIG_BLE_MESH_GATT_PROXY) - .proxy_write_descr = proxy_write_ccc_descr, - .proxy_notify = proxy_notification, -#endif /* CONFIG_BLE_MESH_GATT_PROXY */ -}; - -void provisioner_proxy_srv_data_recv(struct net_buf_simple *buf) -{ - /** TODO: Parse node_id_adv or net_id_adv pkts. Currently we - * don't support this function, and if realized later, proxy - * client need to check if there is server structure left - * before create connection with a server. - * check conn_count & CONFIG_BLE_MESH_PBG_SAME_TIME - */ -} - -int provisioner_proxy_init(void) -{ - int i; - - /* Initialize the server receive buffers */ - for (i = 0; i < ARRAY_SIZE(servers); i++) { - struct bt_mesh_proxy_server *server = &servers[i]; - - server->buf.size = SERVER_BUF_SIZE; - server->buf.__buf = server_buf_data + (i * SERVER_BUF_SIZE); - } - - bt_mesh_gattc_conn_cb_register(&conn_callbacks); - - return 0; -} - -#endif /* CONFIG_BLE_MESH_PROVISIONER */ diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_proxy.h b/components/bt/esp_ble_mesh/mesh_core/provisioner_proxy.h deleted file mode 100644 index 6a64167b3..000000000 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_proxy.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _PROVISIONER_PROXY_H_ -#define _PROVISIONER_PROXY_H_ - -#include "mesh_buf.h" - -#define BLE_MESH_PROXY_NET_PDU 0x00 -#define BLE_MESH_PROXY_BEACON 0x01 -#define BLE_MESH_PROXY_CONFIG 0x02 -#define BLE_MESH_PROXY_PROV 0x03 - -/** - * @brief This function is called to send proxy protocol messages. - * - * @param[in] conn: Pointer to bt_conn structure - * @param[in] type: Proxy protocol message type - * @param[in] msg: Pointer to the buffer contains sending message. - * - * @return Zero-success, other-fail - */ -int provisioner_proxy_send(struct bt_mesh_conn *conn, u8_t type, struct net_buf_simple *msg); - -/** - * @brief This function is called to parse received node identity and net - * id adv pkts and create connection if deceided to. - * - * @param[in] buf: Pointer to the buffer contains received message. - * - * @return None - */ -void provisioner_proxy_srv_data_recv(struct net_buf_simple *buf); - -/** - * @brief This function is called to initialize proxy provisioner structure - * and register proxy connection related callbacks. - * - * @return Zero-success, other-fail - */ -int provisioner_proxy_init(void); - -/** - * @brief This function is called to enable dealing with proxy provisioning - * messages. - * - * @return Zero-success, other-fail - */ -int provisioner_pb_gatt_enable(void); - -/** - * @brief This function is called to disable dealing with proxy provisioning - * messages and if proxy provisioning connections exist, the connections - * will be disconnected. - * - * @return Zero-success, other-fail - */ -int provisioner_pb_gatt_disable(void); - -/* The following APIs are for application use */ -/** - * @brief This function is called to enable receiving node identity and net - * id adv pkts. - * - * @return Zero-success, other-fail - */ -int bt_mesh_provisioner_proxy_enable(void); - -/** - * @brief This function is called to disable receiving node identity and net - * id adv pkts, and if proxy connections exist, these connections will - * be disconnected. - * - * @return Zero-success, other-fail - */ -int bt_mesh_provisioner_proxy_disable(void); - -#endif /* _PROVISIONER_PROXY_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/proxy_client.c b/components/bt/esp_ble_mesh/mesh_core/proxy_client.c new file mode 100644 index 000000000..ee0961e82 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_core/proxy_client.c @@ -0,0 +1,998 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "sdkconfig.h" + +#include "mesh.h" +#include "mesh_bearer_adapt.h" +#include "mesh_trace.h" +#include "mesh_common.h" + +#include "net.h" +#include "access.h" +#include "beacon.h" +#include "foundation.h" +#include "provisioner_prov.h" +#include "proxy_client.h" +#include "provisioner_beacon.h" +#include "provisioner_main.h" + +#define PDU_TYPE(data) (data[0] & BIT_MASK(6)) +#define PDU_SAR(data) (data[0] >> 6) + +#define PROXY_SAR_TIMEOUT K_SECONDS(20) + +#define SAR_COMPLETE 0x00 +#define SAR_FIRST 0x01 +#define SAR_CONT 0x02 +#define SAR_LAST 0x03 + +#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) + +#define SERVER_BUF_SIZE 68 + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT + +static struct bt_mesh_proxy_server { + struct bt_mesh_conn *conn; + enum __packed { + NONE, + PROV, + PROXY, + } conn_type; +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + u16_t net_idx; +#endif + u8_t msg_type; + struct k_delayed_work sar_timer; + struct net_buf_simple buf; +} servers[BLE_MESH_MAX_CONN]; + +static u8_t server_buf_data[SERVER_BUF_SIZE * BLE_MESH_MAX_CONN]; + +static struct bt_mesh_proxy_server *find_server(struct bt_mesh_conn *conn) +{ + u8_t i; + + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + if (servers[i].conn == conn) { + return &servers[i]; + } + } + + return NULL; +} + +static void proxy_sar_timeout(struct k_work *work) +{ + struct bt_mesh_proxy_server *server = NULL; + + BT_DBG("%s", __func__); + + server = CONTAINER_OF(work, struct bt_mesh_proxy_server, sar_timer.work); + if (!server || !server->conn) { + BT_ERR("%s, Invalid proxy server parameter", __func__); + return; + } + + net_buf_simple_reset(&server->buf); + bt_mesh_gattc_disconnect(server->conn); +} + +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT +/** + * The following callbacks are used to notify proper information + * to the application layer. + */ +static proxy_client_recv_adv_cb_t proxy_client_adv_recv_cb; +static proxy_client_connect_cb_t proxy_client_connect_cb; +static proxy_client_disconnect_cb_t proxy_client_disconnect_cb; +static proxy_client_recv_filter_status_cb_t proxy_client_filter_status_recv_cb; + +void bt_mesh_proxy_client_set_adv_recv_cb(proxy_client_recv_adv_cb_t cb) +{ + proxy_client_adv_recv_cb = cb; +} + +void bt_mesh_proxy_client_set_conn_cb(proxy_client_connect_cb_t cb) +{ + proxy_client_connect_cb = cb; +} + +void bt_mesh_proxy_client_set_disconn_cb(proxy_client_disconnect_cb_t cb) +{ + proxy_client_disconnect_cb = cb; +} + +void bt_mesh_proxy_client_set_filter_status_cb(proxy_client_recv_filter_status_cb_t cb) +{ + proxy_client_filter_status_recv_cb = cb; +} + +static void filter_status(struct bt_mesh_proxy_server *server, + struct bt_mesh_net_rx *rx, + struct net_buf_simple *buf) +{ + u8_t filter_type; + u16_t list_size; + + if (buf->len != 3) { + BT_ERR("%s, Invalid Proxy Filter Status length %d", __func__, buf->len); + return; + } + + filter_type = net_buf_simple_pull_u8(buf); + if (filter_type > 0x01) { + BT_ERR("%s, Invalid filter type 0x%02x", __func__, filter_type); + return; + } + + list_size = net_buf_simple_pull_be16(buf); + + BT_DBG("%s, filter_type 0x%02x list_size %d", __func__, filter_type, list_size); + + if (proxy_client_filter_status_recv_cb) { + proxy_client_filter_status_recv_cb(server - servers, rx->ctx.addr, server->net_idx, filter_type, list_size); + } + + return; +} + +static void proxy_cfg(struct bt_mesh_proxy_server *server) +{ + NET_BUF_SIMPLE_DEFINE(buf, 29); + struct bt_mesh_net_rx rx = {0}; + u8_t opcode; + int err; + + err = bt_mesh_net_decode(&server->buf, BLE_MESH_NET_IF_PROXY_CFG, + &rx, &buf); + if (err) { + BT_ERR("%s, Failed to decode Proxy Configuration (err %d)", __func__, err); + return; + } + + if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.addr)) { + BT_ERR("%s, Proxy Configuration from non-unicast addr 0x%04x", __func__, rx.ctx.addr); + return; + } + + /* Remove network headers */ + net_buf_simple_pull(&buf, BLE_MESH_NET_HDR_LEN); + + BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len)); + + if (buf.len < 3) { + BT_WARN("Too short proxy configuration PDU"); + return; + } + + opcode = net_buf_simple_pull_u8(&buf); + + switch (opcode) { + case BLE_MESH_PROXY_CFG_FILTER_STATUS: + filter_status(server, &rx, &buf); + break; + default: + BT_WARN("Unknown Proxy Configuration OpCode 0x%02x", opcode); + break; + } +} +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + +static void proxy_complete_pdu(struct bt_mesh_proxy_server *server) +{ + switch (server->msg_type) { +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + case BLE_MESH_PROXY_NET_PDU: + BT_DBG("Mesh Network PDU"); + bt_mesh_net_recv(&server->buf, 0, BLE_MESH_NET_IF_PROXY); + break; + case BLE_MESH_PROXY_BEACON: + BT_DBG("Mesh Beacon PDU"); + if (bt_mesh_is_provisioner_en()) { +#if CONFIG_BLE_MESH_PROVISIONER + provisioner_beacon_recv(&server->buf); +#endif + } else { +#if CONFIG_BLE_MESH_NODE + bt_mesh_beacon_recv(&server->buf); +#endif + } + break; + case BLE_MESH_PROXY_CONFIG: + BT_DBG("Mesh Configuration PDU"); + proxy_cfg(server); + break; +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + case BLE_MESH_PROXY_PROV: + BT_DBG("Mesh Provisioning PDU"); + provisioner_pb_gatt_recv(server->conn, &server->buf); + break; +#endif + default: + BT_WARN("Unhandled Message Type 0x%02x", server->msg_type); + break; + } + + net_buf_simple_reset(&server->buf); +} + +#define ATTR_IS_PROV(uuid) (uuid == BLE_MESH_UUID_MESH_PROV_VAL) + +static ssize_t proxy_recv(struct bt_mesh_conn *conn, + const struct bt_mesh_gatt_attr *attr, const void *buf, + u16_t len, u16_t offset, u8_t flags) +{ + struct bt_mesh_proxy_server *server = find_server(conn); + const u8_t *data = buf; + u16_t srvc_uuid; + + if (!server) { + BT_ERR("%s, No Proxy Server object found", __func__); + return -ENOTCONN; + } + + if (len < 1) { + BT_WARN("Too small Proxy PDU"); + return -EINVAL; + } + + srvc_uuid = bt_mesh_gattc_get_service_uuid(conn); + if (!srvc_uuid) { + BT_ERR("%s, No service uuid found", __func__); + return -ENOTCONN; + } + + if (ATTR_IS_PROV(srvc_uuid) != (PDU_TYPE(data) == BLE_MESH_PROXY_PROV)) { + BT_WARN("Proxy PDU type doesn't match GATT service uuid"); + return -EINVAL; + } + + if (len - 1 > net_buf_simple_tailroom(&server->buf)) { + BT_WARN("Too big proxy PDU"); + return -EINVAL; + } + + switch (PDU_SAR(data)) { + case SAR_COMPLETE: + if (server->buf.len) { + BT_WARN("Complete PDU while a pending incomplete one"); + return -EINVAL; + } + + server->msg_type = PDU_TYPE(data); + net_buf_simple_add_mem(&server->buf, data + 1, len - 1); + proxy_complete_pdu(server); + break; + + case SAR_FIRST: + if (server->buf.len) { + BT_WARN("First PDU while a pending incomplete one"); + return -EINVAL; + } + + k_delayed_work_submit(&server->sar_timer, PROXY_SAR_TIMEOUT); + server->msg_type = PDU_TYPE(data); + net_buf_simple_add_mem(&server->buf, data + 1, len - 1); + break; + + case SAR_CONT: + if (!server->buf.len) { + BT_WARN("Continuation with no prior data"); + return -EINVAL; + } + + if (server->msg_type != PDU_TYPE(data)) { + BT_WARN("Unexpected message type in continuation"); + return -EINVAL; + } + + k_delayed_work_submit(&server->sar_timer, PROXY_SAR_TIMEOUT); + net_buf_simple_add_mem(&server->buf, data + 1, len - 1); + break; + + case SAR_LAST: + if (!server->buf.len) { + BT_WARN("Last SAR PDU with no prior data"); + return -EINVAL; + } + + if (server->msg_type != PDU_TYPE(data)) { + BT_WARN("Unexpected message type in last SAR PDU"); + return -EINVAL; + } + + k_delayed_work_cancel(&server->sar_timer); + net_buf_simple_add_mem(&server->buf, data + 1, len - 1); + proxy_complete_pdu(server); + break; + } + + return len; +} + + +static int proxy_send(struct bt_mesh_conn *conn, const void *data, u16_t len) +{ + BT_DBG("%u bytes: %s", len, bt_hex(data, len)); + + return bt_mesh_gattc_write_no_rsp(conn, NULL, data, len); +} + +static int proxy_segment_and_send(struct bt_mesh_conn *conn, u8_t type, + struct net_buf_simple *msg) +{ + u16_t mtu; + int err; + + if (conn == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len, + bt_hex(msg->data, msg->len)); + + mtu = bt_mesh_gattc_get_mtu_info(conn); + if (!mtu) { + BT_ERR("%s, Conn used to get mtu does not exist", __func__); + return -ENOTCONN; + } + + /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ + mtu -= 3; + if (mtu > msg->len) { + net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); + return proxy_send(conn, msg->data, msg->len); + } + + net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); + err = proxy_send(conn, msg->data, mtu); + net_buf_simple_pull(msg, mtu); + + while (msg->len) { + if (msg->len + 1 < mtu) { + net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); + err = proxy_send(conn, msg->data, msg->len); + break; + } + + net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); + err = proxy_send(conn, msg->data, mtu); + net_buf_simple_pull(msg, mtu); + } + + return err; +} + +int bt_mesh_proxy_prov_client_send(struct bt_mesh_conn *conn, u8_t type, + struct net_buf_simple *msg) +{ + struct bt_mesh_proxy_server *server = find_server(conn); + + if (!server) { + BT_ERR("$%s, No Proxy Server object found", __func__); + return -ENOTCONN; + } + + if ((server->conn_type == PROV) != (type == BLE_MESH_PROXY_PROV)) { + BT_ERR("%s, Invalid PDU type for Proxy Server", __func__); + return -EINVAL; + } + + return proxy_segment_and_send(conn, type, msg); +} + +static void proxy_connected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int id) +{ + struct bt_mesh_proxy_server *server = NULL; + + if (!servers[id].conn) { + server = &servers[id]; + } + + if (!server) { + BT_ERR("%s, No free Proxy Server objects", __func__); + /** Disconnect current connection, clear part of prov_link + * information, like uuid, dev_addr, linking flag, etc. + */ + bt_mesh_gattc_disconnect(conn); + return; + } + + server->conn = bt_mesh_conn_ref(conn); + server->conn_type = NONE; + net_buf_simple_reset(&server->buf); + + bt_mesh_gattc_exchange_mtu(id); + return; +} + +static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, u8_t reason) +{ + struct bt_mesh_proxy_server *server = find_server(conn); + + BT_DBG("conn %p, handle is %d, reason 0x%02x", conn, conn->handle, reason); + + if (!server) { + BT_ERR("%s, No Proxy Server object found", __func__); + return; + } + +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + if (server->conn_type == PROV) { + provisioner_pb_gatt_close(conn, reason); + } +#endif + +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + if (server->conn_type == PROXY) { + if (proxy_client_disconnect_cb) { + proxy_client_disconnect_cb(addr, server - servers, server->net_idx, reason); + } + } +#endif + + k_delayed_work_cancel(&server->sar_timer); + server->conn = NULL; + server->conn_type = NONE; +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + server->net_idx = BLE_MESH_KEY_UNUSED; +#endif + + return; +} + +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT +static ssize_t prov_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) +{ + struct bt_mesh_proxy_server *server = find_server(conn); + + if (!server) { + BT_ERR("%s, No Proxy Server object found", __func__); + return -ENOTCONN; + } + + if (server->conn_type == NONE) { + server->conn_type = PROV; + + if (provisioner_set_prov_conn(addr->val, server->conn)) { + BT_ERR("%s, provisioner_set_prov_conn failed", __func__); + bt_mesh_gattc_disconnect(server->conn); + return -EIO; + } + return provisioner_pb_gatt_open(conn, addr->val); + } + + return -ENOMEM; +} + +static ssize_t prov_recv_ntf(struct bt_mesh_conn *conn, u8_t *data, u16_t len) +{ + struct bt_mesh_proxy_server *server = find_server(conn); + + if (!server) { + BT_ERR("%s, No Proxy Server object found", __func__); + return -ENOTCONN; + } + + if (server->conn_type == PROV) { + return proxy_recv(conn, NULL, data, len, 0, 0); + } + + return -EINVAL; +} + +int provisioner_pb_gatt_enable(void) +{ + u8_t i; + + BT_DBG("%s", __func__); + + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + if (servers[i].conn) { + servers[i].conn_type = PROV; + } + } + + return 0; +} + +int provisioner_pb_gatt_disable(void) +{ + u8_t i; + + BT_DBG("%s", __func__); + + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + struct bt_mesh_proxy_server *server = &servers[i]; + + if (server->conn && server->conn_type == PROV) { + bt_mesh_gattc_disconnect(server->conn); + server->conn_type = NONE; + } + } + + return 0; +} +#endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */ + +#if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) +static ssize_t proxy_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) +{ + struct bt_mesh_proxy_server *server = find_server(conn); + + if (!server) { + BT_ERR("%s, No Proxy Server object found", __func__); + return -ENOTCONN; + } + + if (server->conn_type == NONE) { + server->conn_type = PROXY; + + if (proxy_client_connect_cb) { + proxy_client_connect_cb(addr, server - servers, server->net_idx); + } + return 0; + } + + return -EINVAL; +} + +static ssize_t proxy_recv_ntf(struct bt_mesh_conn *conn, u8_t *data, u16_t len) +{ + struct bt_mesh_proxy_server *server = find_server(conn); + + if (!server) { + BT_ERR("%s, No Proxy Server object found", __func__); + return -ENOTCONN; + } + + if (server->conn_type == PROXY) { + return proxy_recv(conn, NULL, data, len, 0, 0); + } + + return -EINVAL; +} + +/** + * Currently proxy client does't need bt_mesh_proxy_client_enable() and + * bt_mesh_proxy_client_disable() functions, and once they are used, + * proxy client can be enabled to parse node_id_adv and net_id_adv in + * order to support proxy client role. + * And if gatt proxy is disabled, proxy client can stop handling these + * two kinds of connectable advertising packets. + */ +int bt_mesh_proxy_client_enable(void) +{ + u8_t i; + + BT_DBG("%s", __func__); + + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + if (servers[i].conn) { + servers[i].conn_type = PROXY; + } + } + + /** + * TODO: + * Once at leat one device has been provisioned, proxy client can be + * set to allow receiving and parsing node_id & net_id adv packets, + * and we may use a global flag to indicate this. + */ + + return 0; +} + +int bt_mesh_proxy_client_disable(void) +{ + u8_t i; + + BT_DBG("%s", __func__); + + /** + * TODO: + * Once this function is invoked, proxy client shall stop handling + * node_id & net_id adv packets, and if proxy connection exists, + * it should be disconnected. + */ + + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + struct bt_mesh_proxy_server *server = &servers[i]; + + if (server->conn && server->conn_type == PROXY) { + bt_mesh_gattc_disconnect(server->conn); + server->conn_type = NONE; + } + } + + return 0; +} +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + +static struct bt_mesh_prov_conn_cb conn_callbacks = { + .connected = proxy_connected, + .disconnected = proxy_disconnected, +#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT + .prov_write_descr = prov_write_ccc, + .prov_notify = prov_recv_ntf, +#endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */ +#if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) + .proxy_write_descr = proxy_write_ccc, + .proxy_notify = proxy_recv_ntf, +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ +}; + +#if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) +static struct bt_mesh_subnet *bt_mesh_is_net_id_exist(const u8_t net_id[8]) +{ + struct bt_mesh_subnet *sub = NULL; + size_t size, i; + + size = bt_mesh_rx_netkey_size(); + + for (i = 0U; i < size; i++) { + sub = bt_mesh_rx_netkey_get(i); + if (sub && !memcmp(sub->keys[sub->kr_flag].net_id, net_id, 8)) { + return sub; + } + } + + return NULL; +} + +void proxy_client_adv_ind_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr) +{ + bt_mesh_proxy_adv_ctx_t ctx = {0}; + u8_t type; + + /* Check if connection reaches the maximum limitation */ + if (bt_mesh_gattc_get_free_conn_count() == 0) { + BT_WARN("%s, max connections", __func__); + return; + } + + type = net_buf_simple_pull_u8(buf); + + switch (type) { + case BLE_MESH_PROXY_ADV_NET_ID: { + struct bt_mesh_subnet *sub = NULL; + sub = bt_mesh_is_net_id_exist(buf->data); + if (!sub) { + return; + } + + memcpy(ctx.net_id.net_id, buf->data, buf->len); + ctx.net_id.net_idx = sub->net_idx; + break; + } + case BLE_MESH_PROXY_ADV_NODE_ID: + /* Gets node identity information. + * hash = aes-ecb(identity key, 16 octets(padding + random + src)) mod 2^64, + * If Proxy Client wants to get src, it may encrypts multiple times and compare + * the hash value (8 octets) with the received one. + */ + return; + default: + BT_DBG("%s, Unknwon Mesh Proxy adv type 0x%02x", __func__, type); + return; + } + + if (proxy_client_adv_recv_cb) { + proxy_client_adv_recv_cb(addr, type, &ctx); + } +} + +int bt_mesh_proxy_client_connect(const u8_t addr[6], u8_t addr_type, u16_t net_idx) +{ + bt_mesh_addr_t remote_addr = {0}; + int result; + + if (!addr || addr_type > BLE_MESH_ADDR_RANDOM) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + memcpy(remote_addr.val, addr, BLE_MESH_ADDR_LEN); + remote_addr.type = addr_type; + + result = bt_mesh_gattc_conn_create(&remote_addr, BLE_MESH_UUID_MESH_PROXY_VAL); + if (result < 0) { + return result; + } + + /* Store corresponding net_idx which can be used for sending Proxy Configuration */ + servers[result].net_idx = net_idx; + return 0; +} + +int bt_mesh_proxy_client_disconnect(u8_t conn_handle) +{ + struct bt_mesh_conn *conn; + + if (conn_handle >= BLE_MESH_MAX_CONN) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + BT_DBG("conn_handle %d", conn_handle); + + conn = servers[conn_handle].conn; + if (!conn) { + BT_ERR("%s, Not connected, conn_handle %d", __func__, conn_handle); + return -ENOTCONN; + } + + bt_mesh_gattc_disconnect(conn); + return 0; +} + +bool bt_mesh_proxy_client_send(struct net_buf_simple *buf, u16_t dst) +{ + bool send = false; + int err; + u8_t i; + + BT_DBG("%u bytes to dst 0x%04x", buf->len, dst); + + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + struct bt_mesh_proxy_server *server = &servers[i]; + NET_BUF_SIMPLE_DEFINE(msg, 32); + + if (!server->conn || server->conn_type != PROXY) { + continue; + } + + /* Proxy PDU sending modifies the original buffer, + * so we need to make a copy. + */ + net_buf_simple_init(&msg, 1); + net_buf_simple_add_mem(&msg, buf->data, buf->len); + + err = bt_mesh_proxy_prov_client_send(server->conn, BLE_MESH_PROXY_NET_PDU, &msg); + if (err) { + BT_ERR("%s, Failed to send proxy net message (err %d)", __func__, err); + } else { + send = true; + } + } + + return send; +} + +static int beacon_send(struct bt_mesh_conn *conn, struct bt_mesh_subnet *sub) +{ + NET_BUF_SIMPLE_DEFINE(buf, 23); + + net_buf_simple_init(&buf, 1); + bt_mesh_beacon_create(sub, &buf); + + return bt_mesh_proxy_prov_client_send(conn, BLE_MESH_PROXY_BEACON, &buf); +} + +bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub) +{ + bool send = false; + int err; + u8_t i; + + /* NULL means we send Secure Network Beacon on all subnets */ + if (!sub) { + if (bt_mesh_is_provisioner_en()) { +#if CONFIG_BLE_MESH_PROVISIONER + for (i = 0U; i < ARRAY_SIZE(bt_mesh.p_sub); i++) { + if (bt_mesh.p_sub[i] && bt_mesh.p_sub[i]->net_idx != BLE_MESH_KEY_UNUSED) { + send = bt_mesh_proxy_client_beacon_send(bt_mesh.p_sub[i]); + } + } +#endif + } else { +#if CONFIG_BLE_MESH_NODE + for (i = 0U; i < ARRAY_SIZE(bt_mesh.sub); i++) { + if (bt_mesh.sub[i].net_idx != BLE_MESH_KEY_UNUSED) { + send = bt_mesh_proxy_client_beacon_send(&bt_mesh.sub[i]); + } + } +#endif + } + + return send; + } + + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + if (servers[i].conn && servers[i].conn_type == PROXY) { + err = beacon_send(servers[i].conn, sub); + if (err) { + BT_ERR("%s, Failed to send proxy beacon message (err %d)", __func__, err); + } else { + send = true; + } + } + } + + return send; +} + +static int send_proxy_cfg(struct bt_mesh_conn *conn, u16_t net_idx, struct bt_mesh_proxy_cfg_pdu *cfg) +{ + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BLE_MESH_KEY_UNUSED, /* CTL shall be set to 1 */ + .addr = BLE_MESH_ADDR_UNASSIGNED, /* DST shall be set to the unassigned address */ + .send_ttl = 0U, /* TTL shall be set to 0 */ + }; + struct bt_mesh_net_tx tx = { + .ctx = &ctx, + .src = bt_mesh_primary_addr(), + }; + struct net_buf_simple *buf = NULL; + u16_t alloc_len; + int err; + + if (bt_mesh_is_provisioner_en()) { +#if CONFIG_BLE_MESH_PROVISIONER + tx.sub = provisioner_subnet_get(net_idx); +#endif + } else { +#if CONFIG_BLE_MESH_NODE + tx.sub = bt_mesh_subnet_get(net_idx); +#endif + } + if (!tx.sub) { + BT_ERR("%s, Failed to find subnet", __func__); + return -EIO; + } + + switch (cfg->opcode) { + case BLE_MESH_PROXY_CFG_FILTER_SET: + if (cfg->set.filter_type > 0x01) { + BT_ERR("%s, Invalid filter type 0x%02x", __func__, cfg->set.filter_type); + return -EINVAL; + } + + alloc_len = sizeof(cfg->opcode) + sizeof(cfg->set.filter_type); + break; + case BLE_MESH_PROXY_CFG_FILTER_ADD: + if (cfg->add.addr == NULL || cfg->add.addr_num == 0) { + BT_ERR("%s, Add address list is NULL", __func__); + return -EINVAL; + } + + alloc_len = sizeof(cfg->opcode) + (cfg->add.addr_num << 1); + break; + case BLE_MESH_PROXY_CFG_FILTER_REMOVE: + if (cfg->remove.addr == NULL || cfg->remove.addr_num == 0) { + BT_ERR("%s, Remove address list is NULL", __func__); + return -EINVAL; + } + + alloc_len = sizeof(cfg->opcode) + (cfg->remove.addr_num << 1); + break; + default: + BT_ERR("%s, Unknown Proxy Configuration opcode 0x%02x", __func__, cfg->opcode); + return -EINVAL; + } + + /** + * For Proxy Configuration PDU: + * 1 octet Proxy PDU type + 9 octets network pdu header + Tranport PDU + 8 octets NetMIC + */ + buf = bt_mesh_alloc_buf(1 + BLE_MESH_NET_HDR_LEN + alloc_len + 8); + if (!buf) { + return -ENOMEM; + } + + net_buf_simple_reset(buf); + net_buf_simple_reserve(buf, 10); + + net_buf_simple_add_u8(buf, cfg->opcode); + switch (cfg->opcode) { + case BLE_MESH_PROXY_CFG_FILTER_SET: + net_buf_simple_add_u8(buf, cfg->set.filter_type); + break; + case BLE_MESH_PROXY_CFG_FILTER_ADD: + for (u16_t i = 0U; i < cfg->add.addr_num; i++) { + net_buf_simple_add_le16(buf, cfg->add.addr[i]); + } + break; + case BLE_MESH_PROXY_CFG_FILTER_REMOVE: + for (u16_t i = 0U; i < cfg->remove.addr_num; i++) { + net_buf_simple_add_le16(buf, cfg->remove.addr[i]); + } + break; + } + + BT_DBG("%s, len %u bytes: %s", __func__, buf->len, bt_hex(buf->data, buf->len)); + + err = bt_mesh_net_encode(&tx, buf, true); + if (err) { + BT_ERR("%s, Encoding Proxy message failed (err %d)", __func__, err); + bt_mesh_free_buf(buf); + return err; + } + + err = bt_mesh_proxy_prov_client_send(conn, BLE_MESH_PROXY_CONFIG, buf); + if (err) { + BT_ERR("%s, Failed to send proxy cfg message (err %d)", __func__, err); + } + + bt_mesh_free_buf(buf); + return err; +} + +int bt_mesh_proxy_client_send_cfg(u8_t conn_handle, u16_t net_idx, struct bt_mesh_proxy_cfg_pdu *pdu) +{ + struct bt_mesh_conn *conn; + + if (conn_handle >= BLE_MESH_MAX_CONN || !pdu || pdu->opcode > BLE_MESH_PROXY_CFG_FILTER_REMOVE) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + BT_DBG("conn_handle %d, net_idx 0x%04x", conn_handle, net_idx); + + conn = servers[conn_handle].conn; + if (!conn) { + BT_ERR("%s, Not connected, conn_handle %d", __func__, conn_handle); + return -ENOTCONN; + } + + /** + * Check if net_idx used to encrypt Proxy Configuration are the same + * with the one added when creating proxy connection. + */ + if (servers[conn_handle].net_idx != net_idx) { + BT_ERR("%s, NetKey Index 0x%04x mismatch, expect 0x%04x", + __func__, net_idx, servers[conn_handle].net_idx); + return -EIO; + } + + return send_proxy_cfg(conn, net_idx, pdu); +} +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + +int bt_mesh_proxy_prov_client_init(void) +{ + u8_t i; + + /* Initialize the server receive buffers */ + for (i = 0U; i < ARRAY_SIZE(servers); i++) { + struct bt_mesh_proxy_server *server = &servers[i]; + + k_delayed_work_init(&server->sar_timer, proxy_sar_timeout); + server->buf.size = SERVER_BUF_SIZE; + server->buf.__buf = server_buf_data + (i * SERVER_BUF_SIZE); +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + server->net_idx = BLE_MESH_KEY_UNUSED; +#endif + } + + bt_mesh_gattc_conn_cb_register(&conn_callbacks); + +#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN && CONFIG_BLE_MESH_GATT_PROXY_CLIENT + bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD, + BLE_MESH_EXCEP_INFO_MESH_PROXY_ADV, NULL); +#endif + + return 0; +} + +#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ diff --git a/components/bt/esp_ble_mesh/mesh_core/proxy_client.h b/components/bt/esp_ble_mesh/mesh_core/proxy_client.h new file mode 100644 index 000000000..59f974ef2 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_core/proxy_client.h @@ -0,0 +1,102 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _PROVISIONER_PROXY_H_ +#define _PROVISIONER_PROXY_H_ + +#include "mesh_buf.h" +#include "net.h" + +#define BLE_MESH_PROXY_ADV_NET_ID 0x00 +#define BLE_MESH_PROXY_ADV_NODE_ID 0x01 + +#define BLE_MESH_PROXY_NET_PDU 0x00 +#define BLE_MESH_PROXY_BEACON 0x01 +#define BLE_MESH_PROXY_CONFIG 0x02 +#define BLE_MESH_PROXY_PROV 0x03 + +#define BLE_MESH_PROXY_CFG_FILTER_SET 0x00 +#define BLE_MESH_PROXY_CFG_FILTER_ADD 0x01 +#define BLE_MESH_PROXY_CFG_FILTER_REMOVE 0x02 +#define BLE_MESH_PROXY_CFG_FILTER_STATUS 0x03 + +typedef union { + struct { + u8_t net_id[8]; + u16_t net_idx; + } net_id; + struct { + u16_t src; + } node_id; +} bt_mesh_proxy_adv_ctx_t; + +struct bt_mesh_proxy_net_pdu { + struct net_buf_simple *val; +}; + +struct bt_mesh_proxy_cfg_pdu { + u8_t opcode; + union { + struct cfg_filter_set { + u8_t filter_type; + } set; + struct cfg_addr_add { + u16_t *addr; + u16_t addr_num; + } add; + struct cfg_addr_remove { + u16_t *addr; + u16_t addr_num; + } remove; + }; +}; + +typedef struct { + u8_t type; + union { + struct bt_mesh_proxy_net_pdu net; + struct bt_mesh_proxy_cfg_pdu cfg; + }; +} bt_mesh_proxy_client_pdu_t; + +int bt_mesh_proxy_prov_client_send(struct bt_mesh_conn *conn, u8_t type, struct net_buf_simple *msg); + +int provisioner_pb_gatt_enable(void); +int provisioner_pb_gatt_disable(void); + +int bt_mesh_proxy_client_enable(void); +int bt_mesh_proxy_client_disable(void); + +typedef void (*proxy_client_recv_adv_cb_t)(const bt_mesh_addr_t *addr, u8_t type, bt_mesh_proxy_adv_ctx_t *ctx); +typedef void (*proxy_client_connect_cb_t)(const bt_mesh_addr_t *addr, u8_t conn_handle, u16_t net_idx); +typedef void (*proxy_client_disconnect_cb_t)(const bt_mesh_addr_t *addr, u8_t conn_handle, u16_t net_idx, u8_t reason); +typedef void (*proxy_client_recv_filter_status_cb_t)(u8_t conn_handle, u16_t src, u16_t net_idx, u8_t filter_type, u16_t list_size); + +void bt_mesh_proxy_client_set_adv_recv_cb(proxy_client_recv_adv_cb_t cb); +void bt_mesh_proxy_client_set_conn_cb(proxy_client_connect_cb_t cb); +void bt_mesh_proxy_client_set_disconn_cb(proxy_client_disconnect_cb_t cb); +void bt_mesh_proxy_client_set_filter_status_cb(proxy_client_recv_filter_status_cb_t cb); + +void proxy_client_adv_ind_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr); + +int bt_mesh_proxy_client_connect(const u8_t addr[6], u8_t addr_type, u16_t net_idx); +int bt_mesh_proxy_client_disconnect(u8_t conn_handle); + +bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub); +bool bt_mesh_proxy_client_send(struct net_buf_simple *buf, u16_t dst); +int bt_mesh_proxy_client_send_cfg(u8_t conn_handle, u16_t net_idx, struct bt_mesh_proxy_cfg_pdu *pdu); + +int bt_mesh_proxy_prov_client_init(void); + +#endif /* _PROVISIONER_PROXY_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/proxy.c b/components/bt/esp_ble_mesh/mesh_core/proxy_server.c similarity index 97% rename from components/bt/esp_ble_mesh/mesh_core/proxy.c rename to components/bt/esp_ble_mesh/mesh_core/proxy_server.c index 5f4ca8c65..ba2556d27 100644 --- a/components/bt/esp_ble_mesh/mesh_core/proxy.c +++ b/components/bt/esp_ble_mesh/mesh_core/proxy_server.c @@ -24,10 +24,14 @@ #include "beacon.h" #include "foundation.h" #include "access.h" -#include "proxy.h" +#include "proxy_server.h" #if CONFIG_BLE_MESH_NODE +/* Not support enabling Proxy Client and Proxy Server simultaneously */ +_Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)), + "Not support Proxy Server and Proxy Client simultaneously"); + #define PDU_TYPE(data) (data[0] & BIT_MASK(6)) #define PDU_SAR(data) (data[0] >> 6) @@ -67,7 +71,7 @@ static const struct bt_mesh_adv_param fast_adv_param = { static bool proxy_adv_enabled; -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) static void proxy_send_beacons(struct k_work *work); static u16_t proxy_ccc_val; #endif @@ -87,14 +91,14 @@ static struct bt_mesh_proxy_client { PROV, } filter_type; u8_t msg_type; -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) struct k_work send_beacons; #endif struct k_delayed_work sar_timer; struct net_buf_simple buf; } clients[BLE_MESH_MAX_CONN] = { [0 ... (BLE_MESH_MAX_CONN - 1)] = { -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) .send_beacons = _K_WORK_INITIALIZER(proxy_send_beacons), #endif }, @@ -158,7 +162,7 @@ static void proxy_sar_timeout(struct k_work *work) bt_mesh_gatts_disconnect(client->conn, 0x13); } -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) /* Next subnet in queue to be advertised */ static int next_idx; @@ -439,7 +443,7 @@ int bt_mesh_proxy_identity_enable(void) static void proxy_complete_pdu(struct bt_mesh_proxy_client *client) { switch (client->msg_type) { -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) case BLE_MESH_PROXY_NET_PDU: BT_DBG("Mesh Network PDU"); bt_mesh_net_recv(&client->buf, 0, BLE_MESH_NET_IF_PROXY); @@ -666,7 +670,7 @@ static ssize_t prov_ccc_read(struct bt_mesh_conn *conn, u16_t *value = attr->user_data; return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, value, - sizeof(*value)); + sizeof(*value)); } /* Mesh Provisioning Service Declaration */ @@ -761,7 +765,7 @@ int bt_mesh_proxy_prov_disable(bool disconnect) #endif /* CONFIG_BLE_MESH_PB_GATT */ -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) static ssize_t proxy_ccc_write(struct bt_mesh_conn *conn, const struct bt_mesh_gatt_attr *attr, const void *buf, u16_t len, @@ -801,7 +805,7 @@ static ssize_t proxy_ccc_read(struct bt_mesh_conn *conn, u16_t *value = attr->user_data; return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, value, - sizeof(*value)); + sizeof(*value)); } /* Mesh Proxy Service Declaration */ @@ -968,13 +972,13 @@ bool bt_mesh_proxy_relay(struct net_buf_simple *buf, u16_t dst) return relayed; } -#endif /* CONFIG_BLE_MESH_GATT_PROXY */ +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ static int proxy_send(struct bt_mesh_conn *conn, const void *data, u16_t len) { BT_DBG("%u bytes: %s", len, bt_hex(data, len)); -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) if (gatt_svc == MESH_GATT_PROXY) { return bt_mesh_gatts_notify(conn, &proxy_attrs[4], data, len); } @@ -1051,7 +1055,7 @@ static const struct bt_mesh_adv_data prov_ad[] = { }; #endif /* PB_GATT */ -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) #define ID_TYPE_NET 0x00 #define ID_TYPE_NODE 0x01 @@ -1360,7 +1364,7 @@ s32_t bt_mesh_proxy_adv_start(void) } #endif /* PB_GATT */ -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) if (bt_mesh_is_provisioned()) { return gatt_proxy_advertise(next_sub()); } diff --git a/components/bt/esp_ble_mesh/mesh_core/proxy.h b/components/bt/esp_ble_mesh/mesh_core/proxy_server.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/proxy.h rename to components/bt/esp_ble_mesh/mesh_core/proxy_server.h diff --git a/components/bt/esp_ble_mesh/mesh_core/settings.c b/components/bt/esp_ble_mesh/mesh_core/settings.c index 874ff7d77..8705b1c9a 100644 --- a/components/bt/esp_ble_mesh/mesh_core/settings.c +++ b/components/bt/esp_ble_mesh/mesh_core/settings.c @@ -27,7 +27,7 @@ #include "transport.h" #include "access.h" #include "foundation.h" -#include "proxy.h" +#include "proxy_server.h" #include "cfg_srv.h" #include "settings_nvs.h" @@ -656,7 +656,7 @@ static int model_set(bool vnd, const char *name) model = bt_mesh_model_get(vnd, elem_idx, model_idx); if (!model) { BT_ERR("%s, Failed to get %s model, elem_idx %u model_idx %u", - __func__, vnd ? "vnd" : "sig", elem_idx, model_idx); + __func__, vnd ? "vnd" : "sig", elem_idx, model_idx); err = -ENOENT; goto free; } @@ -743,7 +743,7 @@ static int subnet_init(struct bt_mesh_subnet *sub) } } - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY)) { + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED; } else { sub->node_id = BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED; @@ -1227,7 +1227,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *model, bool vnd) err = bt_mesh_add_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); if (err) { BT_ERR("%s, Failed to add 0x%04x to %s", __func__, model_key, - vnd ? "mesh/vnd" : "mesh/sig"); + vnd ? "mesh/vnd" : "mesh/sig"); } return; @@ -1257,7 +1257,7 @@ static void store_pending_mod_sub(struct bt_mesh_model *model, bool vnd) err = bt_mesh_add_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); if (err) { BT_ERR("%s, Failed to add 0x%04x to %s", __func__, model_key, - vnd ? "mesh/vnd" : "mesh/sig"); + vnd ? "mesh/vnd" : "mesh/sig"); } return; @@ -1301,7 +1301,7 @@ static void store_pending_mod_pub(struct bt_mesh_model *model, bool vnd) err = bt_mesh_add_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); if (err) { BT_ERR("%s, Failed to add 0x%04x to %s", __func__, model_key, - vnd ? "mesh/vnd" : "mesh/sig"); + vnd ? "mesh/vnd" : "mesh/sig"); } return; diff --git a/components/bt/esp_ble_mesh/mesh_core/settings/settings_nvs.c b/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c similarity index 99% rename from components/bt/esp_ble_mesh/mesh_core/settings/settings_nvs.c rename to components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c index 59e9ac114..96ef197ad 100644 --- a/components/bt/esp_ble_mesh/mesh_core/settings/settings_nvs.c +++ b/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c @@ -121,7 +121,7 @@ static int settings_save(nvs_handle handle, const char *key, const u8_t *val, si } if (err != ESP_OK) { BT_ERR("%s, Failed to %s %s data (err %d)", __func__, - val ? "set" : "erase", key, err); + val ? "set" : "erase", key, err); return -EIO; } diff --git a/components/bt/esp_ble_mesh/mesh_core/settings/settings_nvs.h b/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.h similarity index 100% rename from components/bt/esp_ble_mesh/mesh_core/settings/settings_nvs.h rename to components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.h diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.c b/components/bt/esp_ble_mesh/mesh_core/transport.c index 9b3606a98..614a3518d 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.c +++ b/components/bt/esp_ble_mesh/mesh_core/transport.c @@ -40,7 +40,7 @@ * count. */ _Static_assert(CONFIG_BLE_MESH_ADV_BUF_COUNT >= (CONFIG_BLE_MESH_TX_SEG_MAX + 3), - "Too small BLE Mesh adv buffer count"); + "Too small BLE Mesh adv buffer count"); #define AID_MASK ((u8_t)(BIT_MASK(6))) @@ -140,31 +140,31 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, net_buf_add_mem(buf, sdu->data, sdu->len); if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { - if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, - tx->src, tx->ctx->addr, - NULL, 1)) { - if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - BT_ERR("Not enough space in Friend Queue"); + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, + tx->src, tx->ctx->addr, + NULL, 1)) { + if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + BT_ERR("Not enough space in Friend Queue"); + net_buf_unref(buf); + return -ENOBUFS; + } else { + BT_WARN("No space in Friend Queue"); + goto send; + } + } + + if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE, + NULL, 1, &buf->b) && + BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + /* PDUs for a specific Friend should only go + * out through the Friend Queue. + */ net_buf_unref(buf); - return -ENOBUFS; - } else { - BT_WARN("No space in Friend Queue"); - goto send; + send_cb_finalize(cb, cb_data); + return 0; } } - - if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE, - NULL, 1, &buf->b) && - BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* PDUs for a specific Friend should only go - * out through the Friend Queue. - */ - net_buf_unref(buf); - send_cb_finalize(cb, cb_data); - return 0; - } - } } send: @@ -380,12 +380,12 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, BT_DBG("SeqZero 0x%04x", seq_zero); if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && - !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src, - tx->dst, &tx->seq_auth, - tx->seg_n + 1) && - BLE_MESH_ADDR_IS_UNICAST(tx->dst)) { + !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src, + tx->dst, &tx->seq_auth, + tx->seg_n + 1) && + BLE_MESH_ADDR_IS_UNICAST(tx->dst)) { BT_ERR("Not enough space in Friend Queue for %u segments", - tx->seg_n + 1); + tx->seg_n + 1); seg_tx_reset(tx); return -ENOBUFS; } @@ -428,10 +428,10 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, } if (bt_mesh_friend_enqueue_tx(net_tx, type, - &tx->seq_auth, - tx->seg_n + 1, - &seg->b) && - BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) { + &tx->seq_auth, + tx->seg_n + 1, + &seg->b) && + BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) { /* PDUs for a specific Friend should only go * out through the Friend Queue. */ @@ -466,10 +466,10 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, } if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && - bt_mesh_lpn_established()) { - bt_mesh_lpn_poll(); - } + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + bt_mesh_lpn_established()) { + bt_mesh_lpn_poll(); + } } return 0; @@ -760,7 +760,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr, BLE_MESH_NET_IVI_RX(rx)); if (err) { BT_DBG("Unable to decrypt with AppKey 0x%03x", - key->app_idx); + key->app_idx); continue; } @@ -927,45 +927,45 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr, } if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { - switch (ctl_op) { - case TRANS_CTL_OP_FRIEND_POLL: - return bt_mesh_friend_poll(rx, buf); - case TRANS_CTL_OP_FRIEND_REQ: - return bt_mesh_friend_req(rx, buf); - case TRANS_CTL_OP_FRIEND_CLEAR: - return bt_mesh_friend_clear(rx, buf); - case TRANS_CTL_OP_FRIEND_CLEAR_CFM: - return bt_mesh_friend_clear_cfm(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_ADD: - return bt_mesh_friend_sub_add(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_REM: - return bt_mesh_friend_sub_rem(rx, buf); + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { + switch (ctl_op) { + case TRANS_CTL_OP_FRIEND_POLL: + return bt_mesh_friend_poll(rx, buf); + case TRANS_CTL_OP_FRIEND_REQ: + return bt_mesh_friend_req(rx, buf); + case TRANS_CTL_OP_FRIEND_CLEAR: + return bt_mesh_friend_clear(rx, buf); + case TRANS_CTL_OP_FRIEND_CLEAR_CFM: + return bt_mesh_friend_clear_cfm(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_ADD: + return bt_mesh_friend_sub_add(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_REM: + return bt_mesh_friend_sub_rem(rx, buf); + } } - } #if defined(CONFIG_BLE_MESH_LOW_POWER) - if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) { - return bt_mesh_lpn_friend_offer(rx, buf); - } - - if (rx->ctx.addr == bt_mesh.lpn.frnd) { - if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) { - return bt_mesh_lpn_friend_clear_cfm(rx, buf); + if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) { + return bt_mesh_lpn_friend_offer(rx, buf); } - if (!rx->friend_cred) { - BT_WARN("Message from friend with wrong credentials"); - return -EINVAL; - } + if (rx->ctx.addr == bt_mesh.lpn.frnd) { + if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) { + return bt_mesh_lpn_friend_clear_cfm(rx, buf); + } - switch (ctl_op) { - case TRANS_CTL_OP_FRIEND_UPDATE: - return bt_mesh_lpn_friend_update(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_CFM: - return bt_mesh_lpn_friend_sub_cfm(rx, buf); + if (!rx->friend_cred) { + BT_WARN("Message from friend with wrong credentials"); + return -EINVAL; + } + + switch (ctl_op) { + case TRANS_CTL_OP_FRIEND_UPDATE: + return bt_mesh_lpn_friend_update(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_CFM: + return bt_mesh_lpn_friend_sub_cfm(rx, buf); + } } - } #endif /* CONFIG_BLE_MESH_LOW_POWER */ } @@ -1056,7 +1056,7 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data, if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE, seq_auth, 1, &buf->b) && - BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { /* PDUs for a specific Friend should only go * out through the Friend Queue. */ @@ -1281,7 +1281,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, if (is_replay(net_rx, &rpl)) { BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", - net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq); + net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq); return -EINVAL; } @@ -1375,11 +1375,11 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, * case this message is destined to an LPN of ours. */ if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && - net_rx->friend_match && !net_rx->local_match && - !bt_mesh_friend_queue_has_space(net_rx->sub->net_idx, - net_rx->ctx.addr, - net_rx->ctx.recv_dst, seq_auth, - *seg_count)) { + net_rx->friend_match && !net_rx->local_match && + !bt_mesh_friend_queue_has_space(net_rx->sub->net_idx, + net_rx->ctx.addr, + net_rx->ctx.recv_dst, seq_auth, + *seg_count)) { BT_ERR("No space in Friend Queue for %u segments", *seg_count); send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, seq_auth, 0, @@ -1504,12 +1504,12 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) * be encrypted using the Friend Credentials. */ if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && - bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV && - (!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) { - BT_WARN("Ignoring unexpected message in Low Power mode"); - return -EAGAIN; - } + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV && + (!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) { + BT_WARN("Ignoring unexpected message in Low Power mode"); + return -EAGAIN; + } } /* Save the app-level state so the buffer can later be placed in @@ -1545,7 +1545,7 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && (bt_mesh_lpn_timer() || - (bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) { + (bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) { bt_mesh_lpn_msg_received(rx); } } @@ -1556,10 +1556,10 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) { if (seq_auth == TRANS_SEQ_AUTH_NVAL) { bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL, - seg_count, buf); + seg_count, buf); } else { bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth, - seg_count, buf); + seg_count, buf); } } } @@ -1666,5 +1666,5 @@ void bt_mesh_heartbeat_send(void) BT_DBG("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat); bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb), - NULL, NULL, NULL); + NULL, NULL, NULL); } diff --git a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c index 7c2ac19b3..bd7231ead 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c @@ -26,15 +26,32 @@ #include "mesh.h" #include "client_common.h" +static bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, u16_t tx_dst) +{ + if (sys_slist_is_empty(list)) { + return NULL; + } + + sys_snode_t *cur = NULL; bt_mesh_client_node_t *node = NULL; + for (cur = sys_slist_peek_head(list); + cur != NULL; cur = sys_slist_peek_next(cur)) { + node = (bt_mesh_client_node_t *)cur; + if (node->ctx.addr == tx_dst) { + return node; + } + } + + return NULL; +} + bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg( - struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf, bool need_pub) + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf, bool need_pub) { bt_mesh_client_internal_data_t *data = NULL; bt_mesh_client_user_data_t *cli = NULL; bt_mesh_client_node_t *node = NULL; - u32_t rsp; if (!model || !ctx || !buf) { BT_ERR("%s, Invalid parameter", __func__); @@ -47,16 +64,14 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg( return NULL; } - rsp = ctx->recv_op; - /** If the received message address is not a unicast address, * the address may be a group/virtual address, and we push * this message to the application layer. */ if (!BLE_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) { - BT_DBG("Unexpected status message 0x%x", rsp); + BT_DBG("Unexpected status message 0x%x", ctx->recv_op); if (cli->publish_status && need_pub) { - cli->publish_status(rsp, model, ctx, buf); + cli->publish_status(ctx->recv_op, model, ctx, buf); } return NULL; } @@ -73,17 +88,17 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg( } if ((node = bt_mesh_client_pick_node(&data->queue, ctx->addr)) == NULL) { - BT_DBG("Unexpected status message 0x%x", rsp); + BT_DBG("Unexpected status message 0x%x", ctx->recv_op); if (cli->publish_status && need_pub) { - cli->publish_status(rsp, model, ctx, buf); + cli->publish_status(ctx->recv_op, model, ctx, buf); } return NULL; } - if (node->op_pending != rsp) { - BT_DBG("Unexpected status message 0x%x", rsp); + if (node->op_pending != ctx->recv_op) { + BT_DBG("Unexpected status message 0x%x", ctx->recv_op); if (cli->publish_status && need_pub) { - cli->publish_status(rsp, model, ctx, buf); + cli->publish_status(ctx->recv_op, model, ctx, buf); } return NULL; } @@ -91,26 +106,7 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg( return node; } -bool bt_mesh_client_find_opcode_in_list(sys_slist_t *list, u32_t opcode) -{ - if (sys_slist_is_empty(list)) { - return false; - } - - sys_snode_t *cur = NULL; bt_mesh_client_node_t *node = NULL; - for (cur = sys_slist_peek_head(list); - cur != NULL; cur = sys_slist_peek_next(cur)) { - node = (bt_mesh_client_node_t *)cur; - if (node->op_pending == opcode) { - return true; - } - return NULL; - } - - return node; -} - -bool bt_mesh_client_check_node_in_list(sys_slist_t *list, u16_t tx_dst) +static bool bt_mesh_client_check_node_in_list(sys_slist_t *list, u16_t tx_dst) { if (sys_slist_is_empty(list)) { return false; @@ -128,24 +124,6 @@ bool bt_mesh_client_check_node_in_list(sys_slist_t *list, u16_t tx_dst) return false; } -bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, u16_t tx_dst) -{ - if (sys_slist_is_empty(list)) { - return NULL; - } - - sys_snode_t *cur = NULL; bt_mesh_client_node_t *node = NULL; - for (cur = sys_slist_peek_head(list); - cur != NULL; cur = sys_slist_peek_next(cur)) { - node = (bt_mesh_client_node_t *)cur; - if (node->ctx.addr == tx_dst) { - return node; - } - } - - return NULL; -} - static u32_t bt_mesh_client_get_status_op(const bt_mesh_client_op_pair_t *op_pair, int size, u32_t opcode) { diff --git a/components/bt/esp_ble_mesh/mesh_models/client/generic_client.c b/components/bt/esp_ble_mesh/mesh_models/client/generic_client.c index fd8986797..48b540b41 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/generic_client.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/generic_client.c @@ -157,7 +157,7 @@ static void timeout_handler(struct k_work *work) node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work); if (node) { bt_mesh_generic_client_cb_evt_to_btc(node->opcode, - BTC_BLE_MESH_EVT_GENERIC_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); + BTC_BLE_MESH_EVT_GENERIC_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); } diff --git a/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h b/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h index 4cf2e890b..74eb366ca 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h +++ b/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef _MODEL_COMMON_H_ -#define _MODEL_COMMON_H_ +#ifndef _CLIENT_COMMON_H_ +#define _CLIENT_COMMON_H_ #include "mesh_access.h" @@ -94,15 +94,9 @@ int bt_mesh_client_init(struct bt_mesh_model *model); * @return 0 on success, or (negative) error code on failure. */ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg( - struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf, bool need_pub); - -bool bt_mesh_client_find_opcode_in_list(sys_slist_t *list, u32_t opcode); - -bool bt_mesh_client_check_node_in_list(sys_slist_t *list, uint16_t tx_dst); - -bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, u16_t tx_dst); + struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf, bool need_pub); int bt_mesh_client_send_msg(struct bt_mesh_model *model, u32_t opcode, @@ -136,5 +130,5 @@ typedef struct { */ int bt_mesh_set_client_model_role(bt_mesh_role_param_t *common); -#endif /* _MODEL_COMMON_H_ */ +#endif /* _CLIENT_COMMON_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/client/lighting_client.c b/components/bt/esp_ble_mesh/mesh_models/client/lighting_client.c index a73f91a36..78b80d7b0 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/lighting_client.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/lighting_client.c @@ -166,7 +166,7 @@ static void timeout_handler(struct k_work *work) node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work); if (node) { bt_mesh_lighting_client_cb_evt_to_btc(node->opcode, - BTC_BLE_MESH_EVT_LIGHTING_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); + BTC_BLE_MESH_EVT_LIGHTING_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); } diff --git a/components/bt/esp_ble_mesh/mesh_models/client/sensor_client.c b/components/bt/esp_ble_mesh/mesh_models/client/sensor_client.c index e3eda759a..7b93aecfb 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/sensor_client.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/sensor_client.c @@ -95,7 +95,7 @@ static void timeout_handler(struct k_work *work) node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work); if (node) { bt_mesh_sensor_client_cb_evt_to_btc(node->opcode, - BTC_BLE_MESH_EVT_SENSOR_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); + BTC_BLE_MESH_EVT_SENSOR_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); } diff --git a/components/bt/esp_ble_mesh/mesh_models/client/time_scene_client.c b/components/bt/esp_ble_mesh/mesh_models/client/time_scene_client.c index 3b05be51b..878ef3da3 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/time_scene_client.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/time_scene_client.c @@ -111,7 +111,7 @@ static void timeout_handler(struct k_work *work) node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work); if (node) { bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode, - BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); + BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0); // Don't forget to release the node at the end. bt_mesh_client_free_node(node); } diff --git a/components/bt/esp_ble_mesh/mesh_models/server/device_property.c b/components/bt/esp_ble_mesh/mesh_models/server/device_property.c new file mode 100644 index 000000000..523f1bcd4 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/device_property.c @@ -0,0 +1,150 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "mesh_types.h" + +#include "server_common.h" +#include "device_property.h" + +static struct bt_mesh_dev_prop { + u16_t prop_id; + u8_t len; +} device_properties [] = { + { BLE_MESH_INVALID_DEVICE_PROPERTY_ID, 0xFF }, + { BLE_MESH_AVERAGE_AMBIENT_TEMPERATURE_IN_A_PERIOD_OF_DAY, 0x03 }, + { BLE_MESH_AVERAGE_INPUT_CURRENT, 0x03 }, + { BLE_MESH_AVERAGE_INPUT_VOLTAGE, 0x03 }, + { BLE_MESH_AVERAGE_OUTPUT_CURRENT, 0x03 }, + { BLE_MESH_AVERAGE_OUTPUT_VOLTAGE, 0x03 }, + { BLE_MESH_CENTER_BEAM_INTENSITY_AT_FULL_POWER, 0x02 }, + { BLE_MESH_CHROMATICITY_TOLERANCE, 0x01 }, + { BLE_MESH_COLOR_RENDERING_INDEX_R9, 0x01 }, + { BLE_MESH_COLOR_RENDERING_INDEX_RA, 0x01 }, + { BLE_MESH_DEVICE_APPEARANCE, 0x02 }, + { BLE_MESH_DEVICE_COUNTRY_OF_ORIGIN, 0x02 }, + { BLE_MESH_DEVICE_DATE_OF_MANUFACTURE, 0x04 }, + { BLE_MESH_DEVICE_ENERGY_USE_SINCE_TURN_ON, 0x04 }, + { BLE_MESH_DEVICE_FIRMWARE_REVISION, 0x08 }, + { BLE_MESH_DEVICE_GLOBAL_TRADE_ITEM_NUMBER, 0x08 }, + { BLE_MESH_DEVICE_HARDWARE_REVISION, 0x16 }, + { BLE_MESH_DEVICE_MANUFACTURER_NAME, 0x36 }, + { BLE_MESH_DEVICE_MODEL_NUMBER, 0x24 }, + { BLE_MESH_DEVICE_OPERATING_TEMPERATURE_RANGE_SPECIFICATION, 0x04 }, + { BLE_MESH_DEVICE_OPERATING_TEMPERATURE_STATISTICAL_VALUES, 0x09 }, + { BLE_MESH_DEVICE_OVER_TEMPERATURE_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_DEVICE_POWER_RANGE_SPECIFICATION, 0x12 }, + { BLE_MESH_DEVICE_RUNTIME_SINCE_TURN_ON, 0x04 }, + { BLE_MESH_DEVICE_RUNTIME_WARRANTY, 0x04 }, + { BLE_MESH_DEVICE_SERIAL_NUMBER, 0x16 }, + { BLE_MESH_DEVICE_SOFTWARE_REVISION, 0x08 }, + { BLE_MESH_DEVICE_UNDER_TEMPERATURE_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_INDOOR_AMBIENT_TEMPERATURE_STATISTICAL_VALUES, 0x05 }, + { BLE_MESH_INITIAL_CIE_1931_CHROMATICITY_COORDINATES, 0x04 }, + { BLE_MESH_INITIAL_CORRELATED_COLOR_TEMPERATURE, 0x02 }, + { BLE_MESH_INITIAL_LUMINOUS_FLUX, 0x02 }, + { BLE_MESH_INITIAL_PLANCKIAN_DISTANCE, 0x02 }, + { BLE_MESH_INPUT_CURRENT_RANGE_SPECIFICATION, 0x06 }, + { BLE_MESH_INPUT_CURRENT_STATISTICS, 0x09 }, + { BLE_MESH_INPUT_OVER_CURRENT_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_INPUT_OVER_RIPPLE_VOLTAGE_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_INPUT_OVER_VOLTAGE_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_INPUT_UNDER_CURRENT_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_INPUT_UNDER_VOLTAGE_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_INPUT_VOLTAGE_RANGE_SPECIFICATION, 0x06 }, + { BLE_MESH_INPUT_VOLTAGE_RIPPLE_SPECIFICATION, 0x01 }, + { BLE_MESH_INPUT_VOLTAGE_STATISTICS, 0x09 }, + { BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_ON, 0x04 }, + { BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_PROLONG, 0x04 }, + { BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_STANDBY, 0x04 }, + { BLE_MESH_LIGHT_CONTROL_LIGHTNESS_ON, 0x02 }, + { BLE_MESH_LIGHT_CONTROL_LIGHTNESS_PROLONG, 0x02 }, + { BLE_MESH_LIGHT_CONTROL_LIGHTNESS_STANDBY, 0x02 }, + { BLE_MESH_LIGHT_CONTROL_REGULATOR_ACCURACY, 0x01 }, + { BLE_MESH_LIGHT_CONTROL_REGULATOR_KID, 0x04 }, + { BLE_MESH_LIGHT_CONTROL_REGULATOR_KIU, 0x04 }, + { BLE_MESH_LIGHT_CONTROL_REGULATOR_KPD, 0x04 }, + { BLE_MESH_LIGHT_CONTROL_REGULATOR_KPU, 0x04 }, + { BLE_MESH_LIGHT_CONTROL_TIME_FADE, 0x03 }, + { BLE_MESH_LIGHT_CONTROL_TIME_FADE_ON, 0x03 }, + { BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_AUTO, 0x03 }, + { BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_MANUAL, 0x03 }, + { BLE_MESH_LIGHT_CONTROL_TIME_OCCUPANCY_DELAY, 0x03 }, + { BLE_MESH_LIGHT_CONTROL_TIME_PROLONG, 0x03 }, + { BLE_MESH_LIGHT_CONTROL_TIME_RUN_ON, 0x03 }, + { BLE_MESH_LUMEN_MAINTENANCE_FACTOR, 0x01 }, + { BLE_MESH_LUMINOUS_EFFICACY, 0x02 }, + { BLE_MESH_LUMINOUS_ENERGY_SINCE_TURN_ON, 0x04 }, + { BLE_MESH_LUMINOUS_EXPOSURE, 0x04 }, + { BLE_MESH_LUMINOUS_FLUX_RANGE, 0x04 }, + { BLE_MESH_MOTION_SENSED, 0x01 }, + { BLE_MESH_MOTION_THRESHOLD, 0x01 }, + { BLE_MESH_OPEN_CIRCUIT_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_OUTDOOR_STATISTICAL_VALUES, 0x05 }, + { BLE_MESH_OUTPUT_CURRENT_RANGE, 0x04 }, + { BLE_MESH_OUTPUT_CURRENT_STATISTICS, 0x09 }, + { BLE_MESH_OUTPUT_RIPPLE_VOLTAGE_SPECIFICATION, 0x01 }, + { BLE_MESH_OUTPUT_VOLTAGE_RANGE, 0x06 }, + { BLE_MESH_OUTPUT_VOLTAGE_STATISTICS, 0x09 }, + { BLE_MESH_OVER_OUTPUT_RIPPLE_VOLTAGE_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_PEOPLE_COUNT, 0x02 }, + { BLE_MESH_PRESENCE_DETECTED, 0x01 }, + { BLE_MESH_PRESENT_AMBIENT_LIGHT_LEVEL, 0x04 }, + { BLE_MESH_PRESENT_AMBIENT_TEMPERATURE, 0x01 }, + { BLE_MESH_PRESENT_CIE_1931_CHROMATICITY, 0x04 }, + { BLE_MESH_PRESENT_CORRELATED_COLOR_TEMPERATURE, 0x02 }, + { BLE_MESH_PRESENT_DEVICE_INPUT_POWER, 0x04 }, + { BLE_MESH_PRESENT_DEVICE_OPERATING_EFFICIENCY, 0x01 }, + { BLE_MESH_PRESENT_DEVICE_OPERATING_TEMPERATURE, 0x02 }, + { BLE_MESH_PRESENT_ILLUMINANCE, 0x04 }, + { BLE_MESH_PRESENT_INDOOR_AMBIENT_TEMPERATURE, 0x01 }, + { BLE_MESH_PRESENT_INPUT_CURRENT, 0x02 }, + { BLE_MESH_PRESENT_INPUT_RIPPLE_VOLTAGE, 0x01 }, + { BLE_MESH_PRESENT_INPUT_VOLTAGE, 0x02 }, + { BLE_MESH_PRESENT_LUMINOUS_FLUX, 0x02 }, + { BLE_MESH_PRESENT_OUTDOOR_AMBIENT_TEMPERATURE, 0x01 }, + { BLE_MESH_PRESENT_OUTPUT_CURRENT, 0x02 }, + { BLE_MESH_PRESENT_OUTPUT_VOLTAGE, 0x02 }, + { BLE_MESH_PRESENT_PLANCKIAN_DISTANCE, 0x02 }, + { BLE_MESH_PRESENT_RELATIVE_OUTPUT_RIPPLE_VOLTAGE, 0x01 }, + { BLE_MESH_RELATIVE_DEVICE_ENERGY_USE_IN_A_PERIOD_OF_DAY, 0x06 }, + { BLE_MESH_RELATIVE_DEVICE_RUNTIME_IN_A_GENERIC_LEVEL_RANGE, 0x05 }, + { BLE_MESH_RELATIVE_EXPOSURE_TIME_IN_AN_ILLUMINANCE_RANGE, 0x09 }, + { BLE_MESH_RELATIVE_RUNTIME_IN_A_CORRELATED_COLOR_TEMPERATURE_RANGE, 0x04 }, + { BLE_MESH_RELATIVE_RUNTIME_IN_A_DEVICE_OPERATING_TEMPERATURE_RANGE, 0x05 }, + { BLE_MESH_RELATIVE_RUNTIME_IN_AN_INPUT_CURRENT_RANGE, 0x05 }, + { BLE_MESH_RELATIVE_RUNTIME_IN_AN_INPUT_VOLTAGE_RANGE, 0x05 }, + { BLE_MESH_SHORT_CIRCUIT_EVENT_STATISTICS, 0x06 }, + { BLE_MESH_TIME_SINCE_MOTION_SENSED, 0x02 }, + { BLE_MESH_TIME_SINCE_PRESENCE_DETECTED, 0x02 }, + { BLE_MESH_TOTAL_DEVICE_ENERGY_USE, 0x04 }, + { BLE_MESH_TOTAL_DEVICE_OFF_ON_CYCLES, 0x04 }, + { BLE_MESH_TOTAL_DEVICE_POWER_ON_CYCLES, 0x04 }, + { BLE_MESH_TOTAL_DEVICE_POWER_ON_TIME, 0x04 }, + { BLE_MESH_TOTAL_DEVICE_RUNTIME, 0x04 }, + { BLE_MESH_TOTAL_LIGHT_EXPOSURE_TIME, 0x04 }, + { BLE_MESH_TOTAL_LUMINOUS_ENERGY, 0x04 }, +}; + +u8_t bt_mesh_get_dev_prop_len(u16_t prop_id) +{ + if (prop_id > BLE_MESH_TOTAL_LUMINOUS_ENERGY) { + BT_ERR("%s, Unknown Device Property ID 0x%04x", __func__, prop_id); + return UINT8_MAX; + } + + return device_properties[prop_id].len; +} diff --git a/components/bt/esp_ble_mesh/mesh_models/server/generic_server.c b/components/bt/esp_ble_mesh/mesh_models/server/generic_server.c new file mode 100644 index 000000000..4bc4bbf65 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/generic_server.c @@ -0,0 +1,2633 @@ +/* Bluetooth: Mesh Generic Server Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "osi/mutex.h" + +#include "mesh_types.h" +#include "mesh_kernel.h" +#include "mesh_trace.h" +#include "mesh_common.h" +#include "mesh.h" +#include "access.h" +#include "model_opcode.h" +#include "transport.h" + +#include "server_common.h" +#include "state_binding.h" +#include "state_transition.h" +#include "device_property.h" + +#include "btc_ble_mesh_generic_model.h" + +static osi_mutex_t generic_server_mutex; + +static void bt_mesh_generic_server_mutex_new(void) +{ + if (!generic_server_mutex) { + osi_mutex_new(&generic_server_mutex); + __ASSERT(generic_server_mutex, "%s, fail", __func__); + } +} + +void bt_mesh_generic_server_lock(void) +{ + osi_mutex_lock(&generic_server_mutex, OSI_MUTEX_MAX_TIMEOUT); +} + +void bt_mesh_generic_server_unlock(void) +{ + osi_mutex_unlock(&generic_server_mutex); +} + +/* message handlers (Start) */ + +/* Generic OnOff Server message handlers */ +static void send_gen_onoff_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish) +{ + struct bt_mesh_gen_onoff_srv *srv = model->user_data; + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 3; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS); + net_buf_simple_add_u8(msg, srv->state.onoff); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_u8(msg, srv->state.target_onoff); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_onoff_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_onoff_srv *srv = model->user_data; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + send_gen_onoff_status(model, ctx, false); + return; +} + +void gen_onoff_publish(struct bt_mesh_model *model) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + send_gen_onoff_status(model, NULL, true); + return; +} + +static void gen_onoff_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_onoff_srv *srv = model->user_data; + u8_t tid, onoff, trans_time, delay; + bool optional; + s64_t now; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + onoff = net_buf_simple_pull_u8(buf); + if (onoff > BLE_MESH_STATE_ON) { + BT_ERR("%s, Invalid OnOff value 0x%02x", __func__, onoff); + return; + } + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .onoff_set.op_en = optional, + .onoff_set.onoff = onoff, + .onoff_set.tid = tid, + .onoff_set.trans_time = trans_time, + .onoff_set.delay = delay, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) { + send_gen_onoff_status(model, ctx, false); + } + send_gen_onoff_status(model, NULL, true); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_generic_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state.target_onoff = onoff; + + if (srv->state.target_onoff != srv->state.onoff) { + generic_onoff_tt_values(srv, trans_time, delay); + } else { + bt_mesh_gen_server_state_change_t change = { + .gen_onoff_set.onoff = srv->state.onoff, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) { + send_gen_onoff_status(model, ctx, false); + } + send_gen_onoff_status(model, NULL, true); + + bt_mesh_generic_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state.onoff = srv->state.target_onoff; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) { + send_gen_onoff_status(model, ctx, false); + } + send_gen_onoff_status(model, NULL, true); + + bt_mesh_generic_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +/* Generic Level Server message handlers */ +static void send_gen_level_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish) +{ + struct bt_mesh_gen_level_srv *srv = model->user_data; + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 5; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS); + net_buf_simple_add_le16(msg, srv->state.level); + if (srv->transition.counter) { + if (srv->state.move_start) { + if (srv->state.positive) { + net_buf_simple_add_le16(msg, INT16_MAX); + } else { /* 0 should not be possible */ + net_buf_simple_add_le16(msg, INT16_MIN); + } + net_buf_simple_add_u8(msg, BLE_MESH_UNKNOWN_REMAIN_TIME); + } else { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_le16(msg, srv->state.target_level); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_level_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_level_srv *srv = model->user_data; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + send_gen_level_status(model, ctx, false); + return; +} + +void gen_level_publish(struct bt_mesh_model *model) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + send_gen_level_status(model, NULL, true); + return; +} + +static void gen_level_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_level_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + bool optional; + s16_t level; + s64_t now; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + level = (s16_t) net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .level_set.op_en = optional, + .level_set.level = level, + .level_set.tid = tid, + .level_set.trans_time = trans_time, + .level_set.delay = delay, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LEVEL_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_generic_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state.target_level = level; + + /** + * If the target state is equal to the current state, the transition + * shall not be started and is considered complete. + */ + if (srv->state.target_level != srv->state.level) { + generic_level_tt_values(srv, trans_time, delay); + } else { + bt_mesh_gen_server_state_change_t change = { + .gen_level_set.level = srv->state.level, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LEVEL_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + + bt_mesh_generic_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state.level = srv->state.target_level; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LEVEL_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + + bt_mesh_generic_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void gen_delta_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_level_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + s32_t tmp32, delta; + bool optional; + s64_t now; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + delta = (s32_t)net_buf_simple_pull_le32(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .delta_set.op_en = optional, + .delta_set.delta_level = delta, + .delta_set.tid = tid, + .delta_set.trans_time = trans_time, + .delta_set.delay = delay, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + /** + * A number of Generic Delta Set and Generic Delta Set Unacknowledged + * messages with the same transaction identifier set in the TID field + * may be sent. + * + * A new transaction starts when the TID field value in the received + * message is different from the TID field value in the previously + * received message that was using the same source and destination + * addresses or from the most recently received message with the same + * TID field value that was received 6 or more seconds earlier. + */ + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (srv->state.last_delta == delta) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DELTA_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + /* In this condition, no event will be callback to application layer */ + return; + } + + tmp32 = srv->state.last_level + delta; + } else { + /* Starts a new transaction */ + srv->state.last_level = srv->state.level; + tmp32 = srv->state.level + delta; + } + + bt_mesh_generic_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state.last_delta = delta; + if (tmp32 < INT16_MIN) { + tmp32 = INT16_MIN; + } else if (tmp32 > INT16_MAX) { + tmp32 = INT16_MAX; + } + srv->state.target_level = tmp32; + + /** + * If the target state is equal to the current state, the transition + * shall not be started and is considered complete. + */ + if (srv->state.target_level != srv->state.level) { + generic_level_tt_values(srv, trans_time, delay); + } else { + bt_mesh_gen_server_state_change_t change = { + .gen_delta_set.level = srv->state.level, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DELTA_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + + bt_mesh_generic_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state.level = srv->state.target_level; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DELTA_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + + bt_mesh_generic_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void gen_move_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_level_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + bool optional; + s16_t delta; + s32_t tmp32; + s64_t now; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + delta = (s16_t) net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .move_set.op_en = optional, + .move_set.delta_level = delta, + .move_set.tid = tid, + .move_set.trans_time = trans_time, + .move_set.delay = delay, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MOVE_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_generic_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state.last_delta = delta; + + tmp32 = srv->state.level + delta; + if (tmp32 < INT16_MIN) { + tmp32 = INT16_MIN; + } else if (tmp32 > INT16_MAX) { + tmp32 = INT16_MAX; + } + srv->state.target_level = tmp32; + + /** + * If the target state is equal to the current state, the transition + * shall not be started and is considered complete. + */ + if (srv->state.target_level != srv->state.level) { + generic_level_tt_values(srv, trans_time, delay); + } else { + bt_mesh_gen_server_state_change_t change = { + .gen_move_set.level = srv->state.level, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MOVE_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + srv->state.move_start = false; + + bt_mesh_generic_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + if (delta) { + srv->state.move_start = true; + srv->state.positive = (delta > 0) ? true : false; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MOVE_SET) { + send_gen_level_status(model, ctx, false); + } + send_gen_level_status(model, NULL, true); + + bt_mesh_generic_server_unlock(); + + /** + * If (trans_time == 0) OR (delta == 0) + * 1. If the resulting Transition Time is equal to 0 or is undefined, + * the Generic Move Set command will not initiate any Generic Level + * state change. + * 2. When a Generic Level Server receives the message with a value of + * the Delta Level field equal to 0, it shall stop changing the + * Generic Level state. (if delta == 0, srv->state.target_level will + * equal to srv->state.level) + */ + if (srv->transition.counter == 0U) { + srv->state.move_start = false; + bt_mesh_gen_server_state_change_t change = { + .gen_move_set.level = srv->state.level, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + return; + } + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +/* Generic Default Transition Time Server message handlers */ +static void send_gen_def_trans_time_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish) +{ + struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data; + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 1; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_STATUS); + net_buf_simple_add_u8(msg, srv->state.trans_time); + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_def_trans_time_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + send_gen_def_trans_time_status(model, ctx, false); + return; +} + +static void gen_def_trans_time_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data; + u8_t trans_time; + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + trans_time = net_buf_simple_pull_u8(buf); + if ((trans_time & 0x3F) == 0x3F) { + BT_WARN("%s, Invalid Transaction Number of Steps 0x3F", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .def_trans_time_set.trans_time = trans_time, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (srv->state.trans_time != trans_time) { + srv->state.trans_time = trans_time; + } + + bt_mesh_gen_server_state_change_t change = { + .gen_def_trans_time_set.trans_time = trans_time, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET) { + send_gen_def_trans_time_status(model, ctx, false); + } + send_gen_def_trans_time_status(model, NULL, true); + + return; +} + +/* Generic Power OnOff Server message handlers */ +static void send_gen_onpowerup_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 1; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ONPOWERUP_STATUS); + switch (model->id) { + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV: { + struct bt_mesh_gen_power_onoff_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->onpowerup); + break; + } + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV: { + struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->onpowerup); + break; + } + default: + BT_ERR("%s, Invalid Generic Power OnOff Server 0x%04x", __func__, model->id); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_onpowerup_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_power_onoff_srv *srv = model->user_data; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + send_gen_onpowerup_status(model, ctx, false); + return; +} + +/* Generic Power OnOff Setup Server message handlers */ +void gen_onpowerup_publish(struct bt_mesh_model *model) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV: { + struct bt_mesh_gen_power_onoff_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Generic Power OnOff Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV: { + struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Generic Power OnOff Setup Server state", __func__); + return; + } + break; + } + default: + BT_ERR("%s, Invalid Generic Power OnOff Server 0x%04x", __func__, model->id); + return; + } + + send_gen_onpowerup_status(model, NULL, true); + return; +} + +static void gen_onpowerup_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data; + u8_t onpowerup; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + onpowerup = net_buf_simple_pull_u8(buf); + if (onpowerup > BLE_MESH_STATE_RESTORE) { + BT_WARN("%s, Invalid OnPowerUp value 0x%02x", __func__, onpowerup); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .onpowerup_set.onpowerup = onpowerup, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (srv->state->onpowerup != onpowerup) { + srv->state->onpowerup = onpowerup; + } + + bt_mesh_gen_server_state_change_t change = { + .gen_onpowerup_set.onpowerup = onpowerup, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET) { + send_gen_onpowerup_status(model, ctx, false); + } + send_gen_onpowerup_status(model, NULL, true); + + return; +} + +/* Generic Power Level Server message handlers */ +static void send_gen_power_level_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 5; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS: + case BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS: { + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + if (opcode == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS) { + net_buf_simple_add_le16(msg, srv->state->power_actual); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_le16(msg, srv->state->target_power_actual); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + } else if (opcode == BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS) { + net_buf_simple_add_le16(msg, srv->state->power_last); + } + break; + } + case BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS: + if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV) { + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->power_default); + } else if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV) { + struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->power_default); + } + break; + case BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS: + if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV) { + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->power_range_min); + net_buf_simple_add_le16(msg, srv->state->power_range_max); + } else if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV) { + struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->power_range_min); + net_buf_simple_add_le16(msg, srv->state->power_range_max); + } + break; + default: + BT_WARN("%s, Unknown Generic Power status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_power_level_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + u16_t opcode; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET: + opcode = BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS; + break; + case BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET: + opcode = BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS; + break; + case BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET: + opcode = BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS; + break; + case BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET: + opcode = BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS; + break; + default: + BT_WARN("%s, Unknown Generic Power Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_gen_power_level_status(model, ctx, false, opcode); + return; +} + +void gen_power_level_publish(struct bt_mesh_model *model, u16_t opcode) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV: { + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Generic Power Level Server state", __func__); + return; + } + break; + } + case ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV: { + struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Generic Power Level Setup Server state", __func__); + return; + } + break; + } + default: + BT_ERR("%s, Invalid Generic Power Level Server 0x%04x", __func__, model->id); + return; + } + + send_gen_power_level_status(model, NULL, true, opcode); + return; +} + +static void gen_power_level_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + bool optional; + u16_t power; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + power = net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .power_level_set.op_en = optional, + .power_level_set.power = power, + .power_level_set.tid = tid, + .power_level_set.trans_time = trans_time, + .power_level_set.delay = delay, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET) { + send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + } + send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_generic_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + if (power) { + if (srv->state->power_range_min && power < srv->state->power_range_min) { + power = srv->state->power_range_min; + } else if (srv->state->power_range_max && power > srv->state->power_range_max) { + power = srv->state->power_range_max; + } + } + srv->state->target_power_actual = power; + + /* If the target state is equal to the current state, the transition + * shall not be started and is considered complete. + */ + if (srv->state->target_power_actual != srv->state->power_actual) { + generic_power_level_tt_values(srv, trans_time, delay); + } else { + bt_mesh_gen_server_state_change_t change = { + .gen_power_level_set.power = srv->state->power_actual, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET) { + send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + } + send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + + bt_mesh_generic_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->power_actual = srv->state->target_power_actual; + /* Whenever the Generic Power Actual state is changed to a non-zero value + * as a result of a non-transactional message or a completed sequence of + * transactional messages, the value of the Generic Power Last state shall + * be set to the value of the Generic Power Actual state. + */ + if (srv->state->power_actual) { + srv->state->power_last = srv->state->power_actual; + } + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET) { + send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + } + send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + + bt_mesh_generic_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +/* Generic Power Level Setup Server message handlers */ +static void gen_power_default_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data; + u16_t power; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + power = net_buf_simple_pull_le16(buf); + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .power_default_set.power = power, /* Just callback the actual recived value */ + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + /** + * Value 0x0000 has a special meaning defined: use the value of the + * Generic Power Last state as the default value. + */ + if (power == 0x0000) { + power = srv->state->power_last; + } + + if (srv->state->power_default != power) { + srv->state->power_default = power; + } + + bt_mesh_gen_server_state_change_t change = { + .gen_power_default_set.power = power, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET) { + send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS); + } + send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS); + + return; +} + +static void gen_power_range_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data; + u16_t range_min, range_max; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + range_min = net_buf_simple_pull_le16(buf); + range_max = net_buf_simple_pull_le16(buf); + + if (range_min > range_max) { + BT_ERR("%s, Range Min 0x%04x is greater than Range Max 0x%04x", + __func__, range_min, range_max); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .power_range_set.range_min = range_min, + .power_range_set.range_max = range_max, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (range_min == 0x0000) { + srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MIN; + } else if (range_max == 0x0000) { + srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MAX; + } else { + srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS; + } + + if (range_min && srv->state->power_range_min != range_min) { + srv->state->power_range_min = range_min; + } + + if (range_max && srv->state->power_range_max != range_max) { + srv->state->power_range_max = range_max; + } + + bt_mesh_gen_server_state_change_t change = { + .gen_power_range_set.range_min = srv->state->power_range_min, + .gen_power_range_set.range_max = srv->state->power_range_max, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET) { + send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS); + } + send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS); + + return; +} + +/* Generic Battery Server message handlers */ +static void gen_battery_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_battery_srv *srv = model->user_data; + NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + BLE_MESH_SERVER_TRANS_MIC_SIZE); + + if (srv == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_GEN_BATTERY_STATUS); + net_buf_simple_add_le32(&msg, srv->state.time_to_discharge << 8 | srv->state.battery_level); + net_buf_simple_add_le32(&msg, srv->state.battery_flags << 24 | srv->state.time_to_charge); + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL)); + return; +} + +/* Generic Location Server message handlers */ +static void send_gen_location_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 1 + 10; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS: + if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SRV) { + struct bt_mesh_gen_location_srv *srv = model->user_data; + net_buf_simple_add_le32(msg, srv->state->global_latitude); + net_buf_simple_add_le32(msg, srv->state->global_longitude); + net_buf_simple_add_le16(msg, srv->state->global_altitude); + } else if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV) { + struct bt_mesh_gen_location_setup_srv *srv = model->user_data; + net_buf_simple_add_le32(msg, srv->state->global_latitude); + net_buf_simple_add_le32(msg, srv->state->global_longitude); + net_buf_simple_add_le16(msg, srv->state->global_altitude); + } + break; + case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS: + if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SRV) { + struct bt_mesh_gen_location_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->local_north); + net_buf_simple_add_le16(msg, srv->state->local_east); + net_buf_simple_add_le16(msg, srv->state->local_altitude); + net_buf_simple_add_u8(msg, srv->state->floor_number); + net_buf_simple_add_le16(msg, srv->state->uncertainty); + } else if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV) { + struct bt_mesh_gen_location_setup_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->local_north); + net_buf_simple_add_le16(msg, srv->state->local_east); + net_buf_simple_add_le16(msg, srv->state->local_altitude); + net_buf_simple_add_u8(msg, srv->state->floor_number); + net_buf_simple_add_le16(msg, srv->state->uncertainty); + } + break; + default: + BT_WARN("%s, Unknown Generic Location status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_location_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_location_srv *srv = model->user_data; + u16_t opcode; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET: + opcode = BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS; + break; + case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET: + opcode = BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS; + break; + default: + BT_WARN("%s, Unknown Generic Location Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_gen_location_status(model, ctx, false, opcode); + return; +} + +/* Generic Location Setup Server message handlers */ +static void gen_location_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_location_setup_srv *srv = model->user_data; + u16_t opcode; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET: + case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK: { + opcode = BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS; + s32_t latitude = net_buf_simple_pull_le32(buf); + s32_t longitude = net_buf_simple_pull_le32(buf); + s16_t altitude = net_buf_simple_pull_le16(buf); + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .loc_global_set.latitude = latitude, + .loc_global_set.longitude = longitude, + .loc_global_set.altitude = altitude, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (latitude != 0x80000000) { + srv->state->global_latitude = latitude; + } + if (longitude != 0x80000000) { + srv->state->global_longitude = longitude; + } + if (altitude != 0x7FFF) { + srv->state->global_altitude = altitude; + } + + bt_mesh_gen_server_state_change_t change = { + .gen_loc_global_set.latitude = srv->state->global_latitude, + .gen_loc_global_set.longitude = srv->state->global_longitude, + .gen_loc_global_set.altitude = srv->state->global_altitude, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + break; + } + case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET: + case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK: { + opcode = BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS; + u16_t north = net_buf_simple_pull_le16(buf); + u16_t east = net_buf_simple_pull_le16(buf); + u16_t altitude = net_buf_simple_pull_le16(buf); + u8_t floor = net_buf_simple_pull_u8(buf); + u16_t uncertainty = net_buf_simple_pull_le16(buf); + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .loc_local_set.north = north, + .loc_local_set.east = east, + .loc_local_set.altitude = altitude, + .loc_local_set.floor_number = floor, + .loc_local_set.uncertainty = uncertainty, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (north != 0x8000) { + srv->state->local_north = north; + } + if (east != 0x8000) { + srv->state->local_east = east; + } + if (altitude != 0x7FFF) { + srv->state->local_altitude = altitude; + } + if (floor != 0xFF) { + srv->state->floor_number = floor; + } + srv->state->uncertainty = uncertainty; + + bt_mesh_gen_server_state_change_t change = { + .gen_loc_local_set.north = srv->state->local_north, + .gen_loc_local_set.east = srv->state->local_east, + .gen_loc_local_set.altitude = srv->state->local_altitude, + .gen_loc_local_set.floor_number = srv->state->floor_number, + .gen_loc_local_set.uncertainty = srv->state->uncertainty, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + break; + } + default: + BT_WARN("%s, Unknown Generic Location Set opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET || + ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET) { + send_gen_location_status(model, ctx, false, opcode); + } + send_gen_location_status(model, NULL, true, opcode); + + return; +} + +/* Generic User Property Server message handlers */ +struct bt_mesh_generic_property *gen_get_user_property(struct bt_mesh_model *model, + u16_t property_id) +{ + struct bt_mesh_gen_user_prop_srv *srv = model->user_data; + u8_t i; + + for (i = 0U; i < srv->property_count; i++) { + if (srv->properties[i].id == property_id) { + return &srv->properties[i]; + } + } + + return NULL; +} + +static void send_gen_user_prop_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t property_id, bool publish) +{ + struct bt_mesh_generic_property *property = NULL; + struct net_buf_simple *msg = NULL; + u16_t length; + + if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) { + BT_ERR("%s, Invalid User Property ID 0x%04x", __func__, property_id); + return; + } + + property = gen_get_user_property(model, property_id); + if (property == NULL) { + BT_WARN("%s, User property 0x%04x not exist", __func__, property_id); + length = sizeof(property_id); + } else { + length = sizeof(property->id) + sizeof(property->user_access) + property->val->len; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, 1 + length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_STATUS); + if (property == NULL) { + net_buf_simple_add_le16(msg, property_id); + } else { + net_buf_simple_add_le16(msg, property->id); + net_buf_simple_add_u8(msg, property->user_access); + if ((ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET && + property->user_access != USER_ACCESS_PROHIBIT && + property->user_access != USER_ACCESS_WRITE) || + ((ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET || + ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK) && + property->user_access != USER_ACCESS_PROHIBIT && + property->user_access != USER_ACCESS_READ)) { + net_buf_simple_add_mem(msg, property->val->data, property->val->len); + } + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_user_prop_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_user_prop_srv *srv = model->user_data; + + if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + /** + * Also we can use __packed for esp_ble_mesh_gen_user_property_get_t, + * and directly callback with buf->data & buf->len. + */ + bt_mesh_gen_server_recv_get_msg_t get = {0}; + const u8_t *param = NULL; + size_t len = 0; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET) { + get.user_property_get.id = net_buf_simple_pull_le16(buf); + param = (const u8_t *)&get; + len = sizeof(get); + } + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, param, len); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET: { + struct net_buf_simple *msg = NULL; + u8_t i; + msg = bt_mesh_alloc_buf(1 + srv->property_count * 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS); + for (i = 0U; i < srv->property_count; i++) { + if (srv->properties[i].admin_access != ADMIN_NOT_USER_PROP && + srv->properties[i].manu_access != MANU_NOT_USER_PROP) { + net_buf_simple_add_le16(msg, srv->properties[i].id); + } + } + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; + } + case BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET: { + u16_t property_id = net_buf_simple_pull_le16(buf); + send_gen_user_prop_status(model, ctx, property_id, false); + return; + } + default: + BT_WARN("%s, Unknown Generic User Property Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } +} + +static void gen_user_prop_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_user_prop_srv *srv = model->user_data; + struct bt_mesh_generic_property *property = NULL; + u16_t property_id; + u8_t expect_len; + + if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + property_id = net_buf_simple_pull_le16(buf); + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .user_property_set.id = property_id, + .user_property_set.value = buf, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + property = gen_get_user_property(model, property_id); + if (property == NULL || property->user_access == USER_ACCESS_PROHIBIT || + property->user_access == USER_ACCESS_READ) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET) { + send_gen_user_prop_status(model, ctx, property_id, false); + } + send_gen_user_prop_status(model, ctx, property_id, true); + return; + } + + /* For BLE Mesh Model BQB test: + * PTS will send Generic User Property Set/Set Unack messages with + * invalid device property value length, these messages need to be + * ignored, otherwise the test case will fail. + */ + expect_len = bt_mesh_get_dev_prop_len(property_id); + if (buf->len != expect_len) { + BT_ERR("%s, Invalid User Property length, ID 0x%04x, expect %d, actual %d", + __func__, property_id, expect_len, buf->len); + return; + } + + net_buf_simple_reset(property->val); + net_buf_simple_add_mem(property->val, buf->data, MIN(buf->len, property->val->size)); + + bt_mesh_gen_server_state_change_t change = { + .gen_user_prop_set.id = property_id, + .gen_user_prop_set.value = property->val, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET) { + send_gen_user_prop_status(model, ctx, property_id, false); + } + send_gen_user_prop_status(model, ctx, property_id, true); + + return; +} + +/* Generic Admin Property Server message handlers */ +struct bt_mesh_generic_property *gen_get_admin_property(struct bt_mesh_model *model, + u16_t property_id) +{ + struct bt_mesh_gen_admin_prop_srv *srv = model->user_data; + u8_t i; + + for (i = 0U; i < srv->property_count; i++) { + if (srv->properties[i].id == property_id) { + return &srv->properties[i]; + } + } + + return NULL; +} + +static void send_gen_admin_prop_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t property_id, bool publish) +{ + struct bt_mesh_generic_property *property = NULL; + struct net_buf_simple *msg = NULL; + u16_t length; + + if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) { + BT_ERR("%s, Invalid User Property ID 0x%04x", __func__, property_id); + return; + } + + property = gen_get_admin_property(model, property_id); + if (property == NULL) { + BT_WARN("%s, Admin property 0x%04x not exist", __func__, property_id); + length = sizeof(property_id); + } else { + length = sizeof(property->id) + sizeof(property->admin_access) + property->val->len; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, 1 + length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_STATUS); + if (property == NULL) { + net_buf_simple_add_le16(msg, property_id); + } else { + net_buf_simple_add_le16(msg, property->id); + net_buf_simple_add_u8(msg, property->admin_access); + if (ctx->recv_op != BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET || + property->admin_access != ADMIN_ACCESS_WRITE) { + net_buf_simple_add_mem(msg, property->val->data, property->val->len); + } + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_admin_prop_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_admin_prop_srv *srv = model->user_data; + + if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_get_msg_t get = {0}; + const u8_t *param = NULL; + size_t len = 0; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET) { + get.admin_property_get.id = net_buf_simple_pull_le16(buf); + param = (const u8_t *)&get; + len = sizeof(get); + } + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, param, len); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET: { + struct net_buf_simple *msg = NULL; + u8_t i; + msg = bt_mesh_alloc_buf(1 + srv->property_count * 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_STATUS); + for (i = 0U; i < srv->property_count; i++) { + net_buf_simple_add_le16(msg, srv->properties[i].id); + } + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; + } + case BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET: { + u16_t property_id = net_buf_simple_pull_le16(buf); + send_gen_admin_prop_status(model, ctx, property_id, false); + return; + } + default: + BT_WARN("%s, Unknown Generic Admin Property Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } +} + +static void gen_admin_prop_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_admin_prop_srv *srv = model->user_data; + struct bt_mesh_generic_property *property = NULL; + u16_t property_id; + u8_t access; + + if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + property_id = net_buf_simple_pull_le16(buf); + access = net_buf_simple_pull_u8(buf); + if (access > ADMIN_ACCESS_READ_WRITE) { + BT_ERR("%s, Invalid Admin Access 0x%02x", __func__, access); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .admin_property_set.id = property_id, + .admin_property_set.access = access, + .admin_property_set.value = buf, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + property = gen_get_admin_property(model, property_id); + if (property == NULL) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET) { + send_gen_admin_prop_status(model, ctx, property_id, false); + } + send_gen_admin_prop_status(model, ctx, property_id, true); + return; + } + + property->admin_access = access; + + net_buf_simple_reset(property->val); + net_buf_simple_add_mem(property->val, buf->data, MIN(buf->len, property->val->size)); + + bt_mesh_gen_server_state_change_t change = { + .gen_admin_prop_set.id = property_id, + .gen_admin_prop_set.access = property->admin_access, + .gen_admin_prop_set.value = property->val, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET) { + send_gen_admin_prop_status(model, ctx, property_id, false); + } + send_gen_admin_prop_status(model, ctx, property_id, true); + + return; +} + +/* Generic Manufacturer Property Server message handlers */ +struct bt_mesh_generic_property *gen_get_manu_property(struct bt_mesh_model *model, + u16_t property_id) +{ + struct bt_mesh_gen_manu_prop_srv *srv = model->user_data; + u8_t i; + + for (i = 0U; i < srv->property_count; i++) { + if (srv->properties[i].id == property_id) { + return &srv->properties[i]; + } + } + + return NULL; +} + +static void send_gen_manu_prop_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t property_id, bool publish) +{ + struct bt_mesh_generic_property *property = NULL; + struct net_buf_simple *msg = NULL; + u16_t length; + + if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) { + BT_ERR("%s, Invalid User Property ID 0x%04x", __func__, property_id); + return; + } + + property = gen_get_manu_property(model, property_id); + if (property == NULL) { + BT_WARN("%s, Manufacturer property 0x%04x not exist", __func__, property_id); + length = sizeof(property_id); + } else { + length = sizeof(property->id) + sizeof(property->manu_access) + property->val->len; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, 1 + length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_STATUS); + if (property == NULL) { + net_buf_simple_add_le16(msg, property_id); + } else { + net_buf_simple_add_le16(msg, property->id); + net_buf_simple_add_u8(msg, property->manu_access); + net_buf_simple_add_mem(msg, property->val->data, property->val->len); + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void gen_manu_prop_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_manu_prop_srv *srv = model->user_data; + + if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_get_msg_t get = {0}; + const u8_t *param = NULL; + size_t len = 0; + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET) { + get.manu_property_get.id = net_buf_simple_pull_le16(buf); + param = (const u8_t *)&get; + len = sizeof(get); + } + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, param, len); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_GET: { + struct net_buf_simple *msg = NULL; + u8_t i; + msg = bt_mesh_alloc_buf(1 + srv->property_count * 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_STATUS); + for (i = 0U; i < srv->property_count; i++) { + net_buf_simple_add_le16(msg, srv->properties[i].id); + } + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; + } + case BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET: { + u16_t property_id = net_buf_simple_pull_le16(buf); + send_gen_manu_prop_status(model, ctx, property_id, false); + return; + } + default: + BT_WARN("%s, Unknown Generic Manufacturer Property Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } +} + +static void gen_manu_prop_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_manu_prop_srv *srv = model->user_data; + struct bt_mesh_generic_property *property = NULL; + u16_t property_id; + u8_t access; + + if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + property_id = net_buf_simple_pull_le16(buf); + access = net_buf_simple_pull_u8(buf); + if (access > MANU_ACCESS_READ) { + BT_ERR("%s, Invalid Manufacturer Access 0x%02x", __func__, access); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_set_msg_t set = { + .manu_property_set.id = property_id, + .manu_property_set.access = access, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + property = gen_get_manu_property(model, property_id); + if (property == NULL) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET) { + send_gen_manu_prop_status(model, ctx, property_id, false); + } + send_gen_manu_prop_status(model, ctx, property_id, true); + return; + } + + property->manu_access = access; + + bt_mesh_gen_server_state_change_t change = { + .gen_manu_prop_set.id = property_id, + .gen_manu_prop_set.access = property->manu_access, + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET) { + send_gen_manu_prop_status(model, ctx, property_id, false); + } + send_gen_manu_prop_status(model, ctx, property_id, true); + + return; +} + +/* Generic Client Property Server message handlers */ +static int search_prop_id_index(const u16_t *array, u8_t array_idx, u16_t id) +{ + static const u16_t *start = NULL; + u8_t index; + u16_t temp; + + if (start == NULL) { + start = array; + } + + if (array_idx == 0U) { + if (*array >= id) { + return array - start; + } else { + return -1; + } + } + + index = array_idx / 2; + temp = array[index]; + + if (temp == id) { + return array + index - start; + } else if (temp > id) { + return search_prop_id_index(array, index, id); + } else { + return search_prop_id_index(array + index + 1, array_idx - 1 - index, id); + } +} + +static void gen_client_prop_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_gen_client_prop_srv *srv = model->user_data; + struct net_buf_simple *sdu = NULL; + u16_t total_len = 5; + u16_t property_id; + int i, index; + + if (srv == NULL || srv->id_count == 0U || srv->property_ids == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_gen_server_recv_get_msg_t get = { + .client_properties_get.id = net_buf_simple_pull_le16(buf), + }; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + return; + } + + /* The sequence shall be in an ascending order of Property ID values and shall + * start with a smallest Property ID that is greater than or equal to the value + * of the Generic Client Property field of the Generic Client Properities Get + * message that it is responding to. + */ + + property_id = net_buf_simple_pull_le16(buf); + index = search_prop_id_index(srv->property_ids, srv->id_count - 1, property_id); + if (index < 0) { + NET_BUF_SIMPLE_DEFINE(msg, 1 + BLE_MESH_SERVER_TRANS_MIC_SIZE); + bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS); + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL)); + return; + } + + sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)); + if (sdu == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + + bt_mesh_model_msg_init(sdu, BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS); + for (i = index; i < srv->id_count; i++) { + total_len += sizeof(u16_t); + if (total_len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)) { + /* Add this in case the message is too long */ + break; + } + net_buf_simple_add_le16(sdu, srv->property_ids[i]); + } + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, sdu, NULL, NULL)); + bt_mesh_free_buf(sdu); + return; +} + +/* message handlers (End) */ + +/* Mapping of message handlers for Generic OnOff Server (0x1000) */ +const struct bt_mesh_model_op gen_onoff_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get }, + { BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set }, + { BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Levl Server (0x1002) */ +const struct bt_mesh_model_op gen_level_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_LEVEL_GET, 0, gen_level_get }, + { BLE_MESH_MODEL_OP_GEN_LEVEL_SET, 3, gen_level_set }, + { BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK, 3, gen_level_set }, + { BLE_MESH_MODEL_OP_GEN_DELTA_SET, 5, gen_delta_set }, + { BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK, 5, gen_delta_set }, + { BLE_MESH_MODEL_OP_GEN_MOVE_SET, 3, gen_move_set }, + { BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK, 3, gen_move_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Default TT Server (0x1004) */ +const struct bt_mesh_model_op gen_def_trans_time_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_GET, 0, gen_def_trans_time_get }, + { BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET, 1, gen_def_trans_time_set }, + { BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET_UNACK, 1, gen_def_trans_time_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Power OnOff Server (0x1006) */ +const struct bt_mesh_model_op gen_power_onoff_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_ONPOWERUP_GET, 0, gen_onpowerup_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Power OnOff Setup Server (0x1007) */ +const struct bt_mesh_model_op gen_power_onoff_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET, 1, gen_onpowerup_set }, + { BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET_UNACK, 1, gen_onpowerup_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Power Level Server (0x1009) */ +const struct bt_mesh_model_op gen_power_level_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET, 0, gen_power_level_get }, + { BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET, 3, gen_power_level_set }, + { BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET_UNACK, 3, gen_power_level_set }, + { BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET, 0, gen_power_level_get }, + { BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET, 0, gen_power_level_get }, + { BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET, 0, gen_power_level_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Power Level Setup Server (0x100A) */ +const struct bt_mesh_model_op gen_power_level_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET, 2, gen_power_default_set }, + { BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET_UNACK, 2, gen_power_default_set }, + { BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET, 4, gen_power_range_set }, + { BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET_UNACK, 4, gen_power_range_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Battery Server (0x100C) */ +const struct bt_mesh_model_op gen_battery_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_BATTERY_GET, 0, gen_battery_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Location Server (0x100E) */ +const struct bt_mesh_model_op gen_location_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET, 0, gen_location_get }, + { BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET, 0, gen_location_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Location Setup Server (0x100F) */ +const struct bt_mesh_model_op gen_location_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET, 10, gen_location_set }, + { BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK, 10, gen_location_set }, + { BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET, 9, gen_location_set }, + { BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK, 9, gen_location_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic User Property Server (0x1013) */ +const struct bt_mesh_model_op gen_user_prop_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET, 0, gen_user_prop_get }, + { BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET, 2, gen_user_prop_get }, + { BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET, 3, gen_user_prop_set }, + { BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK, 3, gen_user_prop_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Admin Property Server (0x1011) */ +const struct bt_mesh_model_op gen_admin_prop_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET, 0, gen_admin_prop_get }, + { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET, 2, gen_admin_prop_get }, + { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET, 4, gen_admin_prop_set }, + { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK, 4, gen_admin_prop_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Manufacturer Property Server (0x1012) */ +const struct bt_mesh_model_op gen_manu_prop_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_GET, 0, gen_manu_prop_get }, + { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET, 2, gen_manu_prop_get }, + { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET, 3, gen_manu_prop_set }, + { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET_UNACK, 3, gen_manu_prop_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Generic Client Property Server (0x1014) */ +const struct bt_mesh_model_op gen_client_prop_srv_op[] = { + { BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET, 2, gen_client_prop_get }, + BLE_MESH_MODEL_OP_END, +}; + +static inline int property_id_compare(const void *p1, const void *p2) +{ + if (*(u16_t *)p1 < * (u16_t *)p2) { + return -1; + } + if (*(u16_t *)p1 > *(u16_t *)p2) { + return 1; + } + return 0; +} + +static int generic_server_init(struct bt_mesh_model *model) +{ + if (model->user_data == NULL) { + BT_ERR("%s, No Generic Server context provided, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_GEN_ONOFF_SRV: { + struct bt_mesh_gen_onoff_srv *srv = model->user_data; + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, generic_onoff_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_LEVEL_SRV: { + struct bt_mesh_gen_level_srv *srv = model->user_data; + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, generic_level_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV: { + struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data; + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV: { + struct bt_mesh_gen_power_onoff_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Generic OnPowerUp State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV: { + struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Generic OnPowerUp State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV: { + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Generic Power Level State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, generic_power_level_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV: { + struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Generic Power Level State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_BATTERY_SRV: { + struct bt_mesh_gen_battery_srv *srv = model->user_data; + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_LOCATION_SRV: { + struct bt_mesh_gen_location_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Generic Location State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV: { + struct bt_mesh_gen_location_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Generic Location State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV: { + struct bt_mesh_gen_user_prop_srv *srv = model->user_data; + if (srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, NULL Generic User Property State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV: { + struct bt_mesh_gen_admin_prop_srv *srv = model->user_data; + if (srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, NULL Generic Admin Property State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV: { + struct bt_mesh_gen_manu_prop_srv *srv = model->user_data; + if (srv->property_count == 0U || srv->properties == NULL) { + BT_ERR("%s, NULL Generic Manufacturer Property State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV: { + struct bt_mesh_gen_client_prop_srv *srv = model->user_data; + if (srv->id_count == 0U || srv->property_ids == NULL) { + BT_ERR("%s, NULL Generic Client Property State", __func__); + return -EINVAL; + } + /* Quick sort the Client Property IDs in ascending order */ + qsort(srv->property_ids, srv->id_count, sizeof(u16_t), property_id_compare); + srv->model = model; + break; + } + default: + BT_WARN("%s, Unknown Generic Server Model, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + bt_mesh_generic_server_mutex_new(); + + return 0; +} + +int bt_mesh_gen_onoff_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic OnOff Server has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_level_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Level Server has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_def_trans_time_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Default Trans Time Server has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_power_onoff_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Power OnOff Server has no publication support", __func__); + return -EINVAL; + } + + /* When this model is present on an element, the corresponding Generic + * Power OnOff Setup Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV) == NULL) { + BT_WARN("%s, Generic Power OnOff Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return generic_server_init(model); +} + +int bt_mesh_gen_power_onoff_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + return generic_server_init(model); +} + +int bt_mesh_gen_power_level_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Power Level Server has no publication support", __func__); + return -EINVAL; + } + + /* When this model is present on an Element, the corresponding Generic + * Power Level Setup Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV) == NULL) { + BT_WARN("%s, Generic Power Level Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return generic_server_init(model); +} + +int bt_mesh_gen_power_level_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + return generic_server_init(model); +} + +int bt_mesh_gen_battery_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Battery Server has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_location_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Location Server has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_location_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + /* When this model is present on an Element, the corresponding Generic + * Location Setup Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV) == NULL) { + BT_WARN("%s, Generic Location Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return generic_server_init(model); +} + +int bt_mesh_gen_user_prop_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic User Property has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_admin_prop_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Admin Property has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_manu_prop_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Manufacturer Property has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} + +int bt_mesh_gen_client_prop_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Generic Client Property has no publication support", __func__); + return -EINVAL; + } + + return generic_server_init(model); +} \ No newline at end of file diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/device_property.h b/components/bt/esp_ble_mesh/mesh_models/server/include/device_property.h new file mode 100644 index 000000000..4f69a4428 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/device_property.h @@ -0,0 +1,1045 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _DEVICE_PROPERTY_H_ +#define _DEVICE_PROPERTY_H_ + +#include "mesh_types.h" + +/** + * BLE Mesh Device Properties. + * + * Name Type ID Characteristic Type Size + * Average Ambient Temperature In A Period Of Day org.bluetooth.property.average_ambient_temperature_in_a_period_of_day 0x0001 Temperature 8 In A Period Of Day 3 + * Average Input Current org.bluetooth.property.average_input_current 0x0002 Average Current 3 + * Average Input Voltage org.bluetooth.property.average_input_voltage 0x0003 Average Voltage 3 + * Average Output Current org.bluetooth.property.average_output_current 0x0004 Average Current 3 + * Average Output Voltage org.bluetooth.property.average_output_voltage 0x0005 Average Voltage 3 + * Center Beam Intensity At Full Power org.bluetooth.property.center_beam_intensity_at_full_power 0x0006 Luminous Intensity 2 + * Chromaticity Tolerance org.bluetooth.property.chromaticity_tolerance 0x0007 Chromaticity Tolerance 1 + * Color Rendering Index R9 org.bluetooth.property.color_rendering_index_r9 0x0008 Cie 13.3-1995 Color Rendering Index 1 + * Color Rendering Index Ra org.bluetooth.property.color_rendering_index_ra 0x0009 Cie 13.3-1995 Color Rendering Index 1 + * Device Appearance org.bluetooth.property.device_appearance 0x000A Gap.Appearance 2 + * Device Country Of Origin org.bluetooth.property.device_country_of_origin 0x000B Country Code 2 + * Device Date Of Manufacture org.bluetooth.property.device_date_of_manufacture 0x000C Date Utc 4 + * Device Energy Use Since Turn On org.bluetooth.property.device_energy_use_since_turn_on 0x000D Energy 4 + * Device Firmware Revision org.bluetooth.property.device_firmware_revision 0x000E Fixed String 8 8 + * Device Global Trade Item Number org.bluetooth.property.device_global_trade_item_number 0x000F Global Trade Item Number 8 + * Device Hardware Revision org.bluetooth.property.device_hardware_revision 0x0010 Fixed String 16 16 + * Device Manufacturer Name org.bluetooth.property.device_manufacturer_name 0x0011 Fixed String 36 36 + * Device Model Number org.bluetooth.property.device_model_number 0x0012 Fixed String 24 24 + * Device Operating Temperature Range Specification org.bluetooth.property.device_operating_temperature_range_specification 0x0013 Temperature Range 4 + * Device Operating Temperature Statistical Values org.bluetooth.property.device_operating_temperature_statistical_values 0x0014 Temperature Statistics 9 + * Device Over Temperature Event Statistics org.bluetooth.property.device_over_temperature_event_statistics 0x0015 Event Statistics 6 + * Device Power Range Specification org.bluetooth.property.device_power_range_specification 0x0016 Power Specification 12 + * Device Runtime Since Turn On org.bluetooth.property.device_runtime_since_turn_on 0x0017 Time Hour 24 4 + * Device Runtime Warranty org.bluetooth.property.device_runtime_warranty 0x0018 Time Hour 24 4 + * Device Serial Number org.bluetooth.property.device_serial_number 0x0019 Fixed String 16 16 + * Device Software Revision org.bluetooth.property.device_software_revision 0x001A Fixed String 8 8 + * Device Under Temperature Event Statistics org.bluetooth.property.device_under_temperature_event_statistics 0x001B Event Statistics 6 + * Indoor Ambient Temperature Statistical Values org.bluetooth.property.indoor_ambient_temperature_statistical_values 0x001C Temperature 8 Statistics 5 + * Initial CIE 1931 Chromaticity Coordinates org.bluetooth.property.initial_cie_1931_chromaticity_coordinates 0x001D Chromaticity Coordinates 4 + * Initial Correlated Color Temperature org.bluetooth.property.initial_correlated_color_temperature 0x001E Correlated Color Temperature 2 + * Initial Luminous Flux org.bluetooth.property.initial_luminous_flux 0x001F Luminous Flux 2 + * Initial Planckian Distance org.bluetooth.property.initial_planckian_distance 0x0020 Chromatic Distance From Planckian 2 + * Input Current Range Specification org.bluetooth.property.input_current_range_specification 0x0021 Electric Current Specification 6 + * Input Current Statistics org.bluetooth.property.input_current_statistics 0x0022 Electric Current Statistics 9 + * Input Over Current Event Statistics org.bluetooth.property.input_over_current_event_statistics 0x0023 Event Statistics 6 + * Input Over Ripple Voltage Event Statistics org.bluetooth.property.input_over_ripple_voltage_event_statistics 0x0024 Event Statistics 6 + * Input Over Voltage Event Statistics org.bluetooth.property.input_over_voltage_event_statistics 0x0025 Event Statistics 6 + * Input Under Current Event Statistics org.bluetooth.property.input_under_current_event_statistics 0x0026 Event Statistics 6 + * Input Under Voltage Event Statistics org.bluetooth.property.input_under_voltage_event_statistics 0x0027 Event Statistics 6 + * Input Voltage Range Specification org.bluetooth.property.input_voltage_range_specification 0x0028 Voltage Specification 6 + * Input Voltage Ripple Specification org.bluetooth.property.input_voltage_ripple_specification 0x0029 Percentage 8 1 + * Input Voltage Statistics org.bluetooth.property.input_voltage_statistics 0x002A Voltage Statistics 9 + * Light Control Ambient LuxLevel On org.bluetooth.property.light_control_ambient_luxlevel_on 0x002B Illuminance 4 + * Light Control Ambient LuxLevel Prolong org.bluetooth.property.light_control_ambient_luxlevel_prolong 0x002C Illuminance 4 + * Light Control Ambient LuxLevel Standby org.bluetooth.property.light_control_ambient_luxlevel_standby 0x002D Illuminance 4 + * Light Control Lightness On org.bluetooth.property.light_control_lightness_on 0x002E Perceived Lightness 2 + * Light Control Lightness Prolong org.bluetooth.property.light_control_lightness_prolong 0x002F Perceived Lightness 2 + * Light Control Lightness Standby org.bluetooth.property.light_control_lightness_standby 0x0030 Perceived Lightness 2 + * Light Control Regulator Accuracy org.bluetooth.property.light_control_regulator_accuracy 0x0031 Percentage 8 1 + * Light Control Regulator Kid org.bluetooth.property.light_control_regulator_kid 0x0032 Coefficient 4 + * Light Control Regulator Kiu org.bluetooth.property.light_control_regulator_kiu 0x0033 Coefficient 4 + * Light Control Regulator Kpd org.bluetooth.property.light_control_regulator_kpd 0x0034 Coefficient 4 + * Light Control Regulator Kpu org.bluetooth.property.light_control_regulator_kpu 0x0035 Coefficient 4 + * Light Control Time Fade org.bluetooth.property.light_control_time_fade 0x0036 Time Millisecond 24 4 + * Light Control Time Fade On org.bluetooth.property.light_control_time_fade_on 0x0037 Time Millisecond 24 4 + * Light Control Time Fade Standby Auto org.bluetooth.property.light_control_time_fade_standby_auto 0x0038 Time Millisecond 24 4 + * Light Control Time Fade Standby Manual org.bluetooth.property.light_control_time_fade_standby_manual 0x0039 Time Millisecond 24 4 + * Light Control Time Occupancy Delay org.bluetooth.property.light_control_time_occupancy_delay 0x003A Time Millisecond 24 4 + * Light Control Time Prolong org.bluetooth.property.light_control_time_prolong 0x003B Time Millisecond 24 4 + * Light Control Time Run On org.bluetooth.property.light_control_time_run_on 0x003C Time Millisecond 24 4 + * Lumen Maintenance Factor org.bluetooth.property.lumen_maintenance_factor 0x003D Percentage 8 1 + * Luminous Efficacy org.bluetooth.property.luminous_efficacy 0x003E Luminous Efficacy 2 + * Luminous Energy Since Turn On org.bluetooth.property.luminous_energy_since_turn_on 0x003F Luminous Energy 4 + * Luminous Exposure org.bluetooth.property.luminous_exposure 0x0040 Luminous Exposure 4 + * Luminous Flux Range org.bluetooth.property.luminous_flux_range 0x0041 Luminous Flux Range 4 + * Motion Sensed org.bluetooth.property.motion_sensed 0x0042 Percentage 8 1 + * Motion Threshold org.bluetooth.property.motion_threshold 0x0043 Percentage 8 1 + * Open Circuit Event Statistics org.bluetooth.property.open_circuit_event_statistics 0x0044 Event Statistics 6 + * Outdoor Statistical Values org.bluetooth.property.outdoor_statistical_values 0x0045 Temperature 8 Statistics 5 + * Output Current Range org.bluetooth.property.output_current_range 0x0046 Electric Current Range 4 + * Output Current Statistics org.bluetooth.property.output_current_statistics 0x0047 Electric Current Statistics 9 + * Output Ripple Voltage Specification org.bluetooth.property.output_ripple_voltage_specification 0x0048 Percentage 8 1 + * Output Voltage Range org.bluetooth.property.output_voltage_range 0x0049 Voltage Specification 6 + * Output Voltage Statistics org.bluetooth.property.output_voltage_statistics 0x004A Voltage Statistics 9 + * Over Output Ripple Voltage Event Statistics org.bluetooth.property.over_output_ripple_voltage_event_statistics 0x004B Event Statistics 6 + * People Count org.bluetooth.property.people_count 0x004C Count 16 2 + * Presence Detected org.bluetooth.property.presence_detected 0x004D Boolean 1 + * Present Ambient Light Level org.bluetooth.property.present_ambient_light_level 0x004E Illuminance 4 + * Present Ambient Temperature org.bluetooth.property.present_ambient_temperature 0x004F Temperature 8 1 + * Present CIE 1931 Chromaticity Coordinates org.bluetooth.property.present_cie_1931_chromaticity 0x0050 Chromaticity Coordinates 4 + * Present Correlated Color Temperature org.bluetooth.property.present_correlated_color_temperature 0x0051 Correlated Color Temperature 2 + * Present Device Input Power org.bluetooth.property.present_device_input_power 0x0052 Power 4 + * Present Device Operating Efficiency org.bluetooth.property.present_device_operating_efficiency 0x0053 Percentage 8 1 + * Present Device Operating Temperature org.bluetooth.property.present_device_operating_temperature 0x0054 Temperature 2 + * Present Illuminance org.bluetooth.property.present_illuminance 0x0055 Illuminance 4 + * Present Indoor Ambient Temperature org.bluetooth.property.present_indoor_ambient_temperature 0x0056 Temperature 8 1 + * Present Input Current org.bluetooth.property.present_input_current 0x0057 Electric Current 2 + * Present Input Ripple Voltage org.bluetooth.property.present_input_ripple_voltage 0x0058 Percentage 8 1 + * Present Input Voltage org.bluetooth.property.present_input_voltage 0x0059 Voltage 2 + * Present Luminous Flux org.bluetooth.property.present_luminous_flux 0x005A Luminous Flux 2 + * Present Outdoor Ambient Temperature org.bluetooth.property.present_outdoor_ambient_temperature 0x005B Temperature 8 1 + * Present Output Current org.bluetooth.property.present_output_current 0x005C Electric Current 2 + * Present Output Voltage org.bluetooth.property.present_output_voltage 0x005D Voltage 2 + * Present Planckian Distance org.bluetooth.property.present_planckian_distance 0x005E Chromatic Distance From Planckian 2 + * Present Relative Output Ripple Voltage org.bluetooth.property.present_relative_output_ripple_voltage 0x005F Percentage 8 1 + * Relative Device Energy Use In A Period Of Day org.bluetooth.property.relative_device_energy_use_in_a_period_of_day 0x0060 Energy In A Period Of Day 6 + * Relative Device Runtime In A Generic Level Range org.bluetooth.property.relative_device_runtime_in_a_generic_level_range 0x0061 Relative Runtime In A Generic Level Range 5 + * Relative Exposure Time In An Illuminance Range org.bluetooth.property.relative_exposure_time_in_an_illuminance_range 0x0062 Relative Value In An Illuminance Range 9 + * Relative Runtime In A Correlated Color Temperature Range org.bluetooth.property.relative_runtime_in_a_correlated_color_temperature_range 0x0063 Luminous Energy 4 + * Relative Runtime In A Device Operating Temperature Range org.bluetooth.property.relative_runtime_in_a_device_operating_temperature_range 0x0064 Relative Value In A Temperature Range 5 + * Relative Runtime In An Input Current Range org.bluetooth.property.relative_runtime_in_an_input_current_range 0x0065 Relative Runtime In A Current Range 5 + * Relative Runtime In An Input Voltage Range org.bluetooth.property.relative_runtime_in_an_input_voltage_range 0x0066 Relative Value In A Voltage Range 5 + * Short Circuit Event Statistics org.bluetooth.property.short_circuit_event_statistics 0x0067 Event Statistics 6 + * Time Since Motion Sensed org.bluetooth.property.time_since_motion_sensed 0x0068 Time Second 16 2 + * Time Since Presence Detected org.bluetooth.property.time_since_presence_detected 0x0069 Time Second 16 2 + * Total Device Energy Use org.bluetooth.property.total_device_energy_use 0x006A Energy 4 + * Total Device Off On Cycles org.bluetooth.property.total_device_off_on_cycles 0x006B Count 24 4 + * Total Device Power On Cycles org.bluetooth.property.total_device_power_on_cycles 0x006C Count 24 4 + * Total Device Power On Time org.bluetooth.property.total_device_power_on_time 0x006D Time Hour 24 4 + * Total Device Runtime org.bluetooth.property.total_device_runtime 0x006E Time Hour 24 4 + * Total Light Exposure Time org.bluetooth.property.total_light_exposure_time 0x006F Time Hour 24 4 + * Total Luminous Energy org.bluetooth.property.total_luminous_energy 0x0070 Luminous Energy 4 + */ + +/** + * Characteristics referenced by BLE Mesh Device Properties. + * + * Name Uniform Type Identifier Assigned Number Specification Level + * Average Current org.bluetooth.characteristic.average_current 2AE0 Adopted + * Average Voltage org.bluetooth.characteristic.average_voltage 2AE1 Adopted + * Boolean org.bluetooth.characteristic.boolean 2AE2 Adopted + * Chromatic Distance From Planckian org.bluetooth.characteristic.chromatic_distance_from_planckian 2AE3 Adopted + * Chromaticity Coordinate org.bluetooth.characteristic.chromaticity_coordinate 2B1C Adopted + * Chromaticity Coordinates org.bluetooth.characteristic.chromaticity_coordinates 2AE4 Adopted + * Chromaticity In CCT And Duv Values org.bluetooth.characteristic.chromaticity_in_cct_and_duv_values 2AE5 Adopted + * Chromaticity Tolerance org.bluetooth.characteristic.chromaticity_tolerance 2AE6 Adopted + * CIE 13.3-1995 Color Rendering Index org.bluetooth.characteristic.cie_13.3-1995_color_rendering_index 2AE7 Adopted + * Coefficient org.bluetooth.characteristic.coefficient 2AE8 Adopted + * Correlated Color Temperature org.bluetooth.characteristic.correlated_color_temperature 2AE9 Adopted + * Count 16 org.bluetooth.characteristic.count_16 2AEA Adopted + * Count 24 org.bluetooth.characteristic.count_24 2AEB Adopted + * Country Code org.bluetooth.characteristic.country_code 2AEC Adopted + * Date UTC org.bluetooth.characteristic.date_utc 2AED Adopted + * Electric Current org.bluetooth.characteristic.electric_current 2AEE Adopted + * Electric Current Range org.bluetooth.characteristic.electric_current_range 2AEF Adopted + * Electric Current Specification org.bluetooth.characteristic.electric_current_specification 2AF0 Adopted + * Electric Current Statistics org.bluetooth.characteristic.electric_current_statistics 2AF1 Adopted + * Energy org.bluetooth.characteristic.energy 2AF2 Adopted + * Energy In A Period Of Day org.bluetooth.characteristic.energy_in_a_period_of_day 2AF3 Adopted + * Event Statistics org.bluetooth.characteristic.event_statistics 2AF4 Adopted + * Fixed String 16 org.bluetooth.characteristic.fixed_string_16 2AF5 Adopted + * Fixed String 24 org.bluetooth.characteristic.fixed_string_24 2AF6 Adopted + * Fixed String 36 org.bluetooth.characteristic.fixed_string_36 2AF7 Adopted + * Fixed String 8 org.bluetooth.characteristic.fixed_string_8 2AF8 Adopted + * Generic Level org.bluetooth.characteristic.generic_level 2AF9 Adopted + * Global Trade Item Number org.bluetooth.characteristic.global_trade_item_number 2AFA Adopted + * Illuminance org.bluetooth.characteristic.illuminance 2AFB Adopted + * Luminous Efficacy org.bluetooth.characteristic.luminous_efficacy 2AFC Adopted + * Luminous Energy org.bluetooth.characteristic.luminous_energy 2AFD Adopted + * Luminous Exposure org.bluetooth.characteristic.luminous_exposure 2AFE Adopted + * Luminous Flux org.bluetooth.characteristic.luminous_flux 2AFF Adopted + * Luminous Flux Range org.bluetooth.characteristic.luminous_flux_range 2B00 Adopted + * Luminous Intensity org.bluetooth.characteristic.luminous_intensity 2B01 Adopted + * Mass Flow org.bluetooth.characteristic.mass_flow 2B02 Adopted + * Mesh Provisioning Data In org.bluetooth.characteristic.mesh_provisioning_data_in 2ADB Adopted + * Mesh Provisioning Data Out org.bluetooth.characteristic.mesh_provisioning_data_out 2ADC Adopted + * Mesh Proxy Data In org.bluetooth.characteristic.mesh_proxy_data_in 2ADD Adopted + * Mesh Proxy Data Out org.bluetooth.characteristic.mesh_proxy_data_out 2ADE Adopted + * Perceived Lightness org.bluetooth.characteristic.perceived_lightness 2B03 Adopted + * Percentage 8 org.bluetooth.characteristic.percentage_8 2B04 Adopted + * Power org.bluetooth.characteristic.power 2B05 Adopted + * Power Specification org.bluetooth.characteristic.power_specification 2B06 Adopted + * Relative Runtime In A Current Range org.bluetooth.characteristic.relative_runtime_in_a_current_range 2B07 Adopted + * Relative Runtime In A Generic Level Range org.bluetooth.characteristic.relative_runtime_in_a_generic_level_range 2B08 Adopted + * Relative Value In A Period of Day org.bluetooth.characteristic.relative_value_in_a_period_of_day 2B0B Adopted + * Relative Value In A Temperature Range org.bluetooth.characteristic.relative_value_in_a_temperature_range 2B0C Adopted + * Relative Value In A Voltage Range org.bluetooth.characteristic.relative_value_in_a_voltage_range 2B09 Adopted + * Relative Value In An Illuminance Range org.bluetooth.characteristic.relative_value_in_an_illuminance_range 2B0A Adopted + * Temperature 8 org.bluetooth.characteristic.temperature_8 2B0D Adopted + * Temperature 8 In A Period Of Day org.bluetooth.characteristic.temperature_8_in_a_period_of_day 2B0E Adopted + * Temperature 8 Statistics org.bluetooth.characteristic.temperature_8_statistics 2B0F Adopted + * Temperature Range org.bluetooth.characteristic.temperature_range 2B10 Adopted + * Temperature Statistics org.bluetooth.characteristic.temperature_statistics 2B11 Adopted + * Time Decihour 8 org.bluetooth.characteristic.time_decihour_8 2B12 Adopted + * Time Exponential 8 org.bluetooth.characteristic.time_exponential_8 2B13 Adopted + * Time Hour 24 org.bluetooth.characteristic.time_hour_24 2B14 Adopted + * Time Millisecond 24 org.bluetooth.characteristic.time_millisecond_24 2B15 Adopted + * Time Second 16 org.bluetooth.characteristic.time_second_16 2B16 Adopted + * Time Second 8 org.bluetooth.characteristic.time_second_8 2B17 Adopted + * Voltage org.bluetooth.characteristic.voltage 2B18 Adopted + * Voltage Specification org.bluetooth.characteristic.voltage_specification 2B19 Adopted + * Voltage Statistics org.bluetooth.characteristic.voltage_statistics 2B1A Adopted + * Volume Flow org.bluetooth.characteristic.volume_flow 2B1B Adopted + */ + +/** + * @brief BLE Mesh Device Property IDs + */ +#define BLE_MESH_AVERAGE_AMBIENT_TEMPERATURE_IN_A_PERIOD_OF_DAY 0x0001 +#define BLE_MESH_AVERAGE_INPUT_CURRENT 0x0002 +#define BLE_MESH_AVERAGE_INPUT_VOLTAGE 0x0003 +#define BLE_MESH_AVERAGE_OUTPUT_CURRENT 0x0004 +#define BLE_MESH_AVERAGE_OUTPUT_VOLTAGE 0x0005 +#define BLE_MESH_CENTER_BEAM_INTENSITY_AT_FULL_POWER 0x0006 +#define BLE_MESH_CHROMATICITY_TOLERANCE 0x0007 +#define BLE_MESH_COLOR_RENDERING_INDEX_R9 0x0008 +#define BLE_MESH_COLOR_RENDERING_INDEX_RA 0x0009 +#define BLE_MESH_DEVICE_APPEARANCE 0x000A +#define BLE_MESH_DEVICE_COUNTRY_OF_ORIGIN 0x000B +#define BLE_MESH_DEVICE_DATE_OF_MANUFACTURE 0x000C +#define BLE_MESH_DEVICE_ENERGY_USE_SINCE_TURN_ON 0x000D +#define BLE_MESH_DEVICE_FIRMWARE_REVISION 0x000E +#define BLE_MESH_DEVICE_GLOBAL_TRADE_ITEM_NUMBER 0x000F +#define BLE_MESH_DEVICE_HARDWARE_REVISION 0x0010 +#define BLE_MESH_DEVICE_MANUFACTURER_NAME 0x0011 +#define BLE_MESH_DEVICE_MODEL_NUMBER 0x0012 +#define BLE_MESH_DEVICE_OPERATING_TEMPERATURE_RANGE_SPECIFICATION 0x0013 +#define BLE_MESH_DEVICE_OPERATING_TEMPERATURE_STATISTICAL_VALUES 0x0014 +#define BLE_MESH_DEVICE_OVER_TEMPERATURE_EVENT_STATISTICS 0x0015 +#define BLE_MESH_DEVICE_POWER_RANGE_SPECIFICATION 0x0016 +#define BLE_MESH_DEVICE_RUNTIME_SINCE_TURN_ON 0x0017 +#define BLE_MESH_DEVICE_RUNTIME_WARRANTY 0x0018 +#define BLE_MESH_DEVICE_SERIAL_NUMBER 0x0019 +#define BLE_MESH_DEVICE_SOFTWARE_REVISION 0x001A +#define BLE_MESH_DEVICE_UNDER_TEMPERATURE_EVENT_STATISTICS 0x001B +#define BLE_MESH_INDOOR_AMBIENT_TEMPERATURE_STATISTICAL_VALUES 0x001C +#define BLE_MESH_INITIAL_CIE_1931_CHROMATICITY_COORDINATES 0x001D +#define BLE_MESH_INITIAL_CORRELATED_COLOR_TEMPERATURE 0x001E +#define BLE_MESH_INITIAL_LUMINOUS_FLUX 0x001F +#define BLE_MESH_INITIAL_PLANCKIAN_DISTANCE 0x0020 +#define BLE_MESH_INPUT_CURRENT_RANGE_SPECIFICATION 0x0021 +#define BLE_MESH_INPUT_CURRENT_STATISTICS 0x0022 +#define BLE_MESH_INPUT_OVER_CURRENT_EVENT_STATISTICS 0x0023 +#define BLE_MESH_INPUT_OVER_RIPPLE_VOLTAGE_EVENT_STATISTICS 0x0024 +#define BLE_MESH_INPUT_OVER_VOLTAGE_EVENT_STATISTICS 0x0025 +#define BLE_MESH_INPUT_UNDER_CURRENT_EVENT_STATISTICS 0x0026 +#define BLE_MESH_INPUT_UNDER_VOLTAGE_EVENT_STATISTICS 0x0027 +#define BLE_MESH_INPUT_VOLTAGE_RANGE_SPECIFICATION 0x0028 +#define BLE_MESH_INPUT_VOLTAGE_RIPPLE_SPECIFICATION 0x0029 +#define BLE_MESH_INPUT_VOLTAGE_STATISTICS 0x002A +#define BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_ON 0x002B +#define BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_PROLONG 0x002C +#define BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_STANDBY 0x002D +#define BLE_MESH_LIGHT_CONTROL_LIGHTNESS_ON 0x002E +#define BLE_MESH_LIGHT_CONTROL_LIGHTNESS_PROLONG 0x002F +#define BLE_MESH_LIGHT_CONTROL_LIGHTNESS_STANDBY 0x0030 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_ACCURACY 0x0031 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KID 0x0032 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KIU 0x0033 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KPD 0x0034 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KPU 0x0035 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE 0x0036 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE_ON 0x0037 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_AUTO 0x0038 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_MANUAL 0x0039 +#define BLE_MESH_LIGHT_CONTROL_TIME_OCCUPANCY_DELAY 0x003A +#define BLE_MESH_LIGHT_CONTROL_TIME_PROLONG 0x003B +#define BLE_MESH_LIGHT_CONTROL_TIME_RUN_ON 0x003C +#define BLE_MESH_LUMEN_MAINTENANCE_FACTOR 0x003D +#define BLE_MESH_LUMINOUS_EFFICACY 0x003E +#define BLE_MESH_LUMINOUS_ENERGY_SINCE_TURN_ON 0x003F +#define BLE_MESH_LUMINOUS_EXPOSURE 0x0040 +#define BLE_MESH_LUMINOUS_FLUX_RANGE 0x0041 +#define BLE_MESH_MOTION_SENSED 0x0042 +#define BLE_MESH_MOTION_THRESHOLD 0x0043 +#define BLE_MESH_OPEN_CIRCUIT_EVENT_STATISTICS 0x0044 +#define BLE_MESH_OUTDOOR_STATISTICAL_VALUES 0x0045 +#define BLE_MESH_OUTPUT_CURRENT_RANGE 0x0046 +#define BLE_MESH_OUTPUT_CURRENT_STATISTICS 0x0047 +#define BLE_MESH_OUTPUT_RIPPLE_VOLTAGE_SPECIFICATION 0x0048 +#define BLE_MESH_OUTPUT_VOLTAGE_RANGE 0x0049 +#define BLE_MESH_OUTPUT_VOLTAGE_STATISTICS 0x004A +#define BLE_MESH_OVER_OUTPUT_RIPPLE_VOLTAGE_EVENT_STATISTICS 0x004B +#define BLE_MESH_PEOPLE_COUNT 0x004C +#define BLE_MESH_PRESENCE_DETECTED 0x004D +#define BLE_MESH_PRESENT_AMBIENT_LIGHT_LEVEL 0x004E +#define BLE_MESH_PRESENT_AMBIENT_TEMPERATURE 0x004F +#define BLE_MESH_PRESENT_CIE_1931_CHROMATICITY 0x0050 +#define BLE_MESH_PRESENT_CORRELATED_COLOR_TEMPERATURE 0x0051 +#define BLE_MESH_PRESENT_DEVICE_INPUT_POWER 0x0052 +#define BLE_MESH_PRESENT_DEVICE_OPERATING_EFFICIENCY 0x0053 +#define BLE_MESH_PRESENT_DEVICE_OPERATING_TEMPERATURE 0x0054 +#define BLE_MESH_PRESENT_ILLUMINANCE 0x0055 +#define BLE_MESH_PRESENT_INDOOR_AMBIENT_TEMPERATURE 0x0056 +#define BLE_MESH_PRESENT_INPUT_CURRENT 0x0057 +#define BLE_MESH_PRESENT_INPUT_RIPPLE_VOLTAGE 0x0058 +#define BLE_MESH_PRESENT_INPUT_VOLTAGE 0x0059 +#define BLE_MESH_PRESENT_LUMINOUS_FLUX 0x005A +#define BLE_MESH_PRESENT_OUTDOOR_AMBIENT_TEMPERATURE 0x005B +#define BLE_MESH_PRESENT_OUTPUT_CURRENT 0x005C +#define BLE_MESH_PRESENT_OUTPUT_VOLTAGE 0x005D +#define BLE_MESH_PRESENT_PLANCKIAN_DISTANCE 0x005E +#define BLE_MESH_PRESENT_RELATIVE_OUTPUT_RIPPLE_VOLTAGE 0x005F +#define BLE_MESH_RELATIVE_DEVICE_ENERGY_USE_IN_A_PERIOD_OF_DAY 0x0060 +#define BLE_MESH_RELATIVE_DEVICE_RUNTIME_IN_A_GENERIC_LEVEL_RANGE 0x0061 +#define BLE_MESH_RELATIVE_EXPOSURE_TIME_IN_AN_ILLUMINANCE_RANGE 0x0062 +#define BLE_MESH_RELATIVE_RUNTIME_IN_A_CORRELATED_COLOR_TEMPERATURE_RANGE 0x0063 +#define BLE_MESH_RELATIVE_RUNTIME_IN_A_DEVICE_OPERATING_TEMPERATURE_RANGE 0x0064 +#define BLE_MESH_RELATIVE_RUNTIME_IN_AN_INPUT_CURRENT_RANGE 0x0065 +#define BLE_MESH_RELATIVE_RUNTIME_IN_AN_INPUT_VOLTAGE_RANGE 0x0066 +#define BLE_MESH_SHORT_CIRCUIT_EVENT_STATISTICS 0x0067 +#define BLE_MESH_TIME_SINCE_MOTION_SENSED 0x0068 +#define BLE_MESH_TIME_SINCE_PRESENCE_DETECTED 0x0069 +#define BLE_MESH_TOTAL_DEVICE_ENERGY_USE 0x006A +#define BLE_MESH_TOTAL_DEVICE_OFF_ON_CYCLES 0x006B +#define BLE_MESH_TOTAL_DEVICE_POWER_ON_CYCLES 0x006C +#define BLE_MESH_TOTAL_DEVICE_POWER_ON_TIME 0x006D +#define BLE_MESH_TOTAL_DEVICE_RUNTIME 0x006E +#define BLE_MESH_TOTAL_LIGHT_EXPOSURE_TIME 0x006F +#define BLE_MESH_TOTAL_LUMINOUS_ENERGY 0x0070 + +/** + * @brief BLE Mesh Device Property value length + */ +#define BLE_MESH_AVERAGE_AMBIENT_TEMPERATURE_IN_A_PERIOD_OF_DAY_LEN 0x03 +#define BLE_MESH_AVERAGE_INPUT_CURRENT_LEN 0x03 +#define BLE_MESH_AVERAGE_INPUT_VOLTAGE_LEN 0x03 +#define BLE_MESH_AVERAGE_OUTPUT_CURRENT_LEN 0x03 +#define BLE_MESH_AVERAGE_OUTPUT_VOLTAGE_LEN 0x03 +#define BLE_MESH_CENTER_BEAM_INTENSITY_AT_FULL_POWER_LEN 0x02 +#define BLE_MESH_CHROMATICITY_TOLERANCE_LEN 0x01 +#define BLE_MESH_COLOR_RENDERING_INDEX_R9_LEN 0x01 +#define BLE_MESH_COLOR_RENDERING_INDEX_RA_LEN 0x01 +#define BLE_MESH_DEVICE_APPEARANCE_LEN 0x02 +#define BLE_MESH_DEVICE_COUNTRY_OF_ORIGIN_LEN 0x02 +#define BLE_MESH_DEVICE_DATE_OF_MANUFACTURE_LEN 0x04 +#define BLE_MESH_DEVICE_ENERGY_USE_SINCE_TURN_ON_LEN 0x04 +#define BLE_MESH_DEVICE_FIRMWARE_REVISION_LEN 0x08 +#define BLE_MESH_DEVICE_GLOBAL_TRADE_ITEM_NUMBER_LEN 0x08 +#define BLE_MESH_DEVICE_HARDWARE_REVISION_LEN 0x16 +#define BLE_MESH_DEVICE_MANUFACTURER_NAME_LEN 0x36 +#define BLE_MESH_DEVICE_MODEL_NUMBER_LEN 0x24 +#define BLE_MESH_DEVICE_OPERATING_TEMPERATURE_RANGE_SPECIFICATION_LEN 0x04 +#define BLE_MESH_DEVICE_OPERATING_TEMPERATURE_STATISTICAL_VALUES_LEN 0x09 +#define BLE_MESH_DEVICE_OVER_TEMPERATURE_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_DEVICE_POWER_RANGE_SPECIFICATION_LEN 0x12 +#define BLE_MESH_DEVICE_RUNTIME_SINCE_TURN_ON_LEN 0x04 +#define BLE_MESH_DEVICE_RUNTIME_WARRANTY_LEN 0x04 +#define BLE_MESH_DEVICE_SERIAL_NUMBER_LEN 0x16 +#define BLE_MESH_DEVICE_SOFTWARE_REVISION_LEN 0x08 +#define BLE_MESH_DEVICE_UNDER_TEMPERATURE_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_INDOOR_AMBIENT_TEMPERATURE_STATISTICAL_VALUES_LEN 0x05 +#define BLE_MESH_INITIAL_CIE_1931_CHROMATICITY_COORDINATES_LEN 0x04 +#define BLE_MESH_INITIAL_CORRELATED_COLOR_TEMPERATURE_LEN 0x02 +#define BLE_MESH_INITIAL_LUMINOUS_FLUX_LEN 0x02 +#define BLE_MESH_INITIAL_PLANCKIAN_DISTANCE_LEN 0x02 +#define BLE_MESH_INPUT_CURRENT_RANGE_SPECIFICATION_LEN 0x06 +#define BLE_MESH_INPUT_CURRENT_STATISTICS_LEN 0x09 +#define BLE_MESH_INPUT_OVER_CURRENT_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_INPUT_OVER_RIPPLE_VOLTAGE_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_INPUT_OVER_VOLTAGE_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_INPUT_UNDER_CURRENT_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_INPUT_UNDER_VOLTAGE_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_INPUT_VOLTAGE_RANGE_SPECIFICATION_LEN 0x06 +#define BLE_MESH_INPUT_VOLTAGE_RIPPLE_SPECIFICATION_LEN 0x01 +#define BLE_MESH_INPUT_VOLTAGE_STATISTICS_LEN 0x09 +#define BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_ON_LEN 0x04 +#define BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_PROLONG_LEN 0x04 +#define BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_STANDBY_LEN 0x04 +#define BLE_MESH_LIGHT_CONTROL_LIGHTNESS_ON_LEN 0x02 +#define BLE_MESH_LIGHT_CONTROL_LIGHTNESS_PROLONG_LEN 0x02 +#define BLE_MESH_LIGHT_CONTROL_LIGHTNESS_STANDBY_LEN 0x02 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_ACCURACY_LEN 0x01 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KID_LEN 0x04 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KIU_LEN 0x04 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KPD_LEN 0x04 +#define BLE_MESH_LIGHT_CONTROL_REGULATOR_KPU_LEN 0x04 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE_LEN 0x03 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE_ON_LEN 0x03 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_AUTO_LEN 0x03 +#define BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_MANUAL_LEN 0x03 +#define BLE_MESH_LIGHT_CONTROL_TIME_OCCUPANCY_DELAY_LEN 0x03 +#define BLE_MESH_LIGHT_CONTROL_TIME_PROLONG_LEN 0x03 +#define BLE_MESH_LIGHT_CONTROL_TIME_RUN_ON_LEN 0x03 +#define BLE_MESH_LUMEN_MAINTENANCE_FACTOR_LEN 0x01 +#define BLE_MESH_LUMINOUS_EFFICACY_LEN 0x02 +#define BLE_MESH_LUMINOUS_ENERGY_SINCE_TURN_ON_LEN 0x04 +#define BLE_MESH_LUMINOUS_EXPOSURE_LEN 0x04 +#define BLE_MESH_LUMINOUS_FLUX_RANGE_LEN 0x04 +#define BLE_MESH_MOTION_SENSED_LEN 0x01 +#define BLE_MESH_MOTION_THRESHOLD_LEN 0x01 +#define BLE_MESH_OPEN_CIRCUIT_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_OUTDOOR_STATISTICAL_VALUES_LEN 0x05 +#define BLE_MESH_OUTPUT_CURRENT_RANGE_LEN 0x04 +#define BLE_MESH_OUTPUT_CURRENT_STATISTICS_LEN 0x09 +#define BLE_MESH_OUTPUT_RIPPLE_VOLTAGE_SPECIFICATION_LEN 0x01 +#define BLE_MESH_OUTPUT_VOLTAGE_RANGE_LEN 0x06 +#define BLE_MESH_OUTPUT_VOLTAGE_STATISTICS_LEN 0x09 +#define BLE_MESH_OVER_OUTPUT_RIPPLE_VOLTAGE_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_PEOPLE_COUNT_LEN 0x02 +#define BLE_MESH_PRESENCE_DETECTED_LEN 0x01 +#define BLE_MESH_PRESENT_AMBIENT_LIGHT_LEVEL_LEN 0x04 +#define BLE_MESH_PRESENT_AMBIENT_TEMPERATURE_LEN 0x01 +#define BLE_MESH_PRESENT_CIE_1931_CHROMATICITY_LEN 0x04 +#define BLE_MESH_PRESENT_CORRELATED_COLOR_TEMPERATURE_LEN 0x02 +#define BLE_MESH_PRESENT_DEVICE_INPUT_POWER_LEN 0x04 +#define BLE_MESH_PRESENT_DEVICE_OPERATING_EFFICIENCY_LEN 0x01 +#define BLE_MESH_PRESENT_DEVICE_OPERATING_TEMPERATURE_LEN 0x02 +#define BLE_MESH_PRESENT_ILLUMINANCE_LEN 0x04 +#define BLE_MESH_PRESENT_INDOOR_AMBIENT_TEMPERATURE_LEN 0x01 +#define BLE_MESH_PRESENT_INPUT_CURRENT_LEN 0x02 +#define BLE_MESH_PRESENT_INPUT_RIPPLE_VOLTAGE_LEN 0x01 +#define BLE_MESH_PRESENT_INPUT_VOLTAGE_LEN 0x02 +#define BLE_MESH_PRESENT_LUMINOUS_FLUX_LEN 0x02 +#define BLE_MESH_PRESENT_OUTDOOR_AMBIENT_TEMPERATURE_LEN 0x01 +#define BLE_MESH_PRESENT_OUTPUT_CURRENT_LEN 0x02 +#define BLE_MESH_PRESENT_OUTPUT_VOLTAGE_LEN 0x02 +#define BLE_MESH_PRESENT_PLANCKIAN_DISTANCE_LEN 0x02 +#define BLE_MESH_PRESENT_RELATIVE_OUTPUT_RIPPLE_VOLTAGE_LEN 0x01 +#define BLE_MESH_RELATIVE_DEVICE_ENERGY_USE_IN_A_PERIOD_OF_DAY_LEN 0x06 +#define BLE_MESH_RELATIVE_DEVICE_RUNTIME_IN_A_GENERIC_LEVEL_RANGE_LEN 0x05 +#define BLE_MESH_RELATIVE_EXPOSURE_TIME_IN_AN_ILLUMINANCE_RANGE_LEN 0x09 +#define BLE_MESH_RELATIVE_RUNTIME_IN_A_CORRELATED_COLOR_TEMPERATURE_RANGE_LEN 0x04 +#define BLE_MESH_RELATIVE_RUNTIME_IN_A_DEVICE_OPERATING_TEMPERATURE_RANGE_LEN 0x05 +#define BLE_MESH_RELATIVE_RUNTIME_IN_AN_INPUT_CURRENT_RANGE_LEN 0x05 +#define BLE_MESH_RELATIVE_RUNTIME_IN_AN_INPUT_VOLTAGE_RANGE_LEN 0x05 +#define BLE_MESH_SHORT_CIRCUIT_EVENT_STATISTICS_LEN 0x06 +#define BLE_MESH_TIME_SINCE_MOTION_SENSED_LEN 0x02 +#define BLE_MESH_TIME_SINCE_PRESENCE_DETECTED_LEN 0x02 +#define BLE_MESH_TOTAL_DEVICE_ENERGY_USE_LEN 0x04 +#define BLE_MESH_TOTAL_DEVICE_OFF_ON_CYCLES_LEN 0x04 +#define BLE_MESH_TOTAL_DEVICE_POWER_ON_CYCLES_LEN 0x04 +#define BLE_MESH_TOTAL_DEVICE_POWER_ON_TIME_LEN 0x04 +#define BLE_MESH_TOTAL_DEVICE_RUNTIME_LEN 0x04 +#define BLE_MESH_TOTAL_LIGHT_EXPOSURE_TIME_LEN 0x04 +#define BLE_MESH_TOTAL_LUMINOUS_ENERGY_LEN 0x04 + +/** + * @brief BLE Mesh Device Property referenced Characteristic UUIDs + */ +#define BLE_MESH_UUID_AVERAGE_CURRENT_VAL 0x2AE0 +#define BLE_MESH_UUID_AVERAGE_VOLTAGE_VAL 0x2AE1 +#define BLE_MESH_UUID_BOOLEAN_VAL 0x2AE2 +#define BLE_MESH_UUID_CHROMATIC_DISTANCE_FROM_PLANCKIAN_VAL 0x2AE3 +#define BLE_MESH_UUID_CHROMATICITY_COORDINATE_VAL 0x2B1C +#define BLE_MESH_UUID_CHROMATICITY_COORDINATES_VAL 0x2AE4 +#define BLE_MESH_UUID_CHROMATICITY_IN_CCT_AND_DUV_VALUES_VAL 0x2AE5 +#define BLE_MESH_UUID_CHROMATICITY_TOLERANCE_VAL 0x2AE6 +#define BLE_MESH_UUID_CIE_13_3_1995_COLOR_RENDERING_INDEX_VAL 0x2AE7 +#define BLE_MESH_UUID_COEFFICIENT_VAL 0x2AE8 +#define BLE_MESH_UUID_CORRELATED_COLOR_TEMPERATURE_VAL 0x2AE9 +#define BLE_MESH_UUID_COUNT_16_VAL 0x2AEA +#define BLE_MESH_UUID_COUNT_24_VAL 0x2AEB +#define BLE_MESH_UUID_COUNTRY_CODE_VAL 0x2AEC +#define BLE_MESH_UUID_DATE_UTC_VAL 0x2AED +#define BLE_MESH_UUID_ELECTRIC_CURRENT_VAL 0x2AEE +#define BLE_MESH_UUID_ELECTRIC_CURRENT_RANGE_VAL 0x2AEF +#define BLE_MESH_UUID_ELECTRIC_CURRENT_SPECIFICATION_VAL 0x2AF0 +#define BLE_MESH_UUID_ELECTRIC_CURRENT_STATISTICS_VAL 0x2AF1 +#define BLE_MESH_UUID_ENERGY_VAL 0x2AF2 +#define BLE_MESH_UUID_ENERGY_IN_A_PERIOD_OF_DAY_VAL 0x2AF3 +#define BLE_MESH_UUID_EVENT_STATISTICS_VAL 0x2AF4 +#define BLE_MESH_UUID_FIXED_STRING_16_VAL 0x2AF5 +#define BLE_MESH_UUID_FIXED_STRING_24_VAL 0x2AF6 +#define BLE_MESH_UUID_FIXED_STRING_36_VAL 0x2AF7 +#define BLE_MESH_UUID_FIXED_STRING_8_VAL 0x2AF8 +#define BLE_MESH_UUID_GENERIC_LEVEL_VAL 0x2AF9 +#define BLE_MESH_UUID_GLOBAL_TRADE_ITEM_NUMBER_VAL 0x2AFA +#define BLE_MESH_UUID_ILLUMINANCE_VAL 0x2AFB +#define BLE_MESH_UUID_LUMINOUS_EFFICACY_VAL 0x2AFC +#define BLE_MESH_UUID_LUMINOUS_ENERGY_VAL 0x2AFD +#define BLE_MESH_UUID_LUMINOUS_EXPOSURE_VAL 0x2AFE +#define BLE_MESH_UUID_LUMINOUS_FLUX_VAL 0x2AFF +#define BLE_MESH_UUID_LUMINOUS_FLUX_RANGE_VAL 0x2B00 +#define BLE_MESH_UUID_LUMINOUS_INTENSITY_VAL 0x2B01 +#define BLE_MESH_UUID_MASS_FLOW_VAL 0x2B02 +/** + * The following four have been defined in mesh_uuid.h + * #define BLE_MESH_UUID_MESH_PROV_DATA_IN_VAL 0x2ADB + * #define BLE_MESH_UUID_MESH_PROV_DATA_OUT_VAL 0x2ADC + * #define BLE_MESH_UUID_MESH_PROXY_DATA_IN_VAL 0x2ADD + * #define BLE_MESH_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ADE + */ +#define BLE_MESH_UUID_PERCEIVED_LIGHTNESS_VAL 0x2B03 +#define BLE_MESH_UUID_PERCENTAGE_8_VAL 0x2B04 +#define BLE_MESH_UUID_POWER_VAL 0x2B05 +#define BLE_MESH_UUID_POWER_SPECIFICATION_VAL 0x2B06 +#define BLE_MESH_UUID_RELATIVE_RUNTIME_IN_A_CURRENT_RANGE_VAL 0x2B07 +#define BLE_MESH_UUID_RELATIVE_RUNTIME_IN_A_GENERIC_LEVEL_RANGE_VAL 0x2B08 +#define BLE_MESH_UUID_RELATIVE_VALUE_IN_A_PERIOD_OF_DAY_VAL 0x2B0B +#define BLE_MESH_UUID_RELATIVE_VALUE_IN_A_TEMPERATURE_RANGE_VAL 0x2B0C +#define BLE_MESH_UUID_RELATIVE_VALUE_IN_A_VOLTAGE_RANGE_VAL 0x2B09 +#define BLE_MESH_UUID_RELATIVE_VALUE_IN_AN_ILLUMINANCE_RANGE_VAL 0x2B0A +#define BLE_MESH_UUID_TEMPERATURE_8_VAL 0x2B0D +#define BLE_MESH_UUID_TEMPERATURE_8_IN_A_PERIOD_OF_DAY_VAL 0x2B0E +#define BLE_MESH_UUID_TEMPERATURE_8_STATISTICS_VAL 0x2B0F +#define BLE_MESH_UUID_TEMPERATURE_RANGE_VAL 0x2B10 +#define BLE_MESH_UUID_TEMPERATURE_STATISTICS_VAL 0x2B11 +#define BLE_MESH_UUID_TIME_DECIHOUR_8_VAL 0x2B12 +#define BLE_MESH_UUID_TIME_EXPONENTIAL_8_VAL 0x2B13 +#define BLE_MESH_UUID_TIME_HOUR_24_VAL 0x2B14 +#define BLE_MESH_UUID_TIME_MILLISECOND_24_VAL 0x2B15 +#define BLE_MESH_UUID_TIME_SECOND_16_VAL 0x2B16 +#define BLE_MESH_UUID_TIME_SECOND_8_VAL 0x2B17 +#define BLE_MESH_UUID_VOLTAGE_VAL 0x2B18 +#define BLE_MESH_UUID_VOLTAGE_SPECIFICATION_VAL 0x2B19 +#define BLE_MESH_UUID_VOLTAGE_STATISTICS_VAL 0x2B1A +#define BLE_MESH_UUID_VOLUME_FLOW_VAL 0x2B1B + +/** + * @brief BLE Mesh Device Property referenced Characteristic Type Definitions + */ + +/* Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius. */ +typedef s16_t bt_mesh_temperature_t; + +typedef u16_t bt_mesh_gap_appearance_t; + +/* Mesh Characteristics Type Definitions */ + +/* This characteristic represents an electric current. + * Note: Unit is ampere with a resolution of 0.01. + * Minimum value: 0, maximum value: 655.34; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_electric_current_t; + +/* The Time Exponential 8 characteristic is used to represent a measure of period of + * time in seconds. + * Note: The time duration is given by the value 1.1^(N-64) in seconds, with N being + * the raw 8-bit value; + * Minimum value: 0.0, maximum value: 73216705; + * A raw value of 0x00 represents 0 seconds, and a raw value of 0xFF represents + * the total life of the device. + */ +typedef u8_t bt_mesh_time_exponential_8_t; + +/* The Voltage characteristic is used to represent a measure of positive electric + * potential difference in units of volts. + * Note: Unit is volt with a resolution of 1/64V; + * Minimum value: 0.0, maximum value: 1022.0; + * A value of 0xFFFF represents 'value is not known'. The minimum representable + * value represents the minimum value or lower, the maximum representable value + * represents the maximum value or higher. + */ +typedef u16_t bt_mesh_voltage_t; + +/* This characteristic aggregates the Electric Current characteristic and instance of + * the Time Exponential 8 characteristic. + */ +typedef struct __packed average_current { + bt_mesh_electric_current_t electric_current; + bt_mesh_time_exponential_8_t sensing_duration; +} bt_mesh_average_current_t; + +/* This characteristic aggregates the Voltage characteristic and instance of the Time + * Exponential 8 characateristic. + */ +typedef struct __packed average_voltage { + bt_mesh_voltage_t voltage; + bt_mesh_time_exponential_8_t sensing_duration; +} bt_mesh_average_voltage_t; + +/* The Boolean characteristic defines the predefined Boolean values as an enumeration. + * Key | Value + * 0 | False + * 1 | True + * 2 to 255 | Prohibited + */ +typedef u8_t bt_mesh_boolean_t; + +/* The Chromatic Distance From Planckian characteristic represents a distance of a + * chromaticity coordinate from the Planckian locus in the (u',2/3 v') diagram as + * defined by ANSI standard C78.377-2008. The distance is positive if the chromaticity + * coordinate is located above the Planckian locus (i.e. has as higher y value than the + * Planckian), and negative if it is located below. The distance is only valid within + * the range from -0.05 to 0.05. + * Note: Unit is unitless with a resolution of 0.00001; + * Minimum value: -0.05, maximum value: 0.05; + * A value of 0xFFFF represents 'value is not known'; + * A value of 0xFFFE represents 'value is not valid'. + */ +typedef s16_t bt_mesh_chromatic_distance_from_planckian_t; + +/* This characteristic represents a chromaticity coordinate in a color diagram such as + * the CIE1931 diagram. It can represent an x or y coordinate. + * Note: Unit is unitless with a resolution of 1/65535; + * Minimum value: 0, maximum value: 1.0. + */ +typedef u16_t bt_mesh_chromaticity_coordinate_t; + +/* This characteristic represents a chromaticity coordinate as a tuple with an x and + * y coordinate. + */ +typedef struct __packed chromaticity_coordinates { + bt_mesh_chromaticity_coordinate_t chromaticity_x_coordinate; + bt_mesh_chromaticity_coordinate_t chromaticity_y_coordinate; +} bt_mesh_chromaticity_coordinates_t; + +/* The Correlated Color Temperature characteristic is used to represent correlated color + * temperature in a range from 800 to 65534 Kelvin with a resolution of 1 Kelvin. + * Note: Unit is Kelvin with a resolution of 1; + * Minimum value: 800, maximum value: 65534; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_correlated_color_temperature_t; + +/* The Chromaticity In CCT And Duv Values characteristic is a composite characteristic + * consisting of the Correlated Color Temperature characteristic and the Chromatic + * Distance From Planckian characteristic. + */ +typedef struct __packed chromaticity_in_cct_and_duv_values { + bt_mesh_correlated_color_temperature_t correlated_color_temperature; + bt_mesh_chromatic_distance_from_planckian_t chromaticity_distance_from_planckian; +} bt_mesh_chromaticity_in_cct_and_duv_values_t; + +/* The Chromaticity Tolerance characteristic is a tolerance of a tuple of chromaticity + * values represented as a value of a radius of a circle in the CIE 1976 (u',v') diagram; + * value corresponding to the 3-sigma values of the expected chromaticity deviations. + * Note: Unit is unitless with a resolution of 0.0001; + * Minimum value: 0, maximum value: 0.0255. + */ +typedef u8_t bt_mesh_chromaticity_tolerance_t; + +/* The CIE 13.3-1995 Color Rendering Index characteristic is a color rendition index value + * for a color patch as calculated in accordance with the CIE 13.3-1995 standard. + * Note: Unit is unitless with a resolution of 1; + * Minimum value: -128, maximum value: 100. + */ +typedef s8_t bt_mesh_cie_13_3_1995_color_rendering_index_t; + +/* The Coefficient characteristic is used to represent a general coefficient value. */ +typedef float bt_mesh_coefficient_t; + +/* The Count 16 characteristic is used to represent a general count value. + * Note: Unit is unitless with a resolution of 1; + * Minimum value: 0, maximum value 65534; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_count_16_t; + +/* The Count 24 characteristic is used to represent a general count value. + * Note: Unit is unitless with a resolution of 1; + * Minimum value: 0, maximum value 16777214; + * A value of 0xFFFFFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_count_24_t[3]; + +/* This characteristic represents a country or dependent areas in accordance with + * the ISO 3166-1 Numeric standard. + * Note: Unit is unitless with a resolution of 1; + * Minimum value: 0, maximum value: 4095; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_country_code_t; + +/* Date as days elapsed since the Epoch (Jan 1, 1970) in the Coordinated Universal + * Time (UTC) time zone. + * Note: Unit is a day with a resolution of 1; + * Minimum value: 1, maximum value: 16777214; + * A value of 0x000000 represents 'value is not known'. + */ +typedef u8_t bt_mesh_date_utc_t[3]; + +/* This characteristic aggregates two instances of the Electric Current characteristic + * to represent a range of Electric Current values. + */ +typedef struct __packed electric_current_range { + bt_mesh_electric_current_t minimum_electric_current_value; + bt_mesh_electric_current_t maximum_electric_current_value; +} bt_mesh_electric_current_range_t; + +/* This characteristic aggregates three instances of the Electric Current characteristic + * to represent a specification of electric current values. + */ +typedef struct __packed electric_current_specification { + bt_mesh_electric_current_t minimum_electric_current_value; + bt_mesh_electric_current_t typical_electric_current_value; + bt_mesh_electric_current_t maximum_electric_current_value; +} bt_mesh_electric_current_specification_t; + +/* This characteristic aggregates four instances of the Electric Current characteristic + * with a Sensing Duration to represent a set of statistical electric current values. + */ +typedef struct __packed electric_current_statistics { + bt_mesh_electric_current_t average_electric_current_value; + bt_mesh_electric_current_t standard_electric_current_value; + bt_mesh_electric_current_t minimum_electric_current_value; + bt_mesh_electric_current_t maximum_electric_current_value; + bt_mesh_time_exponential_8_t sensing_duration; +} bt_mesh_electric_current_statistics_t; + +/* The Energy characteristic is used to represent a measure of energy in units of + * kilowatt hours. + * Note: Unit is kilowatt-hour with a resolution of 1; + * Minimum value: 0, maximum value: 16777214; + * A value of 0xFFFFFF represents ‘value is not known’. + */ +typedef u8_t bt_mesh_energy_t[3]; + +/* The Time Decihour 8 characteristic is used to represent a period of time in + * tenths of an hour. + * Note: Unit is hour with a resolution of 0.1; + * Minimum value: 0.0, maximum value: 24.0; + * A value of 0xFF represents 'value is not known'. All other values are Prohibited. + */ +typedef u8_t bt_mesh_time_decihour_8_t; + +/* This characteristic aggregates the Energy characteristic, and two instances of + * the Time Decihour 8 characteristic, to represent energy use in a period of day. + */ +typedef struct __packed energy_in_a_period_of_day { + bt_mesh_energy_t energy_value; + bt_mesh_time_decihour_8_t start_time; + bt_mesh_time_decihour_8_t end_time; +} bt_mesh_energy_in_a_period_of_day_t; + +/* The Time Second 16 characteristic is used to represent a period of time with a + * unit of 1 second. + * Note: Unit is second with a resolution of 1; + * Minimum value: 0, maximum value: 65534; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_time_second_16_t; + +/* This characteristic aggregates the Count 16 characteristic, two instances of the + * Time Decihour 8 characteristic and an instance of the Sensing Duration characteristic, + * to represent statistical values of events. + */ +typedef struct __packed event_statistics { + bt_mesh_count_16_t number_of_events; + bt_mesh_time_second_16_t average_event_duration; + bt_mesh_time_exponential_8_t time_elapsed_since_last_event; + bt_mesh_time_exponential_8_t sensing_duration; +} bt_mesh_event_statistics_t; + +/* The Fixed String 16 characteristic represents a 16-octet UTF-8 string. */ +typedef char bt_mesh_fixed_string_16_t[16]; + +/* The Fixed String 24 characteristic represents a 24-octet UTF-8 string. */ +typedef char bt_mesh_fixed_string_24_t[24]; + +/* The Fixed String 36 characteristic represents a 36-octet UTF-8 string. */ +typedef char bt_mesh_fixed_string_36_t[36]; + +/* The Fixed String 8 characteristic represents an 8-octet UTF-8 string. */ +typedef char bt_mesh_fixed_string_8_t[8]; + +/* The Generic Level characteristic represents a general level value of a + * setting of a device. + * Note: Unit is unitless with a resolution of 1; + * Minimum value: 0, maximum value: 65535. + */ +typedef u16_t bt_mesh_generic_level_t; + +/* The Global Trade Item Number characteristic represents an identifier as + * issued by GS1 General Specifications, which may consist up to 14 digits, + * and is here represented as a 48-bit unsigned integer. + */ +typedef u8_t bt_mesh_global_trade_item_number_t[6]; + +/* The Illuminance characteristic is used to represent a measure of illuminance + * in units of lux. + * Note: Unit is lux with a resolution of 0.01; + * Minimum value: 0, maximum value: 167772.14; + * A value of 0xFFFFFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_illuminance_t[3]; + +/* The Luminous Efficacy characteristic is used to represent a measure of luminous + * efficacy in units of lumen per watt. + * Note: Unit is lumen per watt with a resolution of 0.1; + * Minimum value: 0, maximum value: 1800; + * A value of 0xFFFF represents 'value is not known'. All other values are Prohibited. + */ +typedef u16_t bt_mesh_luminous_efficacy_t; + +/* The Luminous Energy characteristic is used to represent a measure of luminous + * energy in units of lumen hour. + * Note: Unit is lumen hour with a resolution of 1000; + * Minimum value: 0, maximum value: 16777214000; + * A value of 0xFFFFFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_luminous_energy_t[3]; + +/* The Luminous Exposure characteristic is used to represent a measure of luminous + * exposure in units of lux-hour. + * Note: Unit is lux hour with a resolution of 1000; + * Minimum value: 0, maximum value: 16777214000; + * A value of 0xFFFFFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_luminous_exposure_t[3]; + +/* The Luminous Flux characteristic is used to represent a measure of luminous flux + * in units of lumen. + * Note: Unit is lumen with a resolution of 1; + * Minimum value: 0, maximum value: 65534; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_luminous_flux_t; + +/* This characteristic aggregates two instances of the Luminous Flux characteristic + * to represent a luminous flux range. + */ +typedef struct __packed luminous_flux_range { + bt_mesh_luminous_flux_t minimum_luminous_flux; + bt_mesh_luminous_flux_t maximum_luminous_flux; +} bt_mesh_luminous_flux_range_t; + +/* The Luminous Intensity characteristic is used to represent a luminous intensity of + * a beam of light in units of candela. + * Note: Unit is candela with a resolution of 1; + * Minimum value: 0, maximum value: 65534; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_luminous_intensity_t; + +/* The Mass Flow characteristic is used to represent a flow of mass. + * Note: Unit is gram/second with a resolution of 1; + * Minimum value: 0, maximum value: 65534; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_mass_flow_t; + +/* The Mesh Provisioning Data In characteristic can be written to send a Proxy PDU + * message containing Provisioning PDU to the Provisioning Server. + */ +struct mesh_provisioning_data_in { + +}; + +/* The Mesh Provisioning Data Out characteristic can be notified to send a Proxy PDU + * message containing Provisioning PDU from a Provisioning Server to a Provisioning Client. + */ +struct mesh_provisioning_data_out { + +}; + +/* The Mesh Proxy Data In characteristic is used by the client to send Proxy PDUs to + * the server. + */ +struct mesh_proxy_data_in { + +}; + +/* The Mesh Proxy Data Out characteristic is used by the server to send Proxy PDUs to + * the client. + */ +struct mesh_proxy_data_out { + +}; + +/* The Perceived Lightness characteristic is used to represent the perceived lightness + * of a light. + * Note: Unit is unitless with a resolution of 1; + * Minimum value: 0, maximum value: 65535. + */ +typedef u16_t bt_mesh_perceived_lightness_t; + +/* The Percentage 8 characteristic is used to represent a measure of percentage. + * Note: Unit is a percentage with a resolution of 0.5; + * Minimum value: 0, maximum value: 100; + * A value of 0xFF represents 'value is not known'. All other values are Prohibited. + */ +typedef u8_t bt_mesh_percentage_8_t; + +/* The Power characteristic is used to represent a measure of power in units of watts. + * Note: Unit is watt with a resolution of 0.1; + * Minimum value: 0, maximum value: 1677721.4; + * A value of 0xFFFFFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_power_t[3]; + +/* This characteristic aggregates three instances of the Power characteristic to + * represent a specification of Power values. + */ +typedef struct __packed power_specification { + bt_mesh_power_t minimum_power_value; + bt_mesh_power_t typical_power_value; + bt_mesh_power_t maximum_power_value; +} bt_mesh_power_specification_t; + +/* This characteristic aggregates the Percentage 8 characteristic and two instances of + * the Electric Current characteristic to represent a relative value in an electric + * current range. + */ +typedef struct __packed relative_runtime_in_a_current_range { + bt_mesh_percentage_8_t relative_runtime_value; + bt_mesh_electric_current_t minimum_current; + bt_mesh_electric_current_t maximum_current; +} bt_mesh_relative_runtime_in_a_current_range_t; + +/* This characteristic aggregates the Percentage 8 characteristic and two instances of + * the Generic Level characteristic to represent a runtime in a generic level range. + */ +typedef struct __packed relative_runtime_in_a_generic_level_range { + bt_mesh_percentage_8_t relative_value; + bt_mesh_generic_level_t minimum_generic_level; + bt_mesh_generic_level_t maximum_generic_level; +} bt_mesh_relative_runtime_in_a_generic_level_range_t; + +/* This characteristic aggregates the Percentage 8 characteristic, and two instances of + * the Time Decihour 8 characteristic. + */ +typedef struct __packed relative_value_in_a_period_of_day { + bt_mesh_percentage_8_t relative_value; + bt_mesh_time_decihour_8_t start_time; + bt_mesh_time_decihour_8_t end_time; +} bt_mesh_relative_value_in_a_period_of_day_t; + +/* This characteristic aggregates the Percentage 8 characteristic, and two instances of + * the Temperature characteristic. + */ +typedef struct __packed relative_value_in_a_temperature_range { + bt_mesh_percentage_8_t relative_value; + bt_mesh_temperature_t minimum_temperature_value; + bt_mesh_temperature_t maximum_temperature_value; +} bt_mesh_relative_value_in_a_temperature_range_t; + +/* This characteristic aggregates the Percentage 8 characteristic and two instances of + * the Voltage characteristic to represent a relative value in a voltage range. + */ +typedef struct __packed relative_value_in_a_voltage_range { + bt_mesh_percentage_8_t relative_value; + bt_mesh_voltage_t minimum_voltage; + bt_mesh_voltage_t maximum_voltage; +} bt_mesh_relative_value_in_a_voltage_range_t; + +/* This characteristic aggregates the Percentage 8 characteristic and two instances of + * the Illuminance characteristic to represent a relative value in a illuminance range. + */ +typedef struct __packed relative_value_in_an_illuminance_range { + bt_mesh_percentage_8_t relative_value; + bt_mesh_illuminance_t minimum_illuminance; + bt_mesh_illuminance_t maximum_illuminance; +} bt_mesh_relative_value_in_an_illuminance_range_t; + +/* The Temperature 8 characteristic is used to represent a measure of temperature with + * a unit of 0.5 degree Celsius. + * Note: Unit is degree Celsius with a resolution of 0.5; + * Minimum value: -64.0, maximum value: 63.5; + * A value of 0xFF represents 'value is not known'. + */ +typedef s8_t bt_mesh_temperature_8_t; + +/* This characteristic aggregates the Temperature 8 characteristic, and two instances + * of the Time Decihour 8 characteristic, to represent a temperature value in a period + * of day. + */ +typedef struct __packed temperature_8_in_a_period_of_day { + bt_mesh_temperature_8_t temperature; + bt_mesh_time_decihour_8_t start_time; + bt_mesh_time_decihour_8_t end_time; +} bt_mesh_temperature_8_in_a_period_of_day_t; + +/* This characteristic aggregates four instances of the Temperature 8 characteristic, + * and one instance of the Time Exponential 8 characteristic. + */ +typedef struct __packed temperature_8_statistics { + bt_mesh_temperature_8_t average; + bt_mesh_temperature_8_t standard_deviation_value; + bt_mesh_temperature_8_t minimum_value; + bt_mesh_temperature_8_t maximum_value; + bt_mesh_time_exponential_8_t sensing_duration; +} bt_mesh_temperature_8_statistics_t; + +/* This characteristic aggregates two instances of the Temperature characteristic to + * represent a temperature range. + */ +typedef struct __packed temperature_range { + bt_mesh_temperature_t minimum_temperature; + bt_mesh_temperature_t maximum_temperature; +} bt_mesh_temperature_range_t; + +/* This characteristic aggregates four instances of the Temperature characteristic, + * and one instance of the Time Exponential 8 characteristic. + */ +typedef struct __packed temperature_statistics { + bt_mesh_temperature_t average_temperature; + bt_mesh_temperature_t standard_deviation_temperature; + bt_mesh_temperature_t minimum_temperature; + bt_mesh_temperature_t maximum_temperature; + bt_mesh_time_exponential_8_t sensing_duration; +} bt_mesh_temperature_statistics_t; + +/* The Time Hour 24 characteristic is used to represent a period of time in hours. + * Note: Unit is hour with a resolution of 1; + * Minimum value: 0, maximum value: 16777214; + * A value of 0xFFFFFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_time_hour_24_t[3]; + +/* The Time Millisecond 24 characteristic is used to represent a period of time with + * a resolution of 1 millisecond. + * Note: Unit is second with a resolution of 0.001; + * Minimum value: 0, maximum value: 16777.214; + * A value of 0xFFFFFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_time_millisecond_24_t[3]; + +/* The Time Second 8 characteristic is used to represent a period of time with a unit + * of 1 second. + * Note: Unit is second with a resolution of 1; + * Minimum value: 0, maximum value: 254; + * A value of 0xFF represents 'value is not known'. + */ +typedef u8_t bt_mesh_time_second_8_t; + +/* This characteristic aggregates three instances of the Voltage characteristic to + * represent a specification of voltage values. + */ +typedef struct __packed voltage_specification { + bt_mesh_voltage_t minimum_voltage_value; + bt_mesh_voltage_t typical_voltage_value; + bt_mesh_voltage_t maximum_voltage_value; +} bt_mesh_voltage_specification_t; + +/* This characteristic aggregates four instances of the Voltage characteristic and an + * instance of the Time Exponential 8 characteristic to represent a set of statistical + * voltage values over a period of time. + */ +typedef struct __packed voltage_statistics { + bt_mesh_voltage_t average_voltage_value; + bt_mesh_voltage_t standard_deviation_voltage_value; + bt_mesh_voltage_t minimum_voltage_value; + bt_mesh_voltage_t maximum_voltage_value; + bt_mesh_time_exponential_8_t sensing_duration; +} bt_mesh_voltage_statistics_t; + +/* The Volume Flow characteristic is used to represent a flow of a general volume such + * as a volume of material or gas. + * Note: Unit is liter/second with a resolution of 0.001 (1 milliliter); + * Minimum value: 0, maximum value: 65534; + * A value of 0xFFFF represents 'value is not known'. + */ +typedef u16_t bt_mesh_volume_flow_t; + +/* Mesh Device Property related function */ + +u8_t bt_mesh_get_dev_prop_len(u16_t prop_id); + +#endif /* _DEVICE_PROPERTY_H_ */ \ No newline at end of file diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/generic_server.h b/components/bt/esp_ble_mesh/mesh_models/server/include/generic_server.h new file mode 100644 index 000000000..a1465aba7 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/generic_server.h @@ -0,0 +1,374 @@ +/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _GENERIC_SERVER_H_ +#define _GENERIC_SERVER_H_ + +#include "server_common.h" + +struct bt_mesh_gen_onoff_state { + u8_t onoff; + u8_t target_onoff; +}; + +struct bt_mesh_gen_onoff_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_onoff_state state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; +}; + +struct bt_mesh_gen_level_state { + s16_t level; + s16_t target_level; + + s16_t last_level; + s32_t last_delta; + + bool move_start; + bool positive; +}; + +struct bt_mesh_gen_level_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_level_state state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_level; +}; + +struct bt_mesh_gen_def_trans_time_state { + u8_t trans_time; +}; + +struct bt_mesh_gen_def_trans_time_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_def_trans_time_state state; +}; + +struct bt_mesh_gen_onpowerup_state { + u8_t onpowerup; +}; + +struct bt_mesh_gen_power_onoff_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_onpowerup_state *state; +}; + +struct bt_mesh_gen_power_onoff_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_onpowerup_state *state; +}; + +struct bt_mesh_gen_power_level_state { + u16_t power_actual; + u16_t target_power_actual; + + u16_t power_last; + u16_t power_default; + + u8_t status_code; + u16_t power_range_min; + u16_t power_range_max; +}; + +struct bt_mesh_gen_power_level_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_power_level_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_level; +}; + +struct bt_mesh_gen_power_level_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_power_level_state *state; +}; + +struct bt_mesh_gen_battery_state { + u32_t battery_level : 8, + time_to_discharge : 24; + u32_t time_to_charge : 24, + battery_flags : 8; +}; + +struct bt_mesh_gen_battery_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_battery_state state; +}; + +struct bt_mesh_gen_location_state { + s32_t global_latitude; + s32_t global_longitude; + s16_t global_altitude; + s16_t local_north; + s16_t local_east; + s16_t local_altitude; + u8_t floor_number; + u16_t uncertainty; +}; + +struct bt_mesh_gen_location_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_location_state *state; +}; + +struct bt_mesh_gen_location_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_gen_location_state *state; +}; + +/** + * According to the hierarchy of Generic Property states (Model Spec section 3.1.8), + * the Manufacturer Properties and Admin Properties may contain multiple Property + * states. User Properties just a collection of which can be accessed. + * + * property_count: Number of the properties contained in the table + * properties: Table of the properties + * + * These variables need to be initialized in the application layer, the precise + * number of the properties should be set and memories used to store the property + * values should be allocated. + */ + +enum bt_mesh_gen_user_prop_access { + USER_ACCESS_PROHIBIT, + USER_ACCESS_READ, + USER_ACCESS_WRITE, + USER_ACCESS_READ_WRITE, +}; + +enum bt_mesh_gen_admin_prop_access { + ADMIN_NOT_USER_PROP, + ADMIN_ACCESS_READ, + ADMIN_ACCESS_WRITE, + ADMIN_ACCESS_READ_WRITE, +}; + +enum bt_mesh_gen_manu_prop_access { + MANU_NOT_USER_PROP, + MANU_ACCESS_READ, +}; + +struct bt_mesh_generic_property { + u16_t id; + u8_t user_access; + u8_t admin_access; + u8_t manu_access; + struct net_buf_simple *val; +}; + +struct bt_mesh_gen_user_prop_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + u8_t property_count; + struct bt_mesh_generic_property *properties; +}; + +struct bt_mesh_gen_admin_prop_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + u8_t property_count; + struct bt_mesh_generic_property *properties; +}; + +struct bt_mesh_gen_manu_prop_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + u8_t property_count; + struct bt_mesh_generic_property *properties; +}; + +struct bt_mesh_gen_client_prop_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + u8_t id_count; + u16_t *property_ids; +}; + +typedef union { + struct { + u8_t onoff; + } gen_onoff_set; + struct { + s16_t level; + } gen_level_set; + struct { + s16_t level; + } gen_delta_set; + struct { + s16_t level; + } gen_move_set; + struct { + u8_t trans_time; + } gen_def_trans_time_set; + struct { + u8_t onpowerup; + } gen_onpowerup_set; + struct { + u16_t power; + } gen_power_level_set; + struct { + u16_t power; + } gen_power_default_set; + struct { + u16_t range_min; + u16_t range_max; + } gen_power_range_set; + struct { + s32_t latitude; + s32_t longitude; + s16_t altitude; + } gen_loc_global_set; + struct { + s16_t north; + s16_t east; + s16_t altitude; + u8_t floor_number; + u16_t uncertainty; + } gen_loc_local_set; + struct { + u16_t id; + struct net_buf_simple *value; + } gen_user_prop_set; + struct { + u16_t id; + u8_t access; + struct net_buf_simple *value; + } gen_admin_prop_set; + struct { + u16_t id; + u8_t access; + } gen_manu_prop_set; +} bt_mesh_gen_server_state_change_t; + +typedef union { + struct { + u16_t id; + } user_property_get; + struct { + u16_t id; + } admin_property_get; + struct { + u16_t id; + } manu_property_get; + struct { + u16_t id; + } client_properties_get; +} bt_mesh_gen_server_recv_get_msg_t; + +typedef union { + struct { + bool op_en; + u8_t onoff; + u8_t tid; + u8_t trans_time; + u8_t delay; + } onoff_set; + struct { + bool op_en; + s16_t level; + u8_t tid; + u8_t trans_time; + u8_t delay; + } level_set; + struct { + bool op_en; + s32_t delta_level; + u8_t tid; + u8_t trans_time; + u8_t delay; + } delta_set; + struct { + bool op_en; + s16_t delta_level; + u8_t tid; + u8_t trans_time; + u8_t delay; + } move_set; + struct { + u8_t trans_time; + } def_trans_time_set; + struct { + u8_t onpowerup; + } onpowerup_set; + struct { + bool op_en; + u16_t power; + u8_t tid; + u8_t trans_time; + u8_t delay; + } power_level_set; + struct { + u16_t power; + } power_default_set; + struct { + u16_t range_min; + u16_t range_max; + } power_range_set; + struct { + s32_t latitude; + s32_t longitude; + s16_t altitude; + } loc_global_set; + struct { + s16_t north; + s16_t east; + s16_t altitude; + u8_t floor_number; + u16_t uncertainty; + } loc_local_set; + struct { + u16_t id; + struct net_buf_simple *value; + } user_property_set; + struct { + u16_t id; + u8_t access; + struct net_buf_simple *value; + } admin_property_set; + struct { + u16_t id; + u8_t access; + } manu_property_set; +} bt_mesh_gen_server_recv_set_msg_t; + +void bt_mesh_generic_server_lock(void); +void bt_mesh_generic_server_unlock(void); + +void gen_onoff_publish(struct bt_mesh_model *model); +void gen_level_publish(struct bt_mesh_model *model); +void gen_onpowerup_publish(struct bt_mesh_model *model); +void gen_power_level_publish(struct bt_mesh_model *model, u16_t opcode); + +int bt_mesh_gen_onoff_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_level_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_def_trans_time_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_power_onoff_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_power_onoff_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_power_level_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_power_level_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_battery_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_location_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_location_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_user_prop_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_admin_prop_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_manu_prop_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_gen_client_prop_srv_init(struct bt_mesh_model *model, bool primary); + +#endif /* _GENERIC_SERVER_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/lighting_server.h b/components/bt/esp_ble_mesh/mesh_models/server/include/lighting_server.h new file mode 100644 index 000000000..9ac112466 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/lighting_server.h @@ -0,0 +1,516 @@ +/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _LIGHTING_SERVER_H_ +#define _LIGHTING_SERVER_H_ + +#include "server_common.h" + +struct bt_mesh_light_lightness_state { + u16_t lightness_linear; + u16_t target_lightness_linear; + + u16_t lightness_actual; + u16_t target_lightness_actual; + + u16_t lightness_last; + u16_t lightness_default; + + u8_t status_code; + u16_t lightness_range_min; + u16_t lightness_range_max; +}; + +struct bt_mesh_light_lightness_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_lightness_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition actual_transition; + struct bt_mesh_state_transition linear_transition; + s32_t tt_delta_lightness_actual; + s32_t tt_delta_lightness_linear; +}; + +struct bt_mesh_light_lightness_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_lightness_state *state; +}; + +struct bt_mesh_light_ctl_state { + u16_t lightness; + u16_t target_lightness; + + u16_t temperature; + u16_t target_temperature; + + s16_t delta_uv; + s16_t target_delta_uv; + + u8_t status_code; + u16_t temperature_range_min; + u16_t temperature_range_max; + + u16_t lightness_default; + u16_t temperature_default; + s16_t delta_uv_default; +}; + +struct bt_mesh_light_ctl_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_ctl_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_lightness; + s32_t tt_delta_temperature; + s32_t tt_delta_delta_uv; +}; + +struct bt_mesh_light_ctl_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_ctl_state *state; +}; + +struct bt_mesh_light_ctl_temp_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_ctl_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_temperature; + s32_t tt_delta_delta_uv; +}; + +struct bt_mesh_light_hsl_state { + u16_t lightness; + u16_t target_lightness; + + u16_t hue; + u16_t target_hue; + + u16_t saturation; + u16_t target_saturation; + + u16_t lightness_default; + u16_t hue_default; + u16_t saturation_default; + + u8_t status_code; + u16_t hue_range_min; + u16_t hue_range_max; + u16_t saturation_range_min; + u16_t saturation_range_max; +}; + +struct bt_mesh_light_hsl_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_hsl_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_lightness; + s32_t tt_delta_hue; + s32_t tt_delta_saturation; +}; + +struct bt_mesh_light_hsl_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_hsl_state *state; +}; + +struct bt_mesh_light_hsl_hue_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_hsl_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_hue; +}; + +struct bt_mesh_light_hsl_sat_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_hsl_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_saturation; +}; + +struct bt_mesh_light_xyl_state { + u16_t lightness; + u16_t target_lightness; + + u16_t x; + u16_t target_x; + + u16_t y; + u16_t target_y; + + u16_t lightness_default; + u16_t x_default; + u16_t y_default; + + u8_t status_code; + u16_t x_range_min; + u16_t x_range_max; + u16_t y_range_min; + u16_t y_range_max; +}; + +struct bt_mesh_light_xyl_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_xyl_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; + s32_t tt_delta_lightness; + s32_t tt_delta_x; + s32_t tt_delta_y; +}; + +struct bt_mesh_light_xyl_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_xyl_state *state; +}; + +struct bt_mesh_light_lc_state { + u32_t mode : 1, /* default 0 */ + occupancy_mode : 1, /* default 1 */ + light_onoff : 1, + target_light_onoff : 1, + occupancy : 1, + ambient_luxlevel : 24; /* 0x000000 ~ 0xFFFFFF */ + + u16_t linear_output; /* 0x0000 ~ 0xFFFF */ +}; + +struct bt_mesh_light_lc_property_state { + u32_t time_occupancy_delay; /* 0x003A */ + u32_t time_fade_on; /* 0x0037 */ + u32_t time_run_on; /* 0x003C */ + u32_t time_fade; /* 0x0036 */ + u32_t time_prolong; /* 0x003B */ + u32_t time_fade_standby_auto; /* 0x0038 */ + u32_t time_fade_standby_manual; /* 0x0039 */ + + u16_t lightness_on; /* 0x002E */ + u16_t lightness_prolong; /* 0x002F */ + u16_t lightness_standby; /* 0x0030 */ + + u16_t ambient_luxlevel_on; /* 0x002B, 0x0000 ~ 0xFFFF */ + u16_t ambient_luxlevel_prolong; /* 0x002C, 0x0000 ~ 0xFFFF */ + u16_t ambient_luxlevel_standby; /* 0x002D, 0x0000 ~ 0xFFFF */ + + float regulator_kiu; /* 0x0033, 0.0 ~ 1000.0, default 250.0 */ + float regulator_kid; /* 0x0032, 0.0 ~ 1000.0, default 25.0 */ + float regulator_kpu; /* 0x0035, 0.0 ~ 1000.0, default 80.0 */ + float regulator_kpd; /* 0x0034, 0.0 ~ 1000.0, default 80.0 */ + s8_t regulator_accuracy; /* 0x0031, 0.0 ~ 100.0, default 2.0 */ + + u32_t set_occupancy_to_1_delay; +}; + +typedef enum { + LC_OFF, + LC_STANDBY, + LC_FADE_ON, + LC_RUN, + LC_FADE, + LC_PROLONG, + LC_FADE_STANDBY_AUTO, + LC_FADE_STANDBY_MANUAL, +} bt_mesh_lc_state; + +struct bt_mesh_light_lc_state_machine { + struct { + u8_t fade_on; + u8_t fade; + u8_t fade_standby_auto; + u8_t fade_standby_manual; + } trans_time; + bt_mesh_lc_state state; + struct k_delayed_work timer; +}; + +struct bt_mesh_light_control { + struct bt_mesh_light_lc_state state; + struct bt_mesh_light_lc_property_state prop_state; + struct bt_mesh_light_lc_state_machine state_machine; +}; + +struct bt_mesh_light_lc_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_control *lc; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; +}; + +struct bt_mesh_light_lc_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_light_control *lc; +}; + +typedef union { + struct { + u16_t lightness; + } lightness_set; + struct { + u16_t lightness; + } lightness_linear_set; + struct { + u16_t lightness; + } lightness_default_set; + struct { + u16_t range_min; + u16_t range_max; + } lightness_range_set; + struct { + u16_t lightness; + u16_t temperature; + s16_t delta_uv; + } ctl_set; + struct { + u16_t temperature; + s16_t delta_uv; + } ctl_temp_set; + struct { + u16_t range_min; + u16_t range_max; + } ctl_temp_range_set; + struct { + u16_t lightness; + u16_t temperature; + s16_t delta_uv; + } ctl_default_set; + struct { + u16_t lightness; + u16_t hue; + u16_t saturation; + } hsl_set; + struct { + u16_t hue; + } hsl_hue_set; + struct { + u16_t saturation; + } hsl_saturation_set; + struct { + u16_t lightness; + u16_t hue; + u16_t saturation; + } hsl_default_set; + struct { + u16_t hue_range_min; + u16_t hue_range_max; + u16_t sat_range_min; + u16_t sat_range_max; + } hsl_range_set; + struct { + u16_t lightness; + u16_t x; + u16_t y; + } xyl_set; + struct { + u16_t lightness; + u16_t x; + u16_t y; + } xyl_default_set; + struct { + u16_t x_range_min; + u16_t x_range_max; + u16_t y_range_min; + u16_t y_range_max; + } xyl_range_set; + struct { + u8_t mode; + } lc_mode_set; + struct { + u8_t mode; + } lc_om_set; + struct { + u8_t onoff; + } lc_light_onoff_set; + struct { + u16_t id; + struct net_buf_simple *value; + } lc_property_set; + struct { + u16_t property_id; + union { + u8_t occupancy; + u32_t set_occupancy_to_1_delay; + u32_t ambient_luxlevel; + } state; + } sensor_status; +} bt_mesh_light_server_state_change_t; + +typedef union { + struct { + u16_t id; + } lc_property_get; +} bt_mesh_light_server_recv_get_msg_t; + +typedef union { + struct { + bool op_en; + u16_t lightness; + u8_t tid; + u8_t trans_time; + u8_t delay; + } lightness_set; + struct { + bool op_en; + u16_t lightness; + u8_t tid; + u8_t trans_time; + u8_t delay; + } lightness_linear_set; + struct { + u16_t lightness; + } lightness_default_set; + struct { + u16_t range_min; + u16_t range_max; + } lightness_range_set; + struct { + bool op_en; + u16_t lightness; + u16_t temperature; + s16_t delta_uv; + u8_t tid; + u8_t trans_time; + u8_t delay; + } ctl_set; + struct { + bool op_en; + u16_t temperature; + s16_t delta_uv; + u8_t tid; + u8_t trans_time; + u8_t delay; + } ctl_temp_set; + struct { + u16_t range_min; + u16_t range_max; + } ctl_temp_range_set; + struct { + u16_t lightness; + u16_t temperature; + s16_t delta_uv; + } ctl_default_set; + struct { + bool op_en; + u16_t lightness; + u16_t hue; + u16_t saturation; + u8_t tid; + u8_t trans_time; + u8_t delay; + } hsl_set; + struct { + bool op_en; + u16_t hue; + u8_t tid; + u8_t trans_time; + u8_t delay; + } hsl_hue_set; + struct { + bool op_en; + u16_t saturation; + u8_t tid; + u8_t trans_time; + u8_t delay; + } hsl_saturation_set; + struct { + u16_t lightness; + u16_t hue; + u16_t saturation; + } hsl_default_set; + struct { + u16_t hue_range_min; + u16_t hue_range_max; + u16_t sat_range_min; + u16_t sat_range_max; + } hsl_range_set; + struct { + bool op_en; + u16_t lightness; + u16_t x; + u16_t y; + u8_t tid; + u8_t trans_time; + u8_t delay; + } xyl_set; + struct { + u16_t lightness; + u16_t x; + u16_t y; + } xyl_default_set; + struct { + u16_t x_range_min; + u16_t x_range_max; + u16_t y_range_min; + u16_t y_range_max; + } xyl_range_set; + struct { + u8_t mode; + } lc_mode_set; + struct { + u8_t mode; + } lc_om_set; + struct { + bool op_en; + u8_t light_onoff; + u8_t tid; + u8_t trans_time; + u8_t delay; + } lc_light_onoff_set; + struct { + u16_t id; + struct net_buf_simple *value; + } lc_property_set; +} bt_mesh_light_server_recv_set_msg_t; + +typedef union { + struct { + struct net_buf_simple *data; + } sensor_status; +} bt_mesh_light_server_recv_status_msg_t; + +void bt_mesh_light_server_lock(void); +void bt_mesh_light_server_unlock(void); + +u8_t *bt_mesh_get_lc_prop_value(struct bt_mesh_model *model, u16_t prop_id); + +void light_lightness_publish(struct bt_mesh_model *model, u16_t opcode); +void light_ctl_publish(struct bt_mesh_model *model, u16_t opcode); +void light_hsl_publish(struct bt_mesh_model *model, u16_t opcode); +void light_xyl_publish(struct bt_mesh_model *model, u16_t opcode); +void light_lc_publish(struct bt_mesh_model *model, u16_t opcode); + +int bt_mesh_light_lightness_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_lightness_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_ctl_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_ctl_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_ctl_temp_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_hsl_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_hsl_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_hsl_hue_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_hsl_sat_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_xyl_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_xyl_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_lc_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_light_lc_setup_srv_init(struct bt_mesh_model *model, bool primary); + +#endif /* _LIGHTING_SERVER_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/sensor_server.h b/components/bt/esp_ble_mesh/mesh_models/server/include/sensor_server.h new file mode 100644 index 000000000..de92a7ad5 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/sensor_server.h @@ -0,0 +1,249 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SENSOR_SERVER_H_ +#define _SENSOR_SERVER_H_ + +#include "server_common.h" + +/* Sensor Property ID related */ +#define INVALID_SENSOR_PROPERTY_ID 0x0000 + +#define SENSOR_PROPERTY_ID_LEN 0x02 + +/* Sensor Descriptor state related */ +#define SENSOR_DESCRIPTOR_LEN 0x08 + +#define SENSOR_UNSPECIFIED_POS_TOLERANCE 0x000 +#define SENSOR_UNSPECIFIED_NEG_TOLERANCE 0x000 + +#define SENSOR_NOT_APPL_MEASURE_PERIOD 0x00 + +#define SENSOR_NOT_APPL_UPDATE_INTERVAL 0x00 + +/* Sensor Setting state related */ +#define INVALID_SENSOR_SETTING_PROPERTY_ID 0x0000 + +#define SENSOR_SETTING_PROPERTY_ID_LEN 0x02 +#define SENSOR_SETTING_ACCESS_LEN 0x01 + +#define SENSOR_SETTING_ACCESS_READ 0x01 +#define SENSOR_SETTING_ACCESS_READ_WRITE 0x03 + +/* Sensor Cadence state related */ +#define SENSOR_DIVISOR_TRIGGER_TYPE_LEN 0x01 +#define SENSOR_STATUS_MIN_INTERVAL_LEN 0x01 + +#define SENSOR_PERIOD_DIVISOR_MAX_VALUE 15 + +#define SENSOR_STATUS_MIN_INTERVAL_MAX 26 + +#define SENSOR_STATUS_TRIGGER_TYPE_CHAR 0 +#define SENSOR_STATUS_TRIGGER_TYPE_UINT16 1 + +#define SENSOR_STATUS_TRIGGER_UINT16_LEN 0x02 + +/* Sensor Data state related */ +#define SENSOR_DATA_FORMAT_A 0x00 +#define SENSOR_DATA_FORMAT_B 0x01 + +#define SENSOR_DATA_FORMAT_A_MPID_LEN 0x02 +#define SENSOR_DATA_FORMAT_B_MPID_LEN 0x03 + +#define SENSOR_DATA_ZERO_LEN 0x7F + +enum bt_mesh_sensor_sample_func { + UNSPECIFIED, + INSTANTANEOUS, + ARITHMETIC_MEAN, + RMS, + MAXIMUM, + MINIMUM, + ACCUMULATED, + COUNT, +}; + +struct sensor_descriptor { + u32_t positive_tolerance : 12, + negative_tolerance : 12, + sample_function : 8; + u8_t measure_period; + u8_t update_interval; +}; + +struct sensor_setting { + u16_t property_id; + u8_t access; + /* Or use union to include all possible types */ + struct net_buf_simple *raw; +}; + +struct sensor_cadence { + u8_t period_divisor : 7, + trigger_type : 1; + struct net_buf_simple *trigger_delta_down; + struct net_buf_simple *trigger_delta_up; + u8_t min_interval; + struct net_buf_simple *fast_cadence_low; + struct net_buf_simple *fast_cadence_high; +}; + +struct sensor_data { + /** + * Format A: The Length field is a 1-based uint4 value (valid range 0x0–0xF, + * representing range of 1 – 16). + * Format B: The Length field is a 1-based uint7 value (valid range 0x0–0x7F, + * representing range of 1 – 127). The value 0x7F represents a + * length of zero. + */ + u8_t format : 1, + length : 7; + struct net_buf_simple *raw_value; +}; + +struct sensor_series_column { + struct net_buf_simple *raw_value_x; + struct net_buf_simple *column_width; + struct net_buf_simple *raw_value_y; +}; + +struct bt_mesh_sensor_state { + u16_t sensor_property_id; + + /* Constant throughout the lifetime of an element */ + struct sensor_descriptor descriptor; + + /* Multiple Sensor Setting states may be present for each sensor. + * The Sensor Setting Property ID values shall be unique for each + * Sensor Property ID that identifies a sensor within an element. + */ + const u8_t setting_count; + struct sensor_setting *settings; + + /* The Sensor Cadence state may be not supported by sensors based + * on device properties referencing "non-scalar characteristics" + * such as "histograms" or "composite characteristics". + */ + struct sensor_cadence *cadence; + + struct sensor_data sensor_data; + + /* Values measured by sensors may be organized as arrays (and + * represented as series of columns, such as histograms). + * 1. The Sensor Raw Value X field has a size and representation + * defined by the Sensor Property ID and represents the left + * corner of the column on the X axis. + * 2. The Sensor Column Width field has a size and representation + * defined by the Sensor Property ID and represents the width + * of the column on the X axis. + * 3. The Sensor Raw Value Y field has a size and representation + * defined by the Sensor Property ID and represents the height + * of the column on the Y axis. + * Note: Values outside the bins defined by a Sensor Property are + * not included. For example, if the histogram is defined as 3 bins + * representing “lamp operating hours in a given temperature range” + * and the bins are [40,60), [60, 80), and [80,100], then any hours + * outside that [40, 100] range would not be included. + */ + struct sensor_series_column series_column; +}; + +/* 1. Multiple instances of the Sensor states may be present within the + * same model, provided that each instance has a unique value of the + * Sensor Property ID to allow the instances to be differentiated. + * 2. Note: The number of sensors within a multisensor is limited by the + * size of the message payload for the Sensor Descriptor Status message. + * A single Sensor Descriptor may be sent using a single Unsegmented + * Access message. Using Segmentation and Reassembly (SAR), up to 38 + * Sensor Descriptor states may be sent. + */ + +struct bt_mesh_sensor_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + const u8_t state_count; + struct bt_mesh_sensor_state *states; +}; + +struct bt_mesh_sensor_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + const u8_t state_count; + struct bt_mesh_sensor_state *states; +}; + +typedef union { + struct { + u16_t id; + u8_t period_divisor : 7, + trigger_type : 1; + struct net_buf_simple *trigger_delta_down; + struct net_buf_simple *trigger_delta_up; + u8_t min_interval; + struct net_buf_simple *fast_cadence_low; + struct net_buf_simple *fast_cadence_high; + } sensor_cadence_set; + struct { + u16_t id; + u16_t setting_id; + struct net_buf_simple *value; + } sensor_setting_set; +} bt_mesh_sensor_server_state_change_t; + +typedef union { + struct { + bool op_en; + u16_t id; + } sensor_descriptor_get; + struct { + u16_t id; + } sensor_cadence_get; + struct { + u16_t id; + } sensor_settings_get; + struct { + u16_t id; + u16_t setting_id; + } sensor_setting_get; + struct { + bool op_en; + u16_t id; + } sensor_get; + struct { + u16_t id; + struct net_buf_simple *raw_x; + } sensor_column_get; + struct { + bool op_en; + u16_t id; + struct net_buf_simple *raw; + } sensor_series_get; +} bt_mesh_sensor_server_recv_get_msg_t; + +typedef union { + struct { + u16_t id; + struct net_buf_simple *cadence; + } sensor_cadence_set; + struct { + u16_t id; + u16_t setting_id; + struct net_buf_simple *raw; + } sensor_setting_set; +} bt_mesh_sensor_server_recv_set_msg_t; + +int bt_mesh_sensor_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_sensor_setup_srv_init(struct bt_mesh_model *model, bool primary); + +#endif /* _SENSOR_SERVER_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/server_common.h b/components/bt/esp_ble_mesh/mesh_models/server/include/server_common.h new file mode 100644 index 000000000..d1a313ee7 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/server_common.h @@ -0,0 +1,128 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SERVER_COMMON_H_ +#define _SERVER_COMMON_H_ + +#include +#include + +#include "mesh_buf.h" +#include "mesh_access.h" +#include "mesh_kernel.h" + +#define BLE_MESH_SERVER_RSP_MAX_LEN 384 + +#define BLE_MESH_SERVER_TRANS_MIC_SIZE 4 + +#define BLE_MESH_CHECK_SEND_STATUS(_func) do { \ + int __status = (_func); \ + if (__status) { \ + BT_ERR("%s, Send failed, err %d", __func__, __status); \ + } \ + } while(0); + +#define BLE_MESH_STATE_OFF 0x00 +#define BLE_MESH_STATE_ON 0x01 +#define BLE_MESH_STATE_RESTORE 0x02 + +/* Following 4 values are as per Mesh Model specification */ +#define BLE_MESH_LIGHTNESS_MIN 0x0001 +#define BLE_MESH_LIGHTNESS_MAX 0xFFFF +#define BLE_MESH_TEMPERATURE_MIN 0x0320 +#define BLE_MESH_TEMPERATURE_MAX 0x4E20 +#define BLE_MESH_TEMPERATURE_UNKNOWN 0xFFFF + +/* Refer 7.2 of Mesh Model Specification */ +#define BLE_MESH_RANGE_UPDATE_SUCCESS 0x00 +#define BLE_MESH_CANNOT_SET_RANGE_MIN 0x01 +#define BLE_MESH_CANNOT_SET_RANGE_MAX 0x02 + +#define BLE_MESH_UNKNOWN_REMAIN_TIME 0x3F +#define BLE_MESH_DEVICE_SPECIFIC_RESOLUTION 10 + +#define BLE_MESH_INVALID_DEVICE_PROPERTY_ID 0x0000 + +enum { + BLE_MESH_TRANS_TIMER_START, /* Proper transition timer has been started */ + BLE_MESH_TRANS_FLAG_MAX, +}; + +struct bt_mesh_state_transition { + bool just_started; + + u8_t trans_time; + u8_t remain_time; + u8_t delay; + u32_t quo_tt; + u32_t counter; + u32_t total_duration; + s64_t start_timestamp; + + BLE_MESH_ATOMIC_DEFINE(flag, BLE_MESH_TRANS_FLAG_MAX); + struct k_delayed_work timer; +}; + +struct bt_mesh_last_msg_info { + u8_t tid; + u16_t src; + u16_t dst; + s64_t timestamp; +}; + +#define BLE_MESH_SERVER_RSP_BY_APP 0 +#define BLE_MESH_SERVER_AUTO_RSP 1 + +struct bt_mesh_server_rsp_ctrl { + /** + * @brief BLE Mesh Server Response Option + * 1. If get_auto_rsp is set to BLE_MESH_SERVER_RSP_BY_APP, then the response + * of Client Get messages need to be replied by the application; + * 2. If get_auto_rsp is set to BLE_MESH_SERVER_AUTO_RSP, then the response + * of Client Get messages will be replied by the server models; + * 3. If set_auto_rsp is set to BLE_MESH_SERVER_RSP_BY_APP, then the response + * of Client Set messages need to be replied by the application; + * 4. If set_auto_rsp is set to BLE_MESH_SERVER_AUTO_RSP, then the response + * of Client Set messages will be replied by the server models; + * 5. If status_auto_rsp is set to BLE_MESH_SERVER_RSP_BY_APP, then the response + * of Server Status messages need to be replied by the application; + * 6. If status_auto_rsp is set to BLE_MESH_SERVER_AUTO_RSP, then the response + * of Server status messages will be replied by the server models; + */ + u8_t get_auto_rsp : 1, /* Response for Client Get messages */ + set_auto_rsp : 1, /* Response for Client Set messages */ + status_auto_rsp : 1; /* Response for Server Status messages */ +}; + +u8_t bt_mesh_get_default_trans_time(struct bt_mesh_model *model); + +int bt_mesh_get_light_lc_trans_time(struct bt_mesh_model *model, u8_t *trans_time); + +int bt_mesh_server_get_optional(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf, + u8_t *trans_time, u8_t *delay, + bool *optional); + +void bt_mesh_server_alloc_ctx(struct k_work *work); + +bool bt_mesh_is_server_recv_last_msg(struct bt_mesh_last_msg_info *last, + u8_t tid, u16_t src, u16_t dst, s64_t *now); + +void bt_mesh_server_update_last_msg(struct bt_mesh_last_msg_info *last, + u8_t tid, u16_t src, u16_t dst, s64_t *now); + +struct net_buf_simple *bt_mesh_server_get_pub_msg(struct bt_mesh_model *model, u16_t msg_len); + +#endif /* _SERVER_COMMON_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/state_binding.h b/components/bt/esp_ble_mesh/mesh_models/server/include/state_binding.h new file mode 100644 index 000000000..2d75ff6c9 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/state_binding.h @@ -0,0 +1,92 @@ +/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _STATE_BINDING_H_ +#define _STATE_BINDING_H_ + +typedef enum { + GENERIC_ONOFF_STATE, + GENERIC_LEVEL_STATE, + GENERIC_ONPOWERUP_STATE, + GENERIC_POWER_ACTUAL_STATE, + LIGHT_LIGHTNESS_ACTUAL_STATE, + LIGHT_LIGHTNESS_LINEAR_STATE, + LIGHT_CTL_LIGHTNESS_STATE, + LIGHT_CTL_TEMP_DELTA_UV_STATE, + LIGHT_HSL_LIGHTNESS_STATE, + LIGHT_HSL_HUE_STATE, + LIGHT_HSL_SATURATION_STATE, + LIGHT_XYL_LIGHTNESS_STATE, + LIGHT_LC_LIGHT_ONOFF_STATE, + BIND_STATE_MAX, +} bt_mesh_server_state_type_t; + +typedef union { + struct { + u8_t onoff; + } gen_onoff; + struct { + s16_t level; + } gen_level; + struct { + u8_t onpowerup; + } gen_onpowerup; + struct { + u16_t power; + } gen_power_actual; + struct { + u16_t lightness; + } light_lightness_actual; + struct { + u16_t lightness; + } light_lightness_linear; + struct { + u16_t lightness; + } light_ctl_lightness; + struct { + u16_t temperature; + s16_t delta_uv; + } light_ctl_temp_delta_uv; + struct { + u16_t lightness; + } light_hsl_lightness; + struct { + u16_t hue; + } light_hsl_hue; + struct { + u16_t saturation; + } light_hsl_saturation; + struct { + u16_t lightness; + } light_xyl_lightness; + struct { + u8_t onoff; + } light_lc_light_onoff; +} bt_mesh_server_state_value_t; + +u16_t bt_mesh_convert_lightness_actual_to_linear(u16_t actual); + +u16_t bt_mesh_convert_lightness_linear_to_actual(u16_t linear); + +s16_t bt_mesh_convert_temperature_to_gen_level(u16_t temp, u16_t min, u16_t max); + +u16_t bt_mesh_covert_gen_level_to_temperature(s16_t level, u16_t min, u16_t max); + +s16_t bt_mesh_convert_hue_to_level(u16_t hue); + +u16_t bt_mesh_convert_level_to_hue(s16_t level); + +s16_t bt_mesh_convert_saturation_to_level(u16_t saturation); + +u16_t bt_mesh_convert_level_to_saturation(s16_t level); + +int bt_mesh_update_binding_state(struct bt_mesh_model *model, + bt_mesh_server_state_type_t type, + bt_mesh_server_state_value_t *value); + +#endif /* _STATE_BINDING_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/state_transition.h b/components/bt/esp_ble_mesh/mesh_models/server/include/state_transition.h new file mode 100644 index 000000000..e9a833572 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/state_transition.h @@ -0,0 +1,91 @@ +/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _STATE_TRANSITION_H_ +#define _STATE_TRANSITION_H_ + +#include "server_common.h" +#include "generic_server.h" +#include "lighting_server.h" +#include "time_scene_server.h" + +void bt_mesh_server_calc_remain_time(struct bt_mesh_state_transition *transition); + +/* APIs used to get server model transtion time values */ + +void generic_onoff_tt_values(struct bt_mesh_gen_onoff_srv *srv, + u8_t trans_time, u8_t delay); + +void generic_level_tt_values(struct bt_mesh_gen_level_srv *srv, + u8_t trans_time, u8_t delay); + +void generic_power_level_tt_values(struct bt_mesh_gen_power_level_srv *srv, + u8_t trans_time, u8_t delay); + +void light_lightness_actual_tt_values(struct bt_mesh_light_lightness_srv *srv, + u8_t trans_time, u8_t delay); + +void light_lightness_linear_tt_values(struct bt_mesh_light_lightness_srv *srv, + u8_t trans_time, u8_t delay); + +void light_ctl_tt_values(struct bt_mesh_light_ctl_srv *srv, + u8_t trans_time, u8_t delay); + +void light_ctl_temp_tt_values(struct bt_mesh_light_ctl_temp_srv *srv, + u8_t trans_time, u8_t delay); + +void light_hsl_tt_values(struct bt_mesh_light_hsl_srv *srv, + u8_t trans_time, u8_t delay); + +void light_hsl_hue_tt_values(struct bt_mesh_light_hsl_hue_srv *srv, + u8_t trans_time, u8_t delay); + +void light_hsl_sat_tt_values(struct bt_mesh_light_hsl_sat_srv *srv, + u8_t trans_time, u8_t delay); + +void light_xyl_tt_values(struct bt_mesh_light_xyl_srv *srv, + u8_t trans_time, u8_t delay); + +void light_lc_tt_values(struct bt_mesh_light_lc_srv *srv, + u8_t trans_time, u8_t delay); + +void scene_tt_values(struct bt_mesh_scene_srv *srv, u8_t trans_time, u8_t delay); + +/* Server model transtion timer handlers */ + +void generic_onoff_work_handler(struct k_work *work); + +void generic_level_work_handler(struct k_work *work); + +void generic_power_level_work_handler(struct k_work *work); + +void light_lightness_actual_work_handler(struct k_work *work); + +void light_lightness_linear_work_handler(struct k_work *work); + +void light_ctl_work_handler(struct k_work *work); + +void light_ctl_temp_work_handler(struct k_work *work); + +void light_hsl_work_handler(struct k_work *work); + +void light_hsl_hue_work_handler(struct k_work *work); + +void light_hsl_sat_work_handler(struct k_work *work); + +void light_xyl_work_handler(struct k_work *work); + +void light_lc_work_handler(struct k_work *work); + +void scene_recall_work_handler(struct k_work *work); + +void bt_mesh_server_stop_transition(struct bt_mesh_state_transition *transition); + +void bt_mesh_server_start_transition(struct bt_mesh_state_transition *transition); + +#endif /* _STATE_TRANSITION_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/include/time_scene_server.h b/components/bt/esp_ble_mesh/mesh_models/server/include/time_scene_server.h new file mode 100644 index 000000000..846677699 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/time_scene_server.h @@ -0,0 +1,393 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _TIME_SCENE_SERVER_H_ +#define _TIME_SCENE_SERVER_H_ + +#include "mesh_slist.h" +#include "mesh_kernel.h" +#include "server_common.h" + +/** + * 1. Mesh defines times based on International Atomic Time (TAI). The base + * representation of times is the number of seconds after 00:00:00 TAI + * on 2000-01-01 (that is, 1999-12-31 T23:59:28 UTC). + * 2. UTC: Coordinated Universal Time. For more information, please refer + * to https://time.is/zh/UTC + * 3. For the algorithm used for the transfer between TAI and UTC, please + * refer to Mesh Model Spec Section 5.1.1 + */ + +#define UNKNOWN_TAI_SECONDS 0x0000000000 +#define UNKNOWN_TAI_ZONE_CHANGE 0x0000000000 +#define UNKNOWN_TAI_DELTA_CHANGE 0x0000000000 +#define TAI_UTC_DELAT_MAX_VALUE 0x7FFF +#define TAI_SECONDS_LEN 0x05 +#define TAI_OF_ZONE_CHANGE_LEN 0x05 +#define TAI_OF_DELTA_CHANGE_LEN 0x05 + +#define INVALID_SCENE_NUMBER 0x0000 +#define SCENE_NUMBER_LEN 0x02 + +#define SCHEDULE_YEAR_ANY_YEAR 0x64 + +#define SCHEDULE_DAY_ANY_DAY 0x00 + +#define SCHEDULE_HOUR_ANY_HOUR 0x18 +#define SCHEDULE_HOUR_ONCE_A_DAY 0x19 + +#define SCHEDULE_SEC_ANY_OF_HOUR 0x3C +#define SCHEDULE_SEC_EVERY_15_MIN 0x3D +#define SCHEDULE_SEC_EVERY_20_MIN 0x3E +#define SCHEDULE_SEC_ONCE_AN_HOUR 0x3F + +#define SCHEDULE_SEC_ANY_OF_MIN 0x3C +#define SCHEDULE_SEC_EVERY_15_SEC 0x3D +#define SCHEDULE_SEC_EVERY_20_SEC 0x3E +#define SCHEDULE_SEC_ONCE_AN_MIN 0x3F + +#define SCHEDULE_ACT_TURN_OFF 0x00 +#define SCHEDULE_ACT_TURN_ON 0x01 +#define SCHEDULE_ACT_SCENE_RECALL 0x02 +#define SCHEDULE_ACT_NO_ACTION 0x0F + +#define SCHEDULE_SCENE_NO_SCENE 0x0000 + +#define SCHEDULE_ENTRY_MAX_INDEX 0x0F + +#define TIME_NONE 0x00 +#define TIME_AUTHORITY 0x01 +#define TIME_RELAY 0x02 +#define TIME_CLINET 0x03 + +#define SCENE_SUCCESS 0x00 +#define SCENE_REG_FULL 0x01 +#define SCENE_NOT_FOUND 0x02 + +/** + * The Time state represents the present TAI time, the current TAI-UTC Delta + * and local time zone offset, and the next change to each of the latter + * (e.g., because of a switch from winter to summer time or an announced leap + * second). It consists of 10 fields with a total size of 183 bits. + */ +struct bt_mesh_time_state { + struct { + u8_t tai_seconds[5]; + u8_t subsecond; + u8_t uncertainty; + u8_t time_zone_offset_curr; + u8_t time_zone_offset_new; + u8_t tai_zone_change[5]; + u16_t time_authority : 1, + tai_utc_delta_curr : 15; + u16_t tai_utc_delta_new : 15; + u8_t tai_delta_change[5]; + } time; + u8_t time_role; +}; + +struct bt_mesh_time_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_time_state *state; +}; + +struct bt_mesh_time_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_time_state *state; +}; + +struct scene_register { + u16_t scene_number; + u8_t scene_type; /* Indicate the type of scene value */ + /** + * Scene value may use a union to represent later, the union contains + * structures of all the model states which can be stored in a scene. + */ + struct net_buf_simple *scene_value; +}; + +/** + * Scenes serve as memory banks for storage of states (e.g., a power level + * or a light level/color). Values of states of an element can be stored + * as a scene and can be recalled later from the scene memory. + * + * A scene is represented by a Scene Number, which is a 16-bit non-zero, + * mesh-wide value. (There can be a maximum of 65535 scenes in a mesh + * network.) The meaning of a scene, as well as the state storage container + * associated with it, are determined by a model. + * + * The Scenes state change may start numerous parallel model transitions. + * In that case, each individual model handles the transition internally. + * + * The scene transition is defined as a group of individual model transitions + * started by a Scene Recall operation. The scene transition is in progress + * when at least one transition from the group of individual model transitions + * is in progress. + */ +struct bt_mesh_scenes_state { + const u16_t scene_count; + struct scene_register *scenes; + + /** + * The Current Scene state is a 16-bit value that contains either the Scene + * Number of the currently active scene or a value of 0x0000 when no scene + * is active. + * + * When a Scene Store operation or a Scene Recall operation completes with + * success, the Current Scene state value shall be to the Scene Number used + * during that operation. + * + * When the Current Scene Number is deleted from a Scene Register state as a + * result of Scene Delete operation, the Current Scene state shall be set to + * 0x0000. + * + * When any of the element's state that is marked as “Stored with Scene” has + * changed not as a result of a Scene Recall operation, the value of the + * Current Scene state shall be set to 0x0000. + * + * When a scene transition is in progress, the value of the Current Scene + * state shall be set to 0x0000. + */ + u16_t current_scene; + + /** + * The Target Scene state is a 16-bit value that contains the target Scene + * Number when a scene transition is in progress. + * + * When the scene transition is in progress and the target Scene Number is + * deleted from a Scene Register state as a result of Scene Delete operation, + * the Target Scene state shall be set to 0x0000. + * + * When the scene transition is in progress and a new Scene Number is stored + * in the Scene Register as a result of Scene Store operation, the Target + * Scene state shall be set to the new Scene Number. + * + * When the scene transition is not in progress, the value of the Target Scene + * state shall be set to 0x0000. + */ + u16_t target_scene; + + /* Indicate the status code for the last operation */ + u8_t status_code; + + /* Indicate if scene transition is in progress */ + bool in_progress; +}; + +struct bt_mesh_scene_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_scenes_state *state; + struct bt_mesh_last_msg_info last; + struct bt_mesh_state_transition transition; +}; + +struct bt_mesh_scene_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_scenes_state *state; +}; + +struct schedule_register { + bool in_use; + u64_t year : 7, + month : 12, + day : 5, + hour : 5, + minute : 6, + second : 6, + day_of_week : 7, + action : 4, + trans_time : 8; + u16_t scene_number; +}; + +struct bt_mesh_scheduler_state { + const u8_t schedule_count; + struct schedule_register *schedules; /* Up to 16 scheduled entries */ + + /** + * A recommended implementation of the Scheduler should calculate the + * value of the TAI Seconds of the next scheduled event and put it in + * a queue of scheduled events sorted by time. + * + * Every second, the first event in the queue is compared with the value + * of the Time state. The first event is executed if it is less than or + * equal to the Time state and then removed from the queue. After + * execution, the Repeat Flag shall be checked, and the next occurrence + * of the scheduled event is calculated and put in the queue. + * + * One second timeout value, and compare the first event in queue with the + * Time state. If it is satisfied, then execute the first event. Also the + * Repeat Flag need to be checked, if it is set then the event needs to + * be put into the end of queue. + * + * sys_slist_t event_queue; + * + * For each event_queue item, it can use the following struct: + * struct schedule_event { + * sys_snode_t node; + * u8_t event_index; + * }; + * + * Also we need a "struct k_delayed_work track_timer" which can be used to + * track the schedule timer and handle proper scheduled events. + */ +}; + +struct bt_mesh_scheduler_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_scheduler_state *state; +}; + +struct bt_mesh_scheduler_setup_srv { + struct bt_mesh_model *model; + struct bt_mesh_server_rsp_ctrl rsp_ctrl; + struct bt_mesh_scheduler_state *state; +}; + +typedef union { + struct { + u8_t tai_seconds[5]; + u8_t subsecond; + u8_t uncertainty; + u16_t time_authority : 1; + u16_t tai_utc_delta_curr : 15; + u8_t time_zone_offset_curr; + } time_set; + struct { + u8_t tai_seconds[5]; + u8_t subsecond; + u8_t uncertainty; + u16_t time_authority : 1; + u16_t tai_utc_delta_curr : 15; + u8_t time_zone_offset_curr; + } time_status; + struct { + u8_t time_zone_offset_new; + u8_t tai_zone_change[5]; + } time_zone_set; + struct { + u16_t tai_utc_delta_new : 15; + u8_t tai_delta_change[5]; + } tai_utc_delta_set; + struct { + u8_t role; + } time_role_set; + struct { + u16_t scene_number; + } scene_store; + struct { + u16_t scene_number; + } scene_recall; + struct { + u16_t scene_number; + } scene_delete; + struct { + u64_t index : 4, + year : 7, + month : 12, + day : 5, + hour : 5, + minute : 6, + second : 6, + day_of_week : 7, + action : 4, + trans_time : 8; + u16_t scene_number; + } scheduler_act_set; +} bt_mesh_time_scene_server_state_change_t; + +typedef union { + struct { + u8_t index; + } scheduler_act_get; +} bt_mesh_time_scene_server_recv_get_msg_t; + +typedef union { + struct { + u8_t tai_seconds[5]; + u8_t subsecond; + u8_t uncertainty; + u16_t time_authority : 1; + u16_t tai_utc_delta : 15; + u8_t time_zone_offset; + } time_set; + struct { + u8_t time_zone_offset_new; + u8_t tai_zone_change[5]; + } time_zone_set; + struct { + u16_t tai_utc_delta_new : 15; + u16_t padding : 1; + u8_t tai_delta_change[5]; + } tai_utc_delta_set; + struct { + u8_t time_role; + } time_role_set; + struct { + u16_t scene_number; + } scene_store; + struct { + bool op_en; + u16_t scene_number; + u8_t tid; + u8_t trans_time; + u8_t delay; + } scene_recall; + struct { + u16_t scene_number; + } scene_delete; + struct { + u64_t index : 4, + year : 7, + month : 12, + day : 5, + hour : 5, + minute : 6, + second : 6, + day_of_week : 7, + action : 4, + trans_time : 8; + u16_t scene_number; + } scheduler_act_set; +} bt_mesh_time_scene_server_recv_set_msg_t; + +typedef union { + struct { + u8_t tai_seconds[5]; + u8_t subsecond; + u8_t uncertainty; + u16_t time_authority : 1; + u16_t tai_utc_delta : 15; + u8_t time_zone_offset; + } time_status; +} bt_mesh_time_scene_server_recv_status_msg_t; + +void bt_mesh_time_scene_server_lock(void); +void bt_mesh_time_scene_server_unlock(void); + +void scene_publish(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, u16_t opcode); + +int bt_mesh_time_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_time_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_scene_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_scene_setup_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_scheduler_srv_init(struct bt_mesh_model *model, bool primary); +int bt_mesh_scheduler_setup_srv_init(struct bt_mesh_model *model, bool primary); + +#endif /* _TIME_SCENE_SERVER_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/lighting_server.c b/components/bt/esp_ble_mesh/mesh_models/server/lighting_server.c new file mode 100644 index 000000000..9948d8d24 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/lighting_server.c @@ -0,0 +1,3333 @@ +/* Bluetooth: Mesh Lighting Server Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "osi/mutex.h" + +#include "mesh_types.h" +#include "mesh_kernel.h" +#include "mesh_trace.h" +#include "mesh.h" +#include "access.h" +#include "model_opcode.h" + +#include "server_common.h" +#include "state_binding.h" +#include "state_transition.h" +#include "device_property.h" + +#include "btc_ble_mesh_lighting_model.h" + +static osi_mutex_t light_server_mutex; + +static void bt_mesh_light_server_mutex_new(void) +{ + if (!light_server_mutex) { + osi_mutex_new(&light_server_mutex); + __ASSERT(light_server_mutex, "%s, fail", __func__); + } +} + +void bt_mesh_light_server_lock(void) +{ + osi_mutex_lock(&light_server_mutex, OSI_MUTEX_MAX_TIMEOUT); +} + +void bt_mesh_light_server_unlock(void) +{ + osi_mutex_unlock(&light_server_mutex); +} + +/* message handlers (Start) */ + +/* Light Lightness Server/Setup Server message handlers */ + +static void send_light_lightness_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 5; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS: { + struct bt_mesh_light_lightness_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_actual); + if (srv->actual_transition.counter) { + bt_mesh_server_calc_remain_time(&srv->actual_transition); + net_buf_simple_add_le16(msg, srv->state->target_lightness_actual); + net_buf_simple_add_u8(msg, srv->actual_transition.remain_time); + } + break; + } + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS: { + struct bt_mesh_light_lightness_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_linear); + if (srv->linear_transition.counter) { + bt_mesh_server_calc_remain_time(&srv->linear_transition); + net_buf_simple_add_le16(msg, srv->state->target_lightness_linear); + net_buf_simple_add_u8(msg, srv->linear_transition.remain_time); + } + break; + } + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS: { + struct bt_mesh_light_lightness_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_last); + break; + } + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS: + if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) { + struct bt_mesh_light_lightness_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV) { + struct bt_mesh_light_lightness_setup_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + } + break; + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS: + if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) { + struct bt_mesh_light_lightness_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->lightness_range_min); + net_buf_simple_add_le16(msg, srv->state->lightness_range_max); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV) { + struct bt_mesh_light_lightness_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->lightness_range_min); + net_buf_simple_add_le16(msg, srv->state->lightness_range_max); + } + break; + default: + BT_WARN("%s, Unknown Light Lightness status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void light_lightness_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lightness_srv *srv = model->user_data; + u16_t opcode; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS; + break; + default: + BT_WARN("%s, Unknown Light Lightness Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_light_lightness_status(model, ctx, false, opcode); + return; +} + +void light_lightness_publish(struct bt_mesh_model *model, u16_t opcode) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV: { + struct bt_mesh_light_lightness_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light Lightness Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV: { + struct bt_mesh_light_lightness_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light Lightness Setup Server state", __func__); + return; + } + break; + } + default: + BT_ERR("%s, Invalid Light Lightness Server Model 0x%04x", __func__, model->id); + return; + } + + send_light_lightness_status(model, NULL, true, opcode); + return; +} + +static void light_lightness_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lightness_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + bool optional; + u16_t actual; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + actual = net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lightness_set.op_en = optional, + .lightness_set.lightness = actual, + .lightness_set.tid = tid, + .lightness_set.trans_time = trans_time, + .lightness_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->actual_transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + if (actual) { + if (srv->state->lightness_range_min && actual < srv->state->lightness_range_min) { + actual = srv->state->lightness_range_min; + } else if (srv->state->lightness_range_max && actual > srv->state->lightness_range_max) { + actual = srv->state->lightness_range_max; + } + } + srv->state->target_lightness_actual = actual; + + /** + * If the target state is equal to the current state, the transition shall not be + * started and is considered complete. + */ + if (srv->state->target_lightness_actual != srv->state->lightness_actual) { + light_lightness_actual_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .lightness_set.lightness = srv->state->lightness_actual, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->actual_transition.timer.work._reserved) { + memcpy(srv->actual_transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->actual_transition.counter == 0U) { + srv->state->lightness_actual = srv->state->target_lightness_actual; + /** + * Whenever the Light Lightness Actual state is changed with a non-transactional + * message or a completed sequence of transactional messages to a non-zero value, + * the value of the Light Lightness Last shall be set to the value of the Light + * Lightness Actual. + */ + if (srv->state->lightness_actual) { + srv->state->lightness_last = srv->state->lightness_actual; + } + } + + srv->actual_transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->actual_transition); + return; +} + +static void light_lightness_linear_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lightness_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + bool optional; + u16_t linear; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + linear = net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lightness_linear_set.op_en = optional, + .lightness_linear_set.lightness = linear, + .lightness_linear_set.tid = tid, + .lightness_linear_set.trans_time = trans_time, + .lightness_linear_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->linear_transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state->target_lightness_linear = linear; + + /** + * If the target state is equal to the current state, the transition shall not + * be started and is considered complete. + */ + if (srv->state->target_lightness_linear != srv->state->lightness_linear) { + light_lightness_linear_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .lightness_linear_set.lightness = srv->state->lightness_actual, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->linear_transition.timer.work._reserved) { + memcpy(srv->linear_transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->linear_transition.counter == 0U) { + srv->state->lightness_linear = srv->state->target_lightness_linear; + } + + srv->linear_transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->linear_transition); + return; +} + +static void light_lightness_default_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lightness_setup_srv *srv = model->user_data; + u16_t lightness; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + lightness = net_buf_simple_pull_le16(buf); + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lightness_default_set.lightness = lightness, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (srv->state->lightness_default != lightness) { + srv->state->lightness_default = lightness; + + bt_mesh_light_server_state_change_t change = { + .lightness_default_set.lightness = lightness, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + } + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS); + + return; +} + +static void light_lightness_range_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lightness_setup_srv *srv = model->user_data; + u16_t range_min, range_max; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + range_min = net_buf_simple_pull_le16(buf); + range_max = net_buf_simple_pull_le16(buf); + + if (range_min > range_max) { + BT_ERR("%s, Range Min 0x%04x is greater than Range Max 0x%04x", + __func__, range_min, range_max); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lightness_range_set.range_min = range_min, + .lightness_range_set.range_max = range_max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + /** + * When a Light Lightness Setup Server receives a Light Lightness Range Set + * message or a Light Lightness Range Set Unacknowledged message with values + * that cannot be accepted, it shall set the status of the operation to a + * value representing the reason why the values cannot be accepted. + * + * TODO: 0x0000 for Light Range Min/Max is prohibited, but BQB test case + * MMDL/SR/LLNS/BI-01-C requires 'SUCCESS' when it sends a set message with + * Light Range Min set to 0x0000. + */ +#if 0 + srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS; +#else + if (range_min == 0x0000) { + srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MIN; + } else if (range_max == 0x0000) { + srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MAX; + } else { + srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS; + } +#endif + + if (range_min && srv->state->lightness_range_min != range_min) { + srv->state->lightness_range_min = range_min; + } + + if (range_max && srv->state->lightness_range_max != range_max) { + srv->state->lightness_range_max = range_max; + } + + bt_mesh_light_server_state_change_t change = { + .lightness_range_set.range_min = srv->state->lightness_range_min, + .lightness_range_set.range_max = srv->state->lightness_range_max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET) { + send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS); + } + send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS); + + return; +} + +/* Light CTL Server/Temperature Server/Setup Server message handlers */ + +static void send_light_ctl_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 9; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS: { + struct bt_mesh_light_ctl_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness); + net_buf_simple_add_le16(msg, srv->state->temperature); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_le16(msg, srv->state->target_lightness); + net_buf_simple_add_le16(msg, srv->state->target_temperature); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + break; + } + case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS: + if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SRV) { + struct bt_mesh_light_ctl_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->temperature_range_min); + net_buf_simple_add_le16(msg, srv->state->temperature_range_max); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV) { + struct bt_mesh_light_ctl_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->temperature_range_min); + net_buf_simple_add_le16(msg, srv->state->temperature_range_max); + } + break; + case BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS: { + if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SRV) { + struct bt_mesh_light_ctl_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + net_buf_simple_add_le16(msg, srv->state->temperature_default); + net_buf_simple_add_le16(msg, srv->state->delta_uv_default); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV) { + struct bt_mesh_light_ctl_setup_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + net_buf_simple_add_le16(msg, srv->state->temperature_default); + net_buf_simple_add_le16(msg, srv->state->delta_uv_default); + } + break; + } + case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS: { + struct bt_mesh_light_ctl_temp_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->temperature); + net_buf_simple_add_le16(msg, srv->state->delta_uv); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_le16(msg, srv->state->target_temperature); + net_buf_simple_add_le16(msg, srv->state->target_delta_uv); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + break; + } + default: + BT_WARN("%s, Unknown Light CTL status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void light_ctl_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_server_rsp_ctrl *rsp_ctrl = NULL; + u16_t opcode; + + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: { + struct bt_mesh_light_ctl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light CTL Server state", __func__); + return; + } + rsp_ctrl = &srv->rsp_ctrl; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: { + struct bt_mesh_light_ctl_temp_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light CTL Temperature Server state", __func__); + return; + } + rsp_ctrl = &srv->rsp_ctrl; + break; + } + default: + BT_ERR("%s, Invalid Light CTL Server Model 0x%04x", __func__, model->id); + return; + } + + /* Callback the received message to the application layer */ + if (rsp_ctrl->get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_LIGHT_CTL_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS; + break; + default: + BT_WARN("%s, Unknown Light CTL Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_light_ctl_status(model, ctx, false, opcode); + return; +} + +void light_ctl_publish(struct bt_mesh_model *model, u16_t opcode) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: { + struct bt_mesh_light_ctl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light CTL Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: { + struct bt_mesh_light_ctl_temp_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light CTL Temperature Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV: { + struct bt_mesh_light_ctl_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light CTL Setup Server state", __func__); + return; + } + break; + } + default: + BT_ERR("%s, Invalid Light CTL Server Model 0x%04x", __func__, model->id); + return; + } + + send_light_ctl_status(model, NULL, true, opcode); + return; +} + +static void light_ctl_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_ctl_srv *srv = model->user_data; + u16_t lightness, temperature; + u8_t tid, trans_time, delay; + s16_t delta_uv; + bool optional; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + lightness = net_buf_simple_pull_le16(buf); + temperature = net_buf_simple_pull_le16(buf); + delta_uv = (s16_t) net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (temperature < BLE_MESH_TEMPERATURE_MIN || temperature > BLE_MESH_TEMPERATURE_MAX) { + BT_ERR("%s, Invalid temperature 0x%04x", __func__, temperature); + return; + } + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .ctl_set.op_en = optional, + .ctl_set.lightness = lightness, + .ctl_set.temperature = temperature, + .ctl_set.delta_uv = delta_uv, + .ctl_set.tid = tid, + .ctl_set.trans_time = trans_time, + .ctl_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state->target_lightness = lightness; + if (srv->state->temperature_range_min && + srv->state->temperature_range_min != BLE_MESH_TEMPERATURE_UNKNOWN && + temperature < srv->state->temperature_range_min) { + temperature = srv->state->temperature_range_min; + } else if (srv->state->temperature_range_max && + srv->state->temperature_range_max != BLE_MESH_TEMPERATURE_UNKNOWN && + temperature > srv->state->temperature_range_max) { + temperature = srv->state->temperature_range_max; + } + srv->state->target_temperature = temperature; + srv->state->target_delta_uv = delta_uv; + + if (srv->state->target_lightness != srv->state->lightness || + srv->state->target_temperature != srv->state->temperature || + srv->state->target_delta_uv != srv->state->delta_uv) { + light_ctl_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .ctl_set.lightness = srv->state->lightness, + .ctl_set.temperature = srv->state->temperature, + .ctl_set.delta_uv = srv->state->delta_uv, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->lightness = srv->state->target_lightness; + srv->state->temperature = srv->state->target_temperature; + srv->state->delta_uv = srv->state->target_delta_uv; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void light_ctl_default_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_ctl_setup_srv *srv = model->user_data; + u16_t lightness, temperature; + s16_t delta_uv; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + lightness = net_buf_simple_pull_le16(buf); + temperature = net_buf_simple_pull_le16(buf); + delta_uv = (s16_t) net_buf_simple_pull_le16(buf); + + if (temperature < BLE_MESH_TEMPERATURE_MIN || temperature > BLE_MESH_TEMPERATURE_MAX) { + BT_ERR("%s, Invalid temperature 0x%04x", __func__, temperature); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .ctl_default_set.lightness = lightness, + .ctl_default_set.temperature = temperature, + .ctl_default_set.delta_uv = delta_uv, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (srv->state->temperature_range_min && + srv->state->temperature_range_min != BLE_MESH_TEMPERATURE_UNKNOWN && + temperature < srv->state->temperature_range_min) { + temperature = srv->state->temperature_range_min; + } else if (srv->state->temperature_range_max && + srv->state->temperature_range_max != BLE_MESH_TEMPERATURE_UNKNOWN && + temperature > srv->state->temperature_range_max) { + temperature = srv->state->temperature_range_max; + } + + srv->state->lightness_default = lightness; + srv->state->temperature_default = temperature; + srv->state->delta_uv_default = delta_uv; + + bt_mesh_light_server_state_change_t change = { + .ctl_default_set.lightness = srv->state->lightness_default, + .ctl_default_set.temperature = srv->state->temperature_default, + .ctl_default_set.delta_uv = srv->state->delta_uv_default, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS); + + return; +} + +static void light_ctl_temp_range_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_ctl_setup_srv *srv = model->user_data; + u16_t min, max; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + min = net_buf_simple_pull_le16(buf); + max = net_buf_simple_pull_le16(buf); + + /* This is as per 6.1.3.1 in Mesh Model Specification */ + if (min > max || + min < BLE_MESH_TEMPERATURE_MIN || (min != BLE_MESH_TEMPERATURE_UNKNOWN && min > BLE_MESH_TEMPERATURE_MAX) || + max < BLE_MESH_TEMPERATURE_MIN || (max != BLE_MESH_TEMPERATURE_UNKNOWN && max > BLE_MESH_TEMPERATURE_MAX)) { + BT_ERR("%s, Invalid parameter, range Min 0x%04x, range max 0x%04x", + __func__, min, max); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .ctl_temp_range_set.range_min = min, + .ctl_temp_range_set.range_max = max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (min == BLE_MESH_TEMPERATURE_UNKNOWN) { + srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MIN; + } else if (max == BLE_MESH_TEMPERATURE_UNKNOWN ) { + srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MAX; + } else { + srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS; + } + + if (min != BLE_MESH_TEMPERATURE_UNKNOWN && srv->state->temperature_range_min != min) { + srv->state->temperature_range_min = min; + } + + if (max != BLE_MESH_TEMPERATURE_UNKNOWN && srv->state->temperature_range_max != max) { + srv->state->temperature_range_max = max; + } + + bt_mesh_light_server_state_change_t change = { + .ctl_temp_range_set.range_min = srv->state->temperature_range_min, + .ctl_temp_range_set.range_max = srv->state->temperature_range_max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS); + + return; +} + +static void light_ctl_temp_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_ctl_temp_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + u16_t temperature; + s16_t delta_uv; + bool optional; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + temperature = net_buf_simple_pull_le16(buf); + delta_uv = (s16_t) net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (temperature < BLE_MESH_TEMPERATURE_MIN || temperature > BLE_MESH_TEMPERATURE_MAX) { + BT_ERR("%s, Invalid temperature 0x%04x", __func__, temperature); + return; + } + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .ctl_temp_set.op_en = optional, + .ctl_temp_set.temperature = temperature, + .ctl_temp_set.delta_uv = delta_uv, + .ctl_temp_set.tid = tid, + .ctl_temp_set.trans_time = trans_time, + .ctl_temp_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + if (srv->state->temperature_range_min && + srv->state->temperature_range_min != BLE_MESH_TEMPERATURE_UNKNOWN && + temperature < srv->state->temperature_range_min) { + temperature = srv->state->temperature_range_min; + } else if (srv->state->temperature_range_max && + srv->state->temperature_range_max != BLE_MESH_TEMPERATURE_UNKNOWN && + temperature > srv->state->temperature_range_max) { + temperature = srv->state->temperature_range_max; + } + srv->state->target_temperature = temperature; + srv->state->target_delta_uv = delta_uv; + + if (srv->state->target_temperature != srv->state->temperature || + srv->state->target_delta_uv != srv->state->delta_uv) { + light_ctl_temp_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .ctl_temp_set.temperature = srv->state->temperature, + .ctl_temp_set.delta_uv = srv->state->delta_uv, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->temperature = srv->state->target_temperature; + srv->state->delta_uv = srv->state->target_delta_uv; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET) { + send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + } + send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +/* Light HSL Server/Hue Server/Saturation Server/Setup Server message handlers */ + +static void send_light_hsl_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 9; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS: + case BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS: { + struct bt_mesh_light_hsl_srv *srv = model->user_data; + if (opcode == BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS) { + net_buf_simple_add_le16(msg, srv->state->lightness); + net_buf_simple_add_le16(msg, srv->state->hue); + net_buf_simple_add_le16(msg, srv->state->saturation); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + } else if (opcode == BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS) { + net_buf_simple_add_le16(msg, srv->state->target_lightness); + net_buf_simple_add_le16(msg, srv->state->target_hue); + net_buf_simple_add_le16(msg, srv->state->target_saturation); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + } + break; + } + case BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS: + if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SRV) { + struct bt_mesh_light_hsl_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + net_buf_simple_add_le16(msg, srv->state->hue_default); + net_buf_simple_add_le16(msg, srv->state->saturation_default); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV) { + struct bt_mesh_light_hsl_setup_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + net_buf_simple_add_le16(msg, srv->state->hue_default); + net_buf_simple_add_le16(msg, srv->state->saturation_default); + } + break; + case BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS: + if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SRV) { + struct bt_mesh_light_hsl_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->hue_range_min); + net_buf_simple_add_le16(msg, srv->state->hue_range_max); + net_buf_simple_add_le16(msg, srv->state->saturation_range_min); + net_buf_simple_add_le16(msg, srv->state->saturation_range_max); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV) { + struct bt_mesh_light_hsl_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->hue_range_min); + net_buf_simple_add_le16(msg, srv->state->hue_range_max); + net_buf_simple_add_le16(msg, srv->state->saturation_range_min); + net_buf_simple_add_le16(msg, srv->state->saturation_range_max); + } + break; + case BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS: { + struct bt_mesh_light_hsl_hue_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->hue); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_le16(msg, srv->state->target_hue); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + break; + } + case BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS: { + struct bt_mesh_light_hsl_sat_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->saturation); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_le16(msg, srv->state->target_saturation); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + break; + } + default: + BT_WARN("%s, Unknown Light HSL status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void light_hsl_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_server_rsp_ctrl *rsp_ctrl = NULL; + u16_t opcode; + + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: { + struct bt_mesh_light_hsl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Server state", __func__); + return; + } + rsp_ctrl = &srv->rsp_ctrl; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: { + struct bt_mesh_light_hsl_hue_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Hue Server state", __func__); + return; + } + rsp_ctrl = &srv->rsp_ctrl; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: { + struct bt_mesh_light_hsl_sat_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Saturation Server state", __func__); + return; + } + rsp_ctrl = &srv->rsp_ctrl; + break; + } + default: + BT_ERR("%s, Invalid Light HSL Server Model 0x%04x", __func__, model->id); + return; + } + + /* Callback the received message to the application layer */ + if (rsp_ctrl->get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_LIGHT_HSL_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS; + break; + default: + BT_WARN("%s, Unknown Light HSL Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_light_hsl_status(model, ctx, false, opcode); + return; +} + +void light_hsl_publish(struct bt_mesh_model *model, u16_t opcode) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: { + struct bt_mesh_light_hsl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: { + struct bt_mesh_light_hsl_hue_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Hue Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: { + struct bt_mesh_light_hsl_sat_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Saturation Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV: { + struct bt_mesh_light_hsl_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Setup Server state", __func__); + return; + } + break; + } + default: + BT_ERR("%s, Invalid Light HSL Server Model 0x%04x", __func__, model->id); + return; + } + + send_light_hsl_status(model, NULL, true, opcode); + return; +} + +static void light_hsl_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_hsl_srv *srv = model->user_data; + u16_t lightness, hue, saturation; + u8_t tid, trans_time, delay; + bool optional; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + lightness = net_buf_simple_pull_le16(buf); + hue = net_buf_simple_pull_le16(buf); + saturation = net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .hsl_set.op_en = optional, + .hsl_set.lightness = lightness, + .hsl_set.hue = hue, + .hsl_set.saturation = saturation, + .hsl_set.tid = tid, + .hsl_set.trans_time = trans_time, + .hsl_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state->target_lightness = lightness; + if (srv->state->hue_range_min && hue < srv->state->hue_range_min) { + hue = srv->state->hue_range_min; + } else if (srv->state->hue_range_max && hue > srv->state->hue_range_max) { + hue = srv->state->hue_range_max; + } + srv->state->target_hue = hue; + if (srv->state->saturation_range_min && saturation < srv->state->saturation_range_min) { + saturation = srv->state->saturation_range_min; + } else if (srv->state->saturation_range_max && saturation > srv->state->saturation_range_max) { + saturation = srv->state->saturation_range_max; + } + srv->state->target_saturation = saturation; + + /** + * If the target state is equal to the current state, the transition shall not + * be started and is considered complete. + */ + if (srv->state->target_lightness != srv->state->lightness || + srv->state->target_hue != srv->state->hue || + srv->state->target_saturation != srv->state->saturation) { + light_hsl_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .hsl_set.lightness = srv->state->lightness, + .hsl_set.hue = srv->state->hue, + .hsl_set.saturation = srv->state->saturation, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->lightness = srv->state->target_lightness; + srv->state->hue = srv->state->target_hue; + srv->state->saturation = srv->state->target_saturation; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void light_hsl_default_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_hsl_setup_srv *srv = model->user_data; + u16_t lightness, hue, saturation; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + lightness = net_buf_simple_pull_le16(buf); + hue = net_buf_simple_pull_le16(buf); + saturation = net_buf_simple_pull_le16(buf); + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .hsl_default_set.lightness = lightness, + .hsl_default_set.hue = hue, + .hsl_default_set.saturation = saturation, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (srv->state->hue_range_min && hue < srv->state->hue_range_min) { + hue = srv->state->hue_range_min; + } else if (srv->state->hue_range_max && hue > srv->state->hue_range_max) { + hue = srv->state->hue_range_max; + } + + if (srv->state->saturation_range_min && saturation < srv->state->saturation_range_min) { + saturation = srv->state->saturation_range_min; + } else if (srv->state->saturation_range_max && saturation > srv->state->saturation_range_max) { + saturation = srv->state->saturation_range_max; + } + + srv->state->lightness_default = lightness; + srv->state->hue_default = hue; + srv->state->saturation_default = saturation; + + bt_mesh_light_server_state_change_t change = { + .hsl_default_set.lightness = srv->state->lightness_default, + .hsl_default_set.hue = srv->state->hue_default, + .hsl_default_set.saturation = srv->state->saturation_default, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS); + + return; +} + +static void light_hsl_range_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_hsl_setup_srv *srv = model->user_data; + u16_t hue_min, hue_max, saturation_min, saturation_max; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + hue_min = net_buf_simple_pull_le16(buf); + hue_max = net_buf_simple_pull_le16(buf); + saturation_min = net_buf_simple_pull_le16(buf); + saturation_max = net_buf_simple_pull_le16(buf); + + if (hue_min > hue_max) { + BT_ERR("%s, Invalid parameter, Hue min 0x%04x, Hue max 0x%04x", + __func__, hue_min, hue_max); + return; + } + + if (saturation_min > saturation_max) { + BT_ERR("%s, Invalid parameter, Saturation min 0x%04x, Saturation max 0x%04x", + __func__, hue_min, hue_max); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .hsl_range_set.hue_range_min = hue_min, + .hsl_range_set.hue_range_max = hue_max, + .hsl_range_set.sat_range_min = saturation_min, + .hsl_range_set.sat_range_max = saturation_max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS; + srv->state->hue_range_min = hue_min; + srv->state->hue_range_max = hue_max; + srv->state->saturation_range_min = saturation_min; + srv->state->saturation_range_max = saturation_max; + + bt_mesh_light_server_state_change_t change = { + .hsl_range_set.hue_range_min = srv->state->hue_range_min, + .hsl_range_set.hue_range_max = srv->state->hue_range_max, + .hsl_range_set.sat_range_min = srv->state->saturation_range_min, + .hsl_range_set.sat_range_max = srv->state->saturation_range_max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS); + + return; +} + +static void light_hsl_hue_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_hsl_hue_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + bool optional; + u16_t hue; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + hue = net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .hsl_hue_set.op_en = optional, + .hsl_hue_set.hue = hue, + .hsl_hue_set.tid = tid, + .hsl_hue_set.trans_time = trans_time, + .hsl_hue_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + if (srv->state->hue_range_min && hue < srv->state->hue_range_min) { + hue = srv->state->hue_range_min; + } else if (srv->state->hue_range_max && hue > srv->state->hue_range_max) { + hue = srv->state->hue_range_max; + } + srv->state->target_hue = hue; + + /** + * If the target state is equal to the current state, the transition shall not + * be started and is considered complete. + */ + if (srv->state->target_hue != srv->state->hue) { + light_hsl_hue_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .hsl_hue_set.hue = srv->state->hue, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->hue = srv->state->target_hue; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void light_hsl_sat_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_hsl_sat_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + u16_t saturation; + bool optional; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + saturation = net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .hsl_saturation_set.op_en = optional, + .hsl_saturation_set.saturation = saturation, + .hsl_saturation_set.tid = tid, + .hsl_saturation_set.trans_time = trans_time, + .hsl_saturation_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + if (srv->state->saturation_range_min && saturation < srv->state->saturation_range_min) { + saturation = srv->state->saturation_range_min; + } else if (srv->state->saturation_range_max && saturation > srv->state->saturation_range_max) { + saturation = srv->state->saturation_range_max; + } + srv->state->target_saturation = saturation; + + /** + * If the target state is equal to the current state, the transition shall not + * be started and is considered complete. + */ + if (srv->state->target_saturation != srv->state->saturation) { + light_hsl_sat_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .hsl_saturation_set.saturation = srv->state->saturation, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->saturation = srv->state->target_saturation; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET) { + send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + } + send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +/* Light xyL Server/Setup Server message handlers */ + +static void send_light_xyl_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 9; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS: + case BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS: { + struct bt_mesh_light_xyl_srv *srv = model->user_data; + if (opcode == BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS) { + net_buf_simple_add_le16(msg, srv->state->lightness); + net_buf_simple_add_le16(msg, srv->state->x); + net_buf_simple_add_le16(msg, srv->state->y); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + } else if (opcode == BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS) { + net_buf_simple_add_le16(msg, srv->state->target_lightness); + net_buf_simple_add_le16(msg, srv->state->target_x); + net_buf_simple_add_le16(msg, srv->state->target_y); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + } + break; + } + case BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS: + if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SRV) { + struct bt_mesh_light_xyl_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + net_buf_simple_add_le16(msg, srv->state->x_default); + net_buf_simple_add_le16(msg, srv->state->y_default); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV) { + struct bt_mesh_light_xyl_setup_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->lightness_default); + net_buf_simple_add_le16(msg, srv->state->x_default); + net_buf_simple_add_le16(msg, srv->state->y_default); + } + break; + case BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS: + if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SRV) { + struct bt_mesh_light_xyl_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->x_range_min); + net_buf_simple_add_le16(msg, srv->state->x_range_max); + net_buf_simple_add_le16(msg, srv->state->y_range_min); + net_buf_simple_add_le16(msg, srv->state->y_range_max); + } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV) { + struct bt_mesh_light_xyl_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->status_code); + net_buf_simple_add_le16(msg, srv->state->x_range_min); + net_buf_simple_add_le16(msg, srv->state->x_range_max); + net_buf_simple_add_le16(msg, srv->state->y_range_min); + net_buf_simple_add_le16(msg, srv->state->y_range_max); + } + break; + default: + BT_WARN("%s, Unknown Light xyL status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void light_xyl_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_xyl_srv *srv = model->user_data; + u16_t opcode; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_LIGHT_XYL_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS; + break; + default: + BT_WARN("%s, Unknown Light xyL Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_light_xyl_status(model, ctx, false, opcode); + return; +} + +void light_xyl_publish(struct bt_mesh_model *model, u16_t opcode) +{ + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_LIGHT_XYL_SRV: { + struct bt_mesh_light_xyl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light xyL Server state", __func__); + return; + } + break; + } + case BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV: { + struct bt_mesh_light_xyl_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light xyL Setup Server state", __func__); + return; + } + break; + } + default: + BT_ERR("%s, Invalid Light xyL Server Model 0x%04x", __func__, model->id); + return; + } + + send_light_xyl_status(model, NULL, true, opcode); + return; +} + +static void light_xyl_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_xyl_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + u16_t lightness, x, y; + bool optional; + s64_t now; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + lightness = net_buf_simple_pull_le16(buf); + x = net_buf_simple_pull_le16(buf); + y = net_buf_simple_pull_le16(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .xyl_set.op_en = optional, + .xyl_set.lightness = lightness, + .xyl_set.x = x, + .xyl_set.y = y, + .xyl_set.tid = tid, + .xyl_set.trans_time = trans_time, + .xyl_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_SET) { + send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + } + send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state->target_lightness = lightness; + if (srv->state->x_range_min && x < srv->state->x_range_min) { + x = srv->state->x_range_min; + } else if (srv->state->x_range_max && x > srv->state->x_range_max) { + x = srv->state->x_range_max; + } + srv->state->target_x = x; + if (srv->state->y_range_min && y < srv->state->y_range_min) { + y = srv->state->y_range_min; + } else if (srv->state->y_range_max && y > srv->state->y_range_max) { + y = srv->state->y_range_max; + } + srv->state->target_y = y; + + /** + * If the target state is equal to the current state, the transition shall not + * be started and is considered complete. + */ + if (srv->state->target_lightness != srv->state->lightness || + srv->state->target_x != srv->state->x || + srv->state->target_y != srv->state->y) { + light_xyl_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .xyl_set.lightness = srv->state->lightness, + .xyl_set.x = srv->state->x, + .xyl_set.y = srv->state->y, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_SET) { + send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + } + send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->lightness = srv->state->target_lightness; + srv->state->x = srv->state->target_x; + srv->state->y = srv->state->target_y; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_SET) { + send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + } + send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void light_xyl_default_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_xyl_setup_srv *srv = model->user_data; + u16_t lightness, x, y; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + lightness = net_buf_simple_pull_le16(buf); + x = net_buf_simple_pull_le16(buf); + y = net_buf_simple_pull_le16(buf); + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .xyl_default_set.lightness = lightness, + .xyl_default_set.x = x, + .xyl_default_set.y = y, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (srv->state->x_range_min && x < srv->state->x_range_min) { + x = srv->state->x_range_min; + } else if (srv->state->x_range_max && x > srv->state->x_range_max) { + x = srv->state->x_range_max; + } + + if (srv->state->y_range_min && y < srv->state->y_range_min) { + y = srv->state->y_range_min; + } else if (srv->state->y_range_max && y > srv->state->y_range_max) { + y = srv->state->y_range_max; + } + + srv->state->lightness_default = lightness; + srv->state->x_default = x; + srv->state->y_default = y; + + bt_mesh_light_server_state_change_t change = { + .xyl_default_set.lightness = srv->state->lightness_default, + .xyl_default_set.x = srv->state->x_default, + .xyl_default_set.y = srv->state->y_default, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET) { + send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS); + } + send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS); + + return; +} + +static void light_xyl_range_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_xyl_setup_srv *srv = model->user_data; + u16_t x_min, x_max, y_min, y_max; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + x_min = net_buf_simple_pull_le16(buf); + x_max = net_buf_simple_pull_le16(buf); + y_min = net_buf_simple_pull_le16(buf); + y_max = net_buf_simple_pull_le16(buf); + + if (x_min > x_max) { + BT_ERR("%s, Invalid parameter, xyL x min 0x%04x, xyL x max 0x%04x", + __func__, x_min, x_max); + return; + } + + if (y_min > y_max) { + BT_ERR("%s, Invalid parameter, xyL y min 0x%04x, xyL y max 0x%04x", + __func__, y_min, y_max); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .xyl_range_set.x_range_min = x_min, + .xyl_range_set.x_range_max = x_max, + .xyl_range_set.y_range_min = y_min, + .xyl_range_set.y_range_max = y_max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS; + srv->state->x_range_min = x_min; + srv->state->x_range_max = x_max; + srv->state->y_range_min = y_min; + srv->state->y_range_max = y_max; + + bt_mesh_light_server_state_change_t change = { + .xyl_range_set.x_range_min = srv->state->x_range_min, + .xyl_range_set.x_range_max = srv->state->x_range_max, + .xyl_range_set.y_range_min = srv->state->y_range_min, + .xyl_range_set.y_range_max = srv->state->y_range_max, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET) { + send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS); + } + send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS); + + return; +} + +/* Light LC Server/Setup Server message handlers */ +static void send_light_lc_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct bt_mesh_light_lc_srv *srv = model->user_data; + struct net_buf_simple *msg = NULL; + u8_t length = 2 + 3; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS: + net_buf_simple_add_u8(msg, srv->lc->state.mode); + break; + case BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS: + net_buf_simple_add_u8(msg, srv->lc->state.occupancy_mode); + break; + case BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS: + net_buf_simple_add_u8(msg, srv->lc->state.light_onoff); + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_u8(msg, srv->lc->state.target_light_onoff); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + break; + default: + BT_WARN("%s, Unknown Light LC status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void light_lc_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lc_srv *srv = model->user_data; + u16_t opcode; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS; + break; + case BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET: + opcode = BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS; + break; + default: + BT_WARN("%s, Unknown Light LC Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_light_lc_status(model, ctx, false, opcode); + return; +} + +void light_lc_publish(struct bt_mesh_model *model, u16_t opcode) +{ + struct bt_mesh_light_lc_srv *srv = model->user_data; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + send_light_lc_status(model, NULL, true, opcode); + return; +} + +static void light_lc_mode_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lc_srv *srv = model->user_data; + u8_t mode; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + mode = net_buf_simple_pull_u8(buf); + if (mode > BLE_MESH_STATE_ON) { + BT_ERR("%s, Invalid LC Mode 0x%02x", __func__, mode); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lc_mode_set.mode = mode, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + srv->lc->state.mode = mode; + + bt_mesh_light_server_state_change_t change = { + .lc_mode_set.mode = srv->lc->state.mode, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET) { + send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS); + } + send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS); + + return; +} + +static void light_lc_om_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lc_srv *srv = model->user_data; + u8_t om; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + om = net_buf_simple_pull_u8(buf); + if (om > BLE_MESH_STATE_ON) { + BT_ERR("%s, Invalid LC Occupancy Mode 0x%02x", __func__, om); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lc_om_set.mode = om, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + srv->lc->state.occupancy_mode = om; + + bt_mesh_light_server_state_change_t change = { + .lc_om_set.mode = srv->lc->state.occupancy_mode, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET) { + send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS); + } + send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS); + + return; +} + +static void light_lc_light_onoff_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lc_srv *srv = model->user_data; + u8_t tid, trans_time, delay; + bool optional; + u8_t onoff; + s64_t now; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + onoff = net_buf_simple_pull_u8(buf); + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lc_light_onoff_set.op_en = optional, + .lc_light_onoff_set.light_onoff = onoff, + .lc_light_onoff_set.tid = tid, + .lc_light_onoff_set.trans_time = trans_time, + .lc_light_onoff_set.delay = delay, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET) { + send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + } + send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_light_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->lc->state.target_light_onoff = onoff; + + if (srv->lc->state.target_light_onoff != srv->lc->state.light_onoff) { + light_lc_tt_values(srv, trans_time, delay); + } else { + bt_mesh_light_server_state_change_t change = { + .lc_light_onoff_set.onoff = srv->lc->state.light_onoff, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET) { + send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + } + send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + + bt_mesh_light_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->lc->state.light_onoff = srv->lc->state.target_light_onoff; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET) { + send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + } + send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + + bt_mesh_light_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void light_lc_sensor_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + /** + * When a Light LC Server receives a Sensor Status message, and if the message + * Raw field contains a Raw Value for the Motion Sensed Property, and the value + * is greater than 0, or a Raw Value for the People Count Property, and the + * value is greater than 0, or a Raw Value for the Presence Detected Property, + * and the value is greater than 0, then it shall set the Light LC Occupancy + * state to 0b1. + * If the message Raw field contains a Raw Value for the Time Since Motion Sensed + * device property, which represents a value less than or equal to the value of + * the Light LC Occupancy Delay state, it shall delay setting the Light LC Occupancy + * state to 0b1 by the difference between the value of the Light LC Occupancy Delay + * state and the received Time Since Motion value. + * When a Light LC Server receives a Sensor Status message, and if the message Raw + * field contains a Raw Value for the Present Ambient Light Level device property, + * it shall set the Light LC Ambient LuxLevel state to the Represented Value of the + * received Present Ambient Light Level. + * + * Motion Sensed: 1 octet, 0x0042 + * People Count: 2 octets, 0x004C + * Presence Detected: 1 octet, 0x004D + * + * Time Since Motion Sensed: 2 octets, 0x0068 + * + * Present Ambient Light Level: 4 octets, 0x004E + */ + struct bt_mesh_light_lc_srv *srv = model->user_data; + bt_mesh_light_server_state_change_t change = {0}; + u16_t mpid, prop_id; + u8_t length; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + if (srv->rsp_ctrl.status_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_status_msg_t status = { + .sensor_status.data = buf, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_STATUS_MSG, model, ctx, (const u8_t *)&status, sizeof(status)); + return; + } + + mpid = net_buf_simple_pull_le16(buf); + if (mpid & BIT(0)) { + length = (u8_t)((mpid & 0xff) >> 1); + u8_t msb = net_buf_simple_pull_u8(buf); + prop_id = (u16_t)(msb << 8) | (u16_t)(mpid >> 8); + } else { + length = (u8_t)((mpid & 0x1f) >> 1); + prop_id = (u16_t)(mpid >> 5); + } + + change.sensor_status.property_id = prop_id; + + switch (prop_id) { + case BLE_MESH_MOTION_SENSED: { + if (length != BLE_MESH_MOTION_SENSED_LEN || length != buf->len) { + BT_WARN("%s, Invalid Motion Sensed Property length", __func__); + return; + } + u8_t val = net_buf_simple_pull_u8(buf); + if (val > 0) { + srv->lc->state.occupancy = BLE_MESH_STATE_ON; + + change.sensor_status.state.occupancy = srv->lc->state.occupancy; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + } + break; + } + case BLE_MESH_PEOPLE_COUNT: { + if (length != BLE_MESH_PEOPLE_COUNT_LEN || length != buf->len) { + BT_WARN("%s, Invalid Motion Sensed Property length", __func__); + return; + } + u16_t val = net_buf_simple_pull_le16(buf); + if (val > 0) { + srv->lc->state.occupancy = BLE_MESH_STATE_ON; + + change.sensor_status.state.occupancy = srv->lc->state.occupancy; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + } + break; + } + case BLE_MESH_PRESENCE_DETECTED: { + if (length != BLE_MESH_PRESENCE_DETECTED_LEN || length != buf->len) { + BT_WARN("%s, Invalid Motion Sensed Property length", __func__); + return; + } + u8_t val = net_buf_simple_pull_u8(buf); + if (val > 0) { + srv->lc->state.occupancy = BLE_MESH_STATE_ON; + + change.sensor_status.state.occupancy = srv->lc->state.occupancy; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + } + break; + } + case BLE_MESH_TIME_SINCE_MOTION_SENSED: { + if (length != BLE_MESH_TIME_SINCE_MOTION_SENSED_LEN || length != buf->len) { + BT_WARN("%s, Invalid Motion Sensed Property length", __func__); + return; + } + u16_t val = net_buf_simple_pull_le16(buf); + if (val <= srv->lc->prop_state.time_occupancy_delay) { + srv->lc->prop_state.set_occupancy_to_1_delay = + srv->lc->prop_state.time_occupancy_delay - val; + + change.sensor_status.state.set_occupancy_to_1_delay = srv->lc->prop_state.set_occupancy_to_1_delay; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + } + break; + } + case BLE_MESH_PRESENT_AMBIENT_LIGHT_LEVEL: { + /** + * Present Ambient Light Level device property is 4 octets, but ambient + * luxlevel length is 3 octets, and other devices may send Sensor Status + * which only contains 3 octets just for Light LC Server. + * Here we just check if the length is larger than 3. + */ + if (buf->len < 3) { + BT_WARN("%s, Invalid Motion Sensed Property length", __func__); + return; + } + u16_t lsb = net_buf_simple_pull_le16(buf); + u8_t msb = net_buf_simple_pull_u8(buf); + srv->lc->state.ambient_luxlevel = (msb << 16) | lsb; + + change.sensor_status.state.ambient_luxlevel = srv->lc->state.ambient_luxlevel; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + break; + } + default: + break; + } +} + +static u8_t *get_light_lc_prop_val(struct bt_mesh_model *model, u16_t prop_id) +{ + struct bt_mesh_light_lc_setup_srv *srv = model->user_data; + u8_t *val = NULL; + + switch (prop_id) { + case BLE_MESH_LIGHT_CONTROL_TIME_OCCUPANCY_DELAY: + val = (u8_t *)&srv->lc->prop_state.time_occupancy_delay; + break; + case BLE_MESH_LIGHT_CONTROL_TIME_FADE_ON: + val = (u8_t *)&srv->lc->prop_state.time_fade_on; + break; + case BLE_MESH_LIGHT_CONTROL_TIME_RUN_ON: + val = (u8_t *)&srv->lc->prop_state.time_run_on; + break; + case BLE_MESH_LIGHT_CONTROL_TIME_FADE: + val = (u8_t *)&srv->lc->prop_state.time_fade; + break; + case BLE_MESH_LIGHT_CONTROL_TIME_PROLONG: + val = (u8_t *)&srv->lc->prop_state.time_prolong; + break; + case BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_AUTO: + val = (u8_t *)&srv->lc->prop_state.time_fade_standby_auto; + break; + case BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_MANUAL: + val = (u8_t *)&srv->lc->prop_state.time_fade_standby_manual; + break; + case BLE_MESH_LIGHT_CONTROL_LIGHTNESS_ON: + val = (u8_t *)&srv->lc->prop_state.lightness_on; + break; + case BLE_MESH_LIGHT_CONTROL_LIGHTNESS_PROLONG: + val = (u8_t *)&srv->lc->prop_state.lightness_prolong; + break; + case BLE_MESH_LIGHT_CONTROL_LIGHTNESS_STANDBY: + val = (u8_t *)&srv->lc->prop_state.lightness_standby; + break; + case BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_ON: + val = (u8_t *)&srv->lc->prop_state.ambient_luxlevel_on; + break; + case BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_PROLONG: + val = (u8_t *)&srv->lc->prop_state.ambient_luxlevel_prolong; + break; + case BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_STANDBY: + val = (u8_t *)&srv->lc->prop_state.ambient_luxlevel_standby; + break; + case BLE_MESH_LIGHT_CONTROL_REGULATOR_KIU: + val = (u8_t *)&srv->lc->prop_state.regulator_kiu; + break; + case BLE_MESH_LIGHT_CONTROL_REGULATOR_KID: + val = (u8_t *)&srv->lc->prop_state.regulator_kid; + break; + case BLE_MESH_LIGHT_CONTROL_REGULATOR_KPU: + val = (u8_t *)&srv->lc->prop_state.regulator_kpu; + break; + case BLE_MESH_LIGHT_CONTROL_REGULATOR_KPD: + val = (u8_t *)&srv->lc->prop_state.regulator_kpd; + break; + case BLE_MESH_LIGHT_CONTROL_REGULATOR_ACCURACY: + val = (u8_t *)&srv->lc->prop_state.regulator_accuracy; + break; + } + + return val; +} + +u8_t *bt_mesh_get_lc_prop_value(struct bt_mesh_model *model, u16_t prop_id) +{ + if (model == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return NULL; + } + + return get_light_lc_prop_val(model, prop_id); +} + +static void send_light_lc_prop_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t prop_id, bool publish) +{ + struct net_buf_simple *msg = NULL; + u8_t length = 1 + 2 + 4; + u8_t *prop_val; + + prop_val = get_light_lc_prop_val(model, prop_id); + if (prop_val == NULL) { + BT_ERR("%s, Failed to get Light LC Property value", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS); + net_buf_simple_add_le16(msg, prop_id); + net_buf_simple_add_mem(msg, prop_val, bt_mesh_get_dev_prop_len(prop_id)); + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void light_lc_prop_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lc_setup_srv *srv = model->user_data; + u16_t prop_id; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id < 0x002B || prop_id > 0x003C) { + BT_ERR("%s, Invalid Light LC Property ID 0x%04x", __func__, prop_id); + return; + } + + /* Callback the received message to the application layer */ + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_get_msg_t get = { + .lc_property_get.id = net_buf_simple_pull_le16(buf), + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + return; + } + + send_light_lc_prop_status(model, ctx, prop_id, false); + return; +} + +static void light_lc_prop_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_light_lc_setup_srv *srv = model->user_data; + u8_t *prop_val, expect_len; + u16_t prop_id; + + if (srv == NULL || srv->lc == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id < 0x002B || prop_id > 0x003C) { + BT_ERR("%s, Invalid Light LC Property ID 0x%04x", __func__, prop_id); + return; + } + + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_light_server_recv_set_msg_t set = { + .lc_property_set.id = net_buf_simple_pull_le16(buf), + .lc_property_set.value = buf, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + expect_len = bt_mesh_get_dev_prop_len(prop_id); + if (buf->len != expect_len) { + BT_ERR("%s, Invalid Light LC Property length, ID 0x%04x, expect %d, actual %d", + __func__, prop_id, expect_len, buf->len); + return; + } + + prop_val = get_light_lc_prop_val(model, prop_id); + if (prop_val == NULL) { + BT_ERR("%s, Failed to get Light LC Property value", __func__); + return; + } + + memcpy(prop_val, buf->data, buf->len); + + bt_mesh_light_server_state_change_t change = { + .lc_property_set.id = prop_id, + .lc_property_set.value = buf, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET) { + send_light_lc_prop_status(model, ctx, prop_id, false); + } + send_light_lc_prop_status(model, ctx, prop_id, true); + + return; +} + +/* message handlers (End) */ + +/* Mapping of message handlers for Light Lightness Server (0x1300) */ +const struct bt_mesh_model_op light_lightness_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET, 0, light_lightness_get }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET, 3, light_lightness_set }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK, 3, light_lightness_set }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET, 0, light_lightness_get }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET, 3, light_lightness_linear_set }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET_UNACK, 3, light_lightness_linear_set }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET, 0, light_lightness_get }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET, 0, light_lightness_get }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET, 0, light_lightness_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light Lightness Setup Server (0x1301) */ +const struct bt_mesh_model_op light_lightness_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET, 2, light_lightness_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK, 2, light_lightness_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET, 4, light_lightness_range_set }, + { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET_UNACK, 4, light_lightness_range_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light CTL Server (0x1303) */ +const struct bt_mesh_model_op light_ctl_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_CTL_GET, 0, light_ctl_get }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_SET, 7, light_ctl_set }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_SET_UNACK, 7, light_ctl_set }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET, 0, light_ctl_get }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET, 0, light_ctl_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light CTL Setup Server (0x1304) */ +const struct bt_mesh_model_op light_ctl_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET, 6, light_ctl_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET_UNACK, 6, light_ctl_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET, 4, light_ctl_temp_range_set }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK, 4, light_ctl_temp_range_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light CTL Temperature Server (0x1306) */ +const struct bt_mesh_model_op light_ctl_temp_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET, 0, light_ctl_get }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET, 5, light_ctl_temp_set }, + { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET_UNACK, 5, light_ctl_temp_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light HSL Server (0x1307) */ +const struct bt_mesh_model_op light_hsl_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_HSL_GET, 0, light_hsl_get }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_SET, 7, light_hsl_set }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_SET_UNACK, 7, light_hsl_set }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET, 0, light_hsl_get }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET, 0, light_hsl_get }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET, 0, light_hsl_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light HSL Setup Server (0x1308) */ +const struct bt_mesh_model_op light_hsl_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET, 6, light_hsl_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET_UNACK, 6, light_hsl_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET, 8, light_hsl_range_set }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK, 8, light_hsl_range_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light HSL Hue Server (0x130A) */ +const struct bt_mesh_model_op light_hsl_hue_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET, 0, light_hsl_get }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET, 3, light_hsl_hue_set }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET_UNACK, 3, light_hsl_hue_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light HSL Saturation Server (0x130B) */ +const struct bt_mesh_model_op light_hsl_sat_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET, 0, light_hsl_get }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET, 3, light_hsl_sat_set }, + { BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET_UNACK, 3, light_hsl_sat_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light xyL Server (0x130C) */ +const struct bt_mesh_model_op light_xyl_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_XYL_GET, 0, light_xyl_get }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_SET, 7, light_xyl_set }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_SET_UNACK, 7, light_xyl_set }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET, 0, light_xyl_get }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET, 0, light_xyl_get }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET, 0, light_xyl_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light xyL Setup Server (0x130D) */ +const struct bt_mesh_model_op light_xyl_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET, 6, light_xyl_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET_UNACK, 6, light_xyl_default_set }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET, 8, light_xyl_range_set }, + { BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET_UNACK, 8, light_xyl_range_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light LC Server (0x130F) */ +const struct bt_mesh_model_op light_lc_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET, 0, light_lc_get }, + { BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET, 1, light_lc_mode_set }, + { BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET_UNACK, 1, light_lc_mode_set }, + { BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET, 0, light_lc_get }, + { BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET, 1, light_lc_om_set }, + { BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET_UNACK, 1, light_lc_om_set }, + { BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET, 0, light_lc_get }, + { BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET, 2, light_lc_light_onoff_set }, + { BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET_UNACK, 2, light_lc_light_onoff_set }, + { BLE_MESH_MODEL_OP_SENSOR_STATUS, 3, light_lc_sensor_status }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Light LC Setup Server (0x1310) */ +const struct bt_mesh_model_op light_lc_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_GET, 2, light_lc_prop_get }, + { BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET, 3, light_lc_prop_set }, + { BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK, 3, light_lc_prop_set }, + BLE_MESH_MODEL_OP_END, +}; + +static int light_server_init(struct bt_mesh_model *model) +{ + if (model->user_data == NULL) { + BT_ERR("%s, No Light Server context provided, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV: { + struct bt_mesh_light_lightness_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light Lightness State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->actual_transition.timer.work); + bt_mesh_server_alloc_ctx(&srv->linear_transition.timer.work); + k_delayed_work_init(&srv->actual_transition.timer, light_lightness_actual_work_handler); + k_delayed_work_init(&srv->linear_transition.timer, light_lightness_linear_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV: { + struct bt_mesh_light_lightness_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light Lightness State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: { + struct bt_mesh_light_ctl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light CTL State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, light_ctl_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV: { + struct bt_mesh_light_ctl_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light CTL State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: { + struct bt_mesh_light_ctl_temp_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light CTL State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, light_ctl_temp_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: { + struct bt_mesh_light_hsl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light HSL State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, light_hsl_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV: { + struct bt_mesh_light_hsl_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light HSL State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: { + struct bt_mesh_light_hsl_hue_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light HSL State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, light_hsl_hue_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: { + struct bt_mesh_light_hsl_sat_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light HSL State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, light_hsl_sat_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_XYL_SRV: { + struct bt_mesh_light_xyl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light xyL State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, light_xyl_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV: { + struct bt_mesh_light_xyl_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Light xyL State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_LC_SRV: { + struct bt_mesh_light_lc_srv *srv = model->user_data; + if (srv->lc == NULL) { + BT_ERR("%s, NULL Light LC State", __func__); + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, light_lc_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV: { + struct bt_mesh_light_lc_setup_srv *srv = model->user_data; + if (srv->lc == NULL) { + BT_ERR("%s, NULL Light LC State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + default: + BT_WARN("%s, Unknown Light Server Model, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + bt_mesh_light_server_mutex_new(); + + return 0; +} + +int bt_mesh_light_lightness_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light Lightness Server has no publication support", __func__); + return -EINVAL; + } + + /* When this model is present on an Element, the corresponding Light Lightness + * Setup Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV) == NULL) { + BT_WARN("%s, Light Lightness Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return light_server_init(model); +} + +int bt_mesh_light_lightness_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + return light_server_init(model); +} + +int bt_mesh_light_ctl_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light CTL Server has no publication support", __func__); + return -EINVAL; + } + + /** + * When this model is present on an Element, the corresponding Light CTL + * Temperature Server model and the corresponding Light CTL Setup Server + * model shall also be present. + * The model requires two elements: the main element and the Temperature + * element. The Temperature element contains the corresponding Light CTL + * Temperature Server model. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV) == NULL) { + BT_WARN("%s, Light CTL Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + if (bt_mesh_elem_count() < 2) { + BT_WARN("%s, Light CTL Server requires two elements", __func__); + /* Just give a warning here, continue with the initialization */ + } + return light_server_init(model); +} + +int bt_mesh_light_ctl_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + return light_server_init(model); +} + +int bt_mesh_light_ctl_temp_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light CTL Temperature Server has no publication support", __func__); + return -EINVAL; + } + + return light_server_init(model); +} + +int bt_mesh_light_hsl_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light HSL Server has no publication support", __func__); + return -EINVAL; + } + + /** + * When this model is present on an Element, the corresponding Light HSL Hue + * Server model and the corresponding Light HSL Saturation Server model and + * the corresponding Light HSL Setup Server model shall also be present. + * The model requires three elements: the main element and the Hue element + * and the Saturation element. The Hue element contains the corresponding + * Light HSL Hue Server model, and the Saturation element contains the corr- + * esponding Light HSL Saturation Server model. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV) == NULL) { + BT_WARN("%s, Light HSL Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + if (bt_mesh_elem_count() < 3) { + BT_WARN("%s, Light HSL Server requires three elements", __func__); + /* Just give a warning here, continue with the initialization */ + } + return light_server_init(model); +} + +int bt_mesh_light_hsl_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + return light_server_init(model); +} + +int bt_mesh_light_hsl_hue_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light HSL Hue Server has no publication support", __func__); + return -EINVAL; + } + + return light_server_init(model); +} + +int bt_mesh_light_hsl_sat_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light HSL Saturation Server has no publication support", __func__); + return -EINVAL; + } + + return light_server_init(model); +} + +int bt_mesh_light_xyl_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light xyL Server has no publication support", __func__); + return -EINVAL; + } + + /** + * When this model is present on an Element, the corresponding Light xyL + * Setup Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV) == NULL) { + BT_WARN("%s, Light xyL Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return light_server_init(model); +} + +int bt_mesh_light_xyl_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + return light_server_init(model); +} + +int bt_mesh_light_lc_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light LC Server has no publication support", __func__); + return -EINVAL; + } + + return light_server_init(model); +} + +int bt_mesh_light_lc_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Light LC Setup Server has no publication support", __func__); + return -EINVAL; + } + + /** + * When this model is present on an Element, the corresponding Light LC + * Setup Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV) == NULL) { + BT_WARN("%s, Light LC Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return light_server_init(model); +} diff --git a/components/bt/esp_ble_mesh/mesh_models/server/sensor_server.c b/components/bt/esp_ble_mesh/mesh_models/server/sensor_server.c new file mode 100644 index 000000000..a28930f75 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/sensor_server.c @@ -0,0 +1,1088 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "mesh_types.h" +#include "mesh_kernel.h" +#include "mesh_trace.h" +#include "mesh.h" +#include "access.h" +#include "model_opcode.h" +#include "transport.h" + +#include "server_common.h" +#include "state_binding.h" +#include "state_transition.h" +#include "sensor_server.h" +#include "device_property.h" + +#include "btc_ble_mesh_sensor_model.h" + +static void update_sensor_periodic_pub(struct bt_mesh_model *model, u16_t prop_id); + +/* message handlers (Start) */ + +/* Sensor Server & Sensor Setup Server message handlers */ +static void send_sensor_descriptor_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t prop_id, bool get_all) +{ + struct bt_mesh_sensor_srv *srv = model->user_data; + struct bt_mesh_sensor_state *state = NULL; + struct net_buf_simple *msg = NULL; + u16_t total_len = 5; + u8_t i; + + msg = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS); + + if (get_all == true) { + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID) { + total_len += SENSOR_DESCRIPTOR_LEN; + if (total_len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)) { + /* Add this in case the message is too long */ + break; + } + net_buf_simple_add_le16(msg, state->sensor_property_id); + net_buf_simple_add_le32(msg, (state->descriptor.sample_function << 24) | + (state->descriptor.negative_tolerance << 12) | + (state->descriptor.positive_tolerance)); + net_buf_simple_add_u8(msg, state->descriptor.measure_period); + net_buf_simple_add_u8(msg, state->descriptor.update_interval); + } + } + } else { + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + net_buf_simple_add_le16(msg, state->sensor_property_id); + net_buf_simple_add_le32(msg, (state->descriptor.sample_function << 24) | + (state->descriptor.negative_tolerance << 12) | + (state->descriptor.positive_tolerance)); + net_buf_simple_add_u8(msg, state->descriptor.measure_period); + net_buf_simple_add_u8(msg, state->descriptor.update_interval); + break; + } + } + if (i == srv->state_count) { + BT_WARN("%s, Sensor Property ID 0x%04x does not exist", __func__, prop_id); + net_buf_simple_add_le16(msg, prop_id); + } + } + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; +} + +static void send_sensor_data_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t prop_id, bool get_all) +{ + struct bt_mesh_sensor_srv *srv = model->user_data; + struct bt_mesh_sensor_state *state = NULL; + struct net_buf_simple *msg = NULL; + u16_t total_len = 5; + u8_t i; + + msg = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SENSOR_STATUS); + + if (get_all == true) { + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID) { + u8_t mpid_len = (state->sensor_data.format == SENSOR_DATA_FORMAT_A) ? + SENSOR_DATA_FORMAT_A_MPID_LEN : SENSOR_DATA_FORMAT_B_MPID_LEN; + total_len += (mpid_len + (state->sensor_data.raw_value ? + state->sensor_data.raw_value->len : 0)); + if (total_len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)) { + /* Add this in case the message is too long */ + break; + } + if (state->sensor_data.format == SENSOR_DATA_FORMAT_A) { + u16_t mpid = ((state->sensor_property_id & BIT_MASK(11)) << 5) | + ((state->sensor_data.length & BIT_MASK(4)) << 1) | state->sensor_data.format; + net_buf_simple_add_le16(msg, mpid); + } else if (state->sensor_data.format == SENSOR_DATA_FORMAT_B) { + u8_t mpid = (state->sensor_data.length << 1) | state->sensor_data.format; + net_buf_simple_add_u8(msg, mpid); + net_buf_simple_add_le16(msg, state->sensor_property_id); + } + if (state->sensor_data.raw_value) { + net_buf_simple_add_mem(msg, state->sensor_data.raw_value->data, state->sensor_data.raw_value->len); + } + } + } + } else { + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + if (state->sensor_data.format == SENSOR_DATA_FORMAT_A) { + u16_t mpid = ((state->sensor_property_id & BIT_MASK(11)) << 5) | + ((state->sensor_data.length & BIT_MASK(4)) << 1) | + state->sensor_data.format; + net_buf_simple_add_le16(msg, mpid); + } else if (state->sensor_data.format == SENSOR_DATA_FORMAT_B) { + u8_t mpid = (state->sensor_data.length << 1) | state->sensor_data.format; + net_buf_simple_add_u8(msg, mpid); + net_buf_simple_add_le16(msg, state->sensor_property_id); + } + if (state->sensor_data.raw_value) { + net_buf_simple_add_mem(msg, state->sensor_data.raw_value->data, + state->sensor_data.raw_value->len); + } + break; + } + } + if (i == srv->state_count) { + BT_WARN("%s, Sensor Property ID 0x%04x does not exist", __func__, prop_id); + u8_t mpid = (SENSOR_DATA_ZERO_LEN << 1) | SENSOR_DATA_FORMAT_B; + net_buf_simple_add_u8(msg, mpid); + net_buf_simple_add_le16(msg, prop_id); + } + } + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; +} + +static void send_sensor_cadence_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t prop_id, bool publish) +{ + struct bt_mesh_sensor_setup_srv *srv = model->user_data; + struct bt_mesh_sensor_state *state = NULL; + struct net_buf_simple *msg = NULL; + u16_t length = 0; + u8_t i; + + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id && state->cadence) { + length = SENSOR_PROPERTY_ID_LEN + 1 + 1; + if (state->cadence->trigger_delta_down) { + if (state->cadence->trigger_type == SENSOR_STATUS_TRIGGER_TYPE_CHAR) { + length += state->cadence->trigger_delta_down->len; + } else { + length += SENSOR_STATUS_TRIGGER_UINT16_LEN; + } + } + if (state->cadence->trigger_delta_up) { + if (state->cadence->trigger_type == SENSOR_STATUS_TRIGGER_TYPE_CHAR) { + length += state->cadence->trigger_delta_up->len; + } else { + length += SENSOR_STATUS_TRIGGER_UINT16_LEN; + } + } + if (state->cadence->fast_cadence_low) { + length += state->cadence->fast_cadence_low->len; + } + if (state->cadence->fast_cadence_high) { + length += state->cadence->fast_cadence_high->len; + } + break; + } + } + if (i == srv->state_count) { + BT_WARN("%s, Sensor Property ID 0x%04x does not exist", __func__, prop_id); + length = SENSOR_PROPERTY_ID_LEN; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, 1 + length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS); + net_buf_simple_add_le16(msg, prop_id); + if (i != srv->state_count) { + if (state->cadence) { + net_buf_simple_add_u8(msg, (state->cadence->trigger_type << 7) | + state->cadence->period_divisor); + if (state->cadence->trigger_delta_down) { + if (state->cadence->trigger_type == SENSOR_STATUS_TRIGGER_TYPE_CHAR) { + net_buf_simple_add_mem(msg, state->cadence->trigger_delta_down->data, + state->cadence->trigger_delta_down->len); + } else { + net_buf_simple_add_mem(msg, state->cadence->trigger_delta_down->data, + SENSOR_STATUS_TRIGGER_UINT16_LEN); + } + } + if (state->cadence->trigger_delta_up) { + if (state->cadence->trigger_type == SENSOR_STATUS_TRIGGER_TYPE_CHAR) { + net_buf_simple_add_mem(msg, state->cadence->trigger_delta_up->data, + state->cadence->trigger_delta_up->len); + } else { + net_buf_simple_add_mem(msg, state->cadence->trigger_delta_up->data, + SENSOR_STATUS_TRIGGER_UINT16_LEN); + } + } + net_buf_simple_add_u8(msg, state->cadence->min_interval); + if (state->cadence->fast_cadence_low) { + net_buf_simple_add_mem(msg, state->cadence->fast_cadence_low->data, + state->cadence->fast_cadence_low->len); + } + if (state->cadence->fast_cadence_high) { + net_buf_simple_add_mem(msg, state->cadence->fast_cadence_high->data, + state->cadence->fast_cadence_high->len); + } + } + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void send_sensor_settings_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u16_t prop_id) +{ + struct bt_mesh_sensor_setup_srv *srv = model->user_data; + struct bt_mesh_sensor_state *state = NULL; + struct sensor_setting *item = NULL; + struct net_buf_simple *msg = NULL; + u16_t total_len = 7; + u8_t i, j; + + msg = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS); + net_buf_simple_add_le16(msg, prop_id); + + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + for (j = 0U; j < state->setting_count; j++) { + item = &state->settings[j]; + if (item->property_id != INVALID_SENSOR_SETTING_PROPERTY_ID) { + total_len += SENSOR_SETTING_PROPERTY_ID_LEN; + if (total_len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)) { + /* Add this in case the message is too long */ + break; + } + net_buf_simple_add_le16(msg, item->property_id); + } + } + break; + } + } + if (i == srv->state_count) { + BT_WARN("%s, Sensor Property ID 0x%04x does not exist", __func__, prop_id); + } + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; +} + +static struct sensor_setting *find_sensor_setting(struct bt_mesh_model *model, + u16_t prop_id, u16_t set_prop_id) +{ + struct bt_mesh_sensor_setup_srv *srv = model->user_data; + struct bt_mesh_sensor_state *state = NULL; + struct sensor_setting *item = NULL; + u8_t i, j; + + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + for (j = 0U; j < state->setting_count; j++) { + item = &state->settings[j]; + if (item->property_id != INVALID_SENSOR_SETTING_PROPERTY_ID && + item->property_id == set_prop_id) { + return item; + } + } + } + } + + return NULL; +} + +static void send_sensor_setting_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, u16_t prop_id, + u16_t set_prop_id, bool publish) +{ + struct sensor_setting *item = NULL; + struct net_buf_simple *msg = NULL; + u16_t length; + + item = find_sensor_setting(model, prop_id, set_prop_id); + if (item) { + length = SENSOR_PROPERTY_ID_LEN + SENSOR_SETTING_PROPERTY_ID_LEN + + SENSOR_SETTING_ACCESS_LEN + (item->raw ? item->raw->len : 0); + } else { + /* If the message is sent as a response to the Sensor Setting Get message or + * a Sensor Setting Set message with an unknown Sensor Property ID field or + * an unknown Sensor Setting Property ID field, the Sensor Setting Access + * field and the Sensor Setting Raw field shall be omitted. + */ + BT_WARN("%s, Sensor Setting not found, 0x%04x, 0x%04x", __func__, prop_id, set_prop_id); + length = SENSOR_PROPERTY_ID_LEN + SENSOR_SETTING_PROPERTY_ID_LEN; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, 1 + length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS); + net_buf_simple_add_le16(msg, prop_id); + net_buf_simple_add_le16(msg, set_prop_id); + if (item) { + /** + * If the message is sent as a response to the Sensor Setting Set message with + * a Sensor Setting Property ID field that identifies an existing Sensor Setting, + * and the value of the Sensor Setting Access state is 0x01 (can be read), the + * Sensor Setting Property ID field shall be set to the value of the Sensor + * Setting Property ID field of the incoming message, the Sensor Setting Access + * field shall be set to the value of the Sensor Setting Access state field, and + * the Sensor Setting Raw field shall be omitted. + * + * TODO: What if the Sensor Setting Access is Prohibited? + */ + net_buf_simple_add_u8(msg, item->access); + if (ctx->recv_op != BLE_MESH_MODEL_OP_SENSOR_SETTING_SET || + item->access == SENSOR_SETTING_ACCESS_READ_WRITE) { + if (item->raw) { + net_buf_simple_add_mem(msg, item->raw->data, item->raw->len); + } + } + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void send_sensor_column_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf, u16_t prop_id) +{ + struct bt_mesh_sensor_srv *srv = model->user_data; + struct bt_mesh_sensor_state *state = NULL; + struct net_buf_simple *msg = NULL; + bool optional = false; + u16_t length = 0; + u8_t i; + + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + length = SENSOR_PROPERTY_ID_LEN + state->series_column.raw_value_x->len; + /** + * TODO: column width & raw value y in Sensor Column Status are optional, + * here we need to add some conditions to decide whether put these two + * in the status message. + */ + if (optional) { + length += state->series_column.column_width->len + state->series_column.raw_value_y->len; + } + break; + } + } + if (i == srv->state_count) { + BT_WARN("%s, Sensor Property ID 0x%04x does not exist", __func__, prop_id); + length = SENSOR_PROPERTY_ID_LEN; + } + + msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + + /** + * TODO: Sensor Column Get contains Raw Value X which identifies a column, + * we need to use this value to decide the column. + */ + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS); + net_buf_simple_add_le16(msg, prop_id); + if (i != srv->state_count) { + net_buf_simple_add_mem(msg, state->series_column.raw_value_x->data, + state->series_column.raw_value_x->len); + if (optional) { + net_buf_simple_add_mem(msg, state->series_column.column_width->data, + state->series_column.column_width->len); + net_buf_simple_add_mem(msg, state->series_column.raw_value_y->data, + state->series_column.raw_value_y->len); + } + } + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; +} + +static void send_sensor_series_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf, u16_t prop_id) +{ + struct bt_mesh_sensor_srv *srv = model->user_data; + struct bt_mesh_sensor_state *state = NULL; + struct net_buf_simple *msg = NULL; + bool optional = false; + u16_t length; + u8_t i; + + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + length = SENSOR_PROPERTY_ID_LEN; + /* TODO: raw value x, column width & raw value y in Sensor Series + * Status are optional, here we need to add some conditions to + * decide whether put these three in the status message. + */ + if (optional) { + length += state->series_column.raw_value_x->len + + state->series_column.column_width->len + + state->series_column.raw_value_y->len; + } + break; + } + } + if (i == srv->state_count) { + BT_WARN("%s, Sensor Property ID 0x%04x does not exist", __func__, prop_id); + length = SENSOR_PROPERTY_ID_LEN; + } + + msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + + /** + * TODO: Sensor Series Get may contain Raw Value X1 and Raw Value X2 which + * identifies a starting column and a ending column, we need to use these + * values to decide the columns. + */ + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS); + net_buf_simple_add_le16(msg, prop_id); + if (i != srv->state_count) { + if (optional) { + net_buf_simple_add_mem(msg, state->series_column.raw_value_x->data, + state->series_column.raw_value_x->len); + net_buf_simple_add_mem(msg, state->series_column.column_width->data, + state->series_column.column_width->len); + net_buf_simple_add_mem(msg, state->series_column.raw_value_y->data, + state->series_column.raw_value_y->len); + } + } + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + return; +} + +static void sensor_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + u16_t set_prop_id = INVALID_SENSOR_PROPERTY_ID; + u16_t prop_id = INVALID_SENSOR_PROPERTY_ID; + + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET: + case BLE_MESH_MODEL_OP_SENSOR_GET: + case BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET: + case BLE_MESH_MODEL_OP_SENSOR_SERIES_GET: { + struct bt_mesh_sensor_srv *srv = model->user_data; + if (srv->state_count == 0U || srv->states == NULL) { + BT_ERR("%s, Invalid Sensor Server state", __func__); + return; + } + if (ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET || + ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_GET) { + bool get_all = buf->len ? false : true; + if (buf->len) { + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Property ID 0x0000", __func__); + return; + } + } + if (ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET) { + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_get_msg_t get = { + .sensor_descriptor_get.op_en = !get_all, + .sensor_descriptor_get.id = prop_id, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + } else { + send_sensor_descriptor_status(model, ctx, prop_id, get_all); + } + } else { + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_get_msg_t get = { + .sensor_get.op_en = !get_all, + .sensor_get.id = prop_id, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + } else { + send_sensor_data_status(model, ctx, prop_id, get_all); + } + } + } else { + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Property ID 0x0000", __func__); + return; + } + if (ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET) { + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_get_msg_t get = { + .sensor_column_get.id = prop_id, + .sensor_column_get.raw_x = buf, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + } else { + send_sensor_column_status(model, ctx, buf, prop_id); + } + } else { + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_get_msg_t get = { + .sensor_series_get.id = prop_id, + .sensor_series_get.raw = buf, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + } else { + send_sensor_series_status(model, ctx, buf, prop_id); + } + } + } + return; + } + case BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET: + case BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET: + case BLE_MESH_MODEL_OP_SENSOR_SETTING_GET: { + struct bt_mesh_sensor_setup_srv *srv = model->user_data; + if (srv->state_count == 0U || srv->states == NULL) { + BT_ERR("%s, Invalid Sensor Setup Server state", __func__); + return; + } + if (ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET || + ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET) { + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Property ID 0x0000", __func__); + return; + } + if (ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET) { + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_get_msg_t get = { + .sensor_cadence_get.id = prop_id, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + } else { + send_sensor_cadence_status(model, ctx, prop_id, false); + } + } else { + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_get_msg_t get = { + .sensor_settings_get.id = prop_id, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + } else { + send_sensor_settings_status(model, ctx, prop_id); + } + } + } else { + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Property ID 0x0000", __func__); + return; + } + set_prop_id = net_buf_simple_pull_le16(buf); + if (set_prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Setting Property ID 0x0000", __func__); + return; + } + + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_get_msg_t get = { + .sensor_setting_get.id = prop_id, + .sensor_setting_get.setting_id = set_prop_id, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + } else { + send_sensor_setting_status(model, ctx, prop_id, set_prop_id, false); + } + } + return; + } + default: + BT_WARN("%s, Unknown Sensor Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } +} + +static void sensor_cadence_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_sensor_setup_srv *srv = model->user_data; + bt_mesh_sensor_server_state_change_t change = {0}; + struct bt_mesh_sensor_state *state = NULL; + struct bt_mesh_model *sensor_model = NULL; + struct bt_mesh_elem *element = NULL; + u16_t prop_id, trigger_len; + u8_t val, divisor; + u8_t i; + + if (srv == NULL || srv->state_count == 0U || srv->states == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Property ID 0x0000", __func__); + return; + } + + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_set_msg_t set = { + .sensor_cadence_set.id = prop_id, + .sensor_cadence_set.cadence = buf, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + break; + } + } + if (i == srv->state_count || state->cadence == NULL) { + /* When the message is sent as a response to the Sensor Cadence Get message or + * a Sensor Cadence Set message with an unknown Property ID field or the Sensor + * Server does not support the Sensor Cadence state for the sensor referred by + * the Property ID, the following fields shall be omitted: + * • Fast Cadence Period Divisor + * • Status Trigger Type + * • Status Trigger Delta Down + * • Status Trigger Delta Up + * • Status Min Interval + * • Fast Cadence Low + * • Fast Cadence High + */ + send_sensor_cadence_status(model, ctx, prop_id, false); + return; + } + + val = net_buf_simple_pull_u8(buf); + divisor = val & BIT_MASK(7); + if (divisor > SENSOR_PERIOD_DIVISOR_MAX_VALUE) { + BT_ERR("%s, Prohibited Fast Cadence Period Divisor 0x%02x", __func__, divisor); + return; + } + state->cadence->period_divisor = divisor; + state->cadence->trigger_type = (val >> 7) & BIT_MASK(1); + + if (state->cadence->trigger_type == SENSOR_STATUS_TRIGGER_TYPE_CHAR) { + trigger_len = bt_mesh_get_dev_prop_len(prop_id); + } else { + trigger_len = SENSOR_STATUS_TRIGGER_UINT16_LEN; + } + if (buf->len < (trigger_len << 1) + SENSOR_STATUS_MIN_INTERVAL_LEN) { + BT_ERR("%s, Invalid Sensor Cadence Set length %d, trigger type %d", + __func__, buf->len + 3, state->cadence->trigger_type); + return; + } + + if (state->cadence->trigger_delta_down) { + net_buf_simple_reset(state->cadence->trigger_delta_down); + net_buf_simple_add_mem(state->cadence->trigger_delta_down, buf->data, trigger_len); + net_buf_simple_pull_mem(buf, trigger_len); + } + if (state->cadence->trigger_delta_up) { + net_buf_simple_reset(state->cadence->trigger_delta_up); + net_buf_simple_add_mem(state->cadence->trigger_delta_up, buf->data, trigger_len); + net_buf_simple_pull_mem(buf, trigger_len); + } + + /* The valid range for the Status Min Interval is 0–26 and other values are Prohibited. */ + val = net_buf_simple_pull_u8(buf); + if (val > SENSOR_STATUS_MIN_INTERVAL_MAX) { + BT_ERR("%s, Invalid Status Min Interval %d", __func__, val); + return; + } + state->cadence->min_interval = val; + + if (buf->len % 2) { + BT_ERR("%s, Different length of Fast Cadence Low & High, length %d", __func__, buf->len); + return; + } + if (buf->len) { + u8_t range_len = buf->len / 2; + if (state->cadence->fast_cadence_low) { + net_buf_simple_reset(state->cadence->fast_cadence_low); + net_buf_simple_add_mem(state->cadence->fast_cadence_low, buf->data, range_len); + net_buf_simple_pull_mem(buf, range_len); + } + if (state->cadence->fast_cadence_high) { + net_buf_simple_reset(state->cadence->fast_cadence_high); + net_buf_simple_add_mem(state->cadence->fast_cadence_high, buf->data, range_len); + net_buf_simple_pull_mem(buf, range_len); + } + } + + change.sensor_cadence_set.id = prop_id; + change.sensor_cadence_set.period_divisor = state->cadence->period_divisor; + change.sensor_cadence_set.trigger_type = state->cadence->trigger_type; + change.sensor_cadence_set.trigger_delta_down = state->cadence->trigger_delta_down; + change.sensor_cadence_set.trigger_delta_up = state->cadence->trigger_delta_up; + change.sensor_cadence_set.min_interval = state->cadence->min_interval; + change.sensor_cadence_set.fast_cadence_low = state->cadence->fast_cadence_low; + change.sensor_cadence_set.fast_cadence_high = state->cadence->fast_cadence_high; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET) { + send_sensor_cadence_status(model, ctx, prop_id, false); + } + send_sensor_cadence_status(model, ctx, prop_id, true); + + /* Try to find the corresponding Sensor Server Model */ + element = bt_mesh_model_elem(model); + sensor_model = bt_mesh_model_find(element, BLE_MESH_MODEL_ID_SENSOR_SRV); + if (sensor_model == NULL) { + BT_WARN("%s, Sensor Server Model does not exist in the element", __func__); + return; + } + + /** + * Based on the configured Sensor Cadence state, change Periodic Sensor + * status publication mechanism. + */ + update_sensor_periodic_pub(sensor_model, prop_id); + return; +} + +static void update_sensor_periodic_pub(struct bt_mesh_model *model, u16_t prop_id) +{ + struct bt_mesh_sensor_state *state = NULL; + struct bt_mesh_sensor_srv *srv = NULL; + u8_t i; + + if (model->id != BLE_MESH_MODEL_ID_SENSOR_SRV) { + BT_ERR("%s, Not a Sensor Server Model", __func__); + return; + } + + srv = (struct bt_mesh_sensor_srv *)model->user_data; + if (srv == NULL || srv->state_count == 0U || srv->states == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + for (i = 0U; i < srv->state_count; i++) { + state = &srv->states[i]; + if (state->sensor_property_id != INVALID_SENSOR_PROPERTY_ID && + state->sensor_property_id == prop_id) { + break; + } + } + if (i == srv->state_count) { + BT_ERR("%s, Sensor Property ID 0x%04x does not exist", __func__, prop_id); + return; + } + + if (state->cadence == NULL) { + BT_WARN("%s, Sensor Cadence state does not exist", __func__); + return; + } + + /** + * Currently when the device receives a Sensor Cadence Set message, + * a event will be callback to the application layer, and users can + * change the Sensor Data publication period in the event. And this + * is exactly what we do for the BQB test. + */ +} + +static void sensor_setting_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_sensor_setup_srv *srv = model->user_data; + bt_mesh_sensor_server_state_change_t change = {0}; + struct sensor_setting *item = NULL; + u16_t prop_id, set_prop_id; + + if (srv == NULL || srv->state_count == 0U || srv->states == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + prop_id = net_buf_simple_pull_le16(buf); + if (prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Property ID 0x0000", __func__); + return; + } + + set_prop_id = net_buf_simple_pull_le16(buf); + if (set_prop_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Prohibited Sensor Setting Property ID 0x0000", __func__); + return; + } + + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_sensor_server_recv_set_msg_t set = { + .sensor_setting_set.id = prop_id, + .sensor_setting_set.setting_id = set_prop_id, + .sensor_setting_set.raw = buf, + }; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + item = find_sensor_setting(model, prop_id, set_prop_id); + if (item) { + if (item->access == SENSOR_SETTING_ACCESS_READ_WRITE && item->raw) { + net_buf_simple_reset(item->raw); + net_buf_simple_add_mem(item->raw, buf->data, + MIN(buf->len, item->raw->size)); + + change.sensor_setting_set.id = prop_id; + change.sensor_setting_set.setting_id = set_prop_id; + change.sensor_setting_set.value = item->raw; + bt_mesh_sensor_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_SENSOR_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + } + } + + if (ctx->recv_op == BLE_MESH_MODEL_OP_SENSOR_SETTING_SET) { + send_sensor_setting_status(model, ctx, prop_id, set_prop_id, false); + } + if (item) { + send_sensor_setting_status(model, ctx, prop_id, set_prop_id, true); + } + + return; +} + +/* message handlers (End) */ + +/* Mapping of message handlers for Sensor Server (0x1100) */ +const struct bt_mesh_model_op sensor_srv_op[] = { + { BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET, 0, sensor_get }, + { BLE_MESH_MODEL_OP_SENSOR_GET, 0, sensor_get }, + { BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET, 2, sensor_get }, + { BLE_MESH_MODEL_OP_SENSOR_SERIES_GET, 2, sensor_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Sensor Setup Server (0x1101) */ +const struct bt_mesh_model_op sensor_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET, 2, sensor_get }, + { BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET, 4, sensor_cadence_set }, + { BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK, 4, sensor_cadence_set }, + { BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET, 2, sensor_get }, + { BLE_MESH_MODEL_OP_SENSOR_SETTING_GET, 4, sensor_get }, + { BLE_MESH_MODEL_OP_SENSOR_SETTING_SET, 4, sensor_setting_set }, + { BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK, 4, sensor_setting_set }, + BLE_MESH_MODEL_OP_END, +}; + +static int check_sensor_server_init(struct bt_mesh_sensor_state *state_start, + const u8_t state_count) +{ + struct bt_mesh_sensor_state *state = NULL; + struct sensor_setting *setting = NULL; + u8_t i, j; + + for (i = 0U; i < state_count; i++) { + state = &state_start[i]; + if (state->sensor_property_id == INVALID_SENSOR_PROPERTY_ID) { + BT_ERR("%s, Invalid Sensor Property ID 0x%04x", __func__, state->sensor_property_id); + return -EINVAL; + } + if (state->setting_count == 0U || state->settings == NULL) { + BT_ERR("%s, Invalid Sensor Setting state", __func__); + return -EINVAL; + } + for (j = 0U; j < state->setting_count; j++) { + setting = &state->settings[j]; + if (setting->property_id == INVALID_SENSOR_SETTING_PROPERTY_ID || setting->raw == NULL) { + BT_ERR("%s, Invalid Sensor Setting state internal parameter", __func__); + return -EINVAL; + } + } + if (state->cadence) { + if (state->cadence->trigger_delta_down == NULL || + state->cadence->trigger_delta_up == NULL || + state->cadence->fast_cadence_low == NULL || + state->cadence->fast_cadence_high == NULL) { + BT_ERR("%s, Invalid Sensor Cadence state", __func__); + return -EINVAL; + } + } + if (state->sensor_data.raw_value == NULL) { + BT_ERR("%s, Invalid Sensor Data state", __func__); + return -EINVAL; + } + if (state->series_column.raw_value_x == NULL || + state->series_column.column_width == NULL || + state->series_column.raw_value_y == NULL) { + BT_ERR("%s, Invalid Sensor Series column state", __func__); + return -EINVAL; + } + } + + return 0; +} + +static int sensor_server_init(struct bt_mesh_model *model) +{ + if (model->user_data == NULL) { + BT_ERR("%s, No Sensor Server context provided, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_SENSOR_SRV: { + struct bt_mesh_sensor_srv *srv = model->user_data; + if (srv->state_count == 0U || srv->states == NULL) { + BT_ERR("%s, Invalid Sensor state parameter, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + if (check_sensor_server_init(srv->states, srv->state_count)) { + BT_ERR("%s, Invalid Sensor Server init value", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV: { + struct bt_mesh_sensor_setup_srv *srv = model->user_data; + if (srv->state_count == 0U || srv->states == NULL) { + BT_ERR("%s, Invalid parameter, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + if (check_sensor_server_init(srv->states, srv->state_count)) { + BT_ERR("%s, Invalid Sensor Setup Server init value", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + default: + BT_WARN("%s, Unknown Sensor Server Model, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + return 0; +} + +int bt_mesh_sensor_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Sensor Server has no publication support", __func__); + return -EINVAL; + } + + /* When this model is present on an element, the corresponding Sensor Setup + * Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_SENSOR_SETUP_SRV) == NULL) { + BT_WARN("%s, Sensor Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return sensor_server_init(model); +} + +int bt_mesh_sensor_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Sensor Setup Server has no publication support", __func__); + return -EINVAL; + } + + return sensor_server_init(model); +} diff --git a/components/bt/esp_ble_mesh/mesh_models/server/server_common.c b/components/bt/esp_ble_mesh/mesh_models/server/server_common.c new file mode 100644 index 000000000..5723c640e --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/server_common.c @@ -0,0 +1,256 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "osi/allocator.h" + +#include "mesh_types.h" +#include "mesh_kernel.h" +#include "mesh_trace.h" +#include "mesh.h" +#include "access.h" +#include "model_opcode.h" + +#include "server_common.h" +#include "state_binding.h" +#include "state_transition.h" + +/** + * According to Mesh Model Spec: + * If the Transition Time field is not present and the Generic Default Transition + * Time state is supported, the Generic Default Transition Time state shall be + * used. Otherwise the transition shall be instantaneous. + */ +#define INSTANTANEOUS_TRANS_TIME 0 + +u8_t bt_mesh_get_default_trans_time(struct bt_mesh_model *model) +{ + /** + * 1. If a Generic Default Transition Time Server model is present on the + * main element of the model, that model instance shall be used. + * 2. If a Generic Default Transition Time Server model is not present on + * the main element of the model, then the Generic Default Transition + * Time Server model instance that is present on the element with the + * largest address that is smaller than the address of the main element + * of the node shall be used; if no model instance is present on any + * element with an address smaller than the address of the main element, + * then the Generic Default Transition Time Server is not supported. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + struct bt_mesh_gen_def_trans_time_srv *state = NULL; + u16_t primary_addr = bt_mesh_primary_addr(); + struct bt_mesh_model *srv = NULL; + + for (u16_t addr = element->addr; addr >= primary_addr; addr--) { + element = bt_mesh_elem_find(addr); + if (element) { + srv = bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV); + if (srv) { + state = (struct bt_mesh_gen_def_trans_time_srv *)srv->user_data; + if (state) { + return state->state.trans_time; + } + } + } + } + + return INSTANTANEOUS_TRANS_TIME; +} + +int bt_mesh_get_light_lc_trans_time(struct bt_mesh_model *model, u8_t *trans_time) +{ + struct bt_mesh_light_lc_srv *srv = NULL; + u32_t value; + + if (model == NULL || trans_time == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + if (model->id != BLE_MESH_MODEL_ID_LIGHT_LC_SRV) { + BT_ERR("%s, Not a Light LC Server", __func__); + return -EINVAL; + } + + srv = (struct bt_mesh_light_lc_srv *)model->user_data; + if (srv == NULL) { + BT_ERR("%s, Invalid Light LC Server user_data", __func__); + return -EINVAL; + } + + /** + * 1. Set transition time to 0x54 for BQB test case MESH/SR/LLC/BV-04-C. + * Light LC Property Set: 0x3C, 0x004E20 -> Light LC Time Run On + * Light LC Property Set: 0x37, 0x004E20 -> Light LC Time Fade On + * Light LC Property Set: 0x39, 0x004E20 -> Light LC Time Fade Standby Manual + * + * 2. Set transition time to 0x0 for BQB test case MESH/SR/LLC/BV-08-C. + * + * TODO: Based on Light LC state and choose property property value as the + * transition time. Currently directly use Light LC Time Run On property value. + * Unit: Millisecond, range: [0, 16777214(0xFFFFFE)] + */ + value = srv->lc->prop_state.time_run_on & 0xFFFFFF; + + /** + * Convert value into Default Transition Time state format. + * 0b00: 0 ~ 6.2s, 100 millisecond step resolution + * 0b01: 0 ~ 62s, 1 second step resolution + * 0b10: 0 ~ 620s, 10 seconds step resolution + * 0b11: 0 ~ 620m, 10 minutes step resolution + */ + if (value <= 6200) { + *trans_time = (0 << 6) | (value / 100); + } else if (value <= 62000) { + *trans_time = (1 << 6) | (value / 1000); + } else if (value <= 620000) { + *trans_time = (2 << 6) | (value / 10000); + } else { + *trans_time = (3 << 6) | (value / 600000); + } + + return 0; +} + +int bt_mesh_server_get_optional(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf, + u8_t *trans_time, u8_t *delay, + bool *optional) +{ + if (model == NULL || buf == NULL || trans_time == NULL || + delay == NULL || optional == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + if (buf->len != 0x00 && buf->len != 0x02) { + BT_ERR("%s, Invalid optional message length %d", __func__, buf->len); + return -EINVAL; + } + + /* Currently we only get optional msg info which dst is set to a unicast address */ + if (!BLE_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) { + *trans_time = 0U; + *delay = 0U; + *optional = false; + return 0; + } + + /* No optional fields are available */ + if (buf->len == 0x00) { + if (model->id == BLE_MESH_MODEL_ID_LIGHT_LC_SRV) { + /** + * Both messages(i.e. Light LC OnOff Set/Set Unack) may optionally include + * a Transition Time field indicating the transition time to the target state. + * If the Transition Time is not included, the Light LC Server shall use + * its appropriate transition times defined by the Light LC Property states. + */ + if (bt_mesh_get_light_lc_trans_time(model, trans_time)) { + BT_ERR("%s, Failed to get Light LC transition time", __func__); + return -EIO; + } + } else { + *trans_time = bt_mesh_get_default_trans_time(model); + } + *delay = 0U; + *optional = false; + return 0; + } + + /* Optional fields are available */ + *trans_time = net_buf_simple_pull_u8(buf); + if ((*trans_time & 0x3F) == 0x3F) { + BT_ERR("%s, Invalid Transaction Number of Steps 0x3F", __func__); + return -EINVAL; + } + + *delay = net_buf_simple_pull_u8(buf); + *optional = true; + return 0; +} + +void bt_mesh_server_alloc_ctx(struct k_work *work) +{ + /** + * This function is used to allocate memory for storing "struct bt_mesh_msg_ctx" + * of the received messages, because some server models will callback the "struct + * bt_mesh_msg_ctx" info to the application layer after a certain delay. + * Here we use the allocated heap memory to store the "struct bt_mesh_msg_ctx". + */ + __ASSERT(work, "%s, Invalid parameter", __func__); + work->_reserved = osi_calloc(sizeof(struct bt_mesh_msg_ctx)); + __ASSERT(work->_reserved, "%s, Failed to allocate memory", __func__); +} + +bool bt_mesh_is_server_recv_last_msg(struct bt_mesh_last_msg_info *last, + u8_t tid, u16_t src, u16_t dst, s64_t *now) +{ + *now = k_uptime_get(); + + /* Currently we only compare msg info which dst is set to a unicast address */ + if (!BLE_MESH_ADDR_IS_UNICAST(dst)) { + return false; + } + + if (last->tid == tid && last->src == src && last->dst == dst && + (*now - last->timestamp <= K_SECONDS(6))) { + return true; + } + + return false; +} + +void bt_mesh_server_update_last_msg(struct bt_mesh_last_msg_info *last, + u8_t tid, u16_t src, u16_t dst, s64_t *now) +{ + /* Currently we only update msg info which dst is set to a unicast address */ + if (!BLE_MESH_ADDR_IS_UNICAST(dst)) { + return; + } + + last->tid = tid; + last->src = src; + last->dst = dst; + last->timestamp = *now; + return; +} + +struct net_buf_simple *bt_mesh_server_get_pub_msg(struct bt_mesh_model *model, u16_t msg_len) +{ + struct net_buf_simple *buf = NULL; + + if (model == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return NULL; + } + + if (model->pub == NULL || model->pub->msg == NULL || + model->pub->addr == BLE_MESH_ADDR_UNASSIGNED) { + BT_DBG("%s, Model 0x%04x has no publication support", __func__, model->id); + return NULL; + } + + buf = model->pub->msg; + if (buf->size < msg_len) { + BT_ERR("%s, Too small publication msg size %d, model 0x%04x", + __func__, buf->size, model->id); + return NULL; + } + + return buf; +} \ No newline at end of file diff --git a/components/bt/esp_ble_mesh/mesh_models/server/state_binding.c b/components/bt/esp_ble_mesh/mesh_models/server/state_binding.c new file mode 100644 index 000000000..f45216a18 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/state_binding.c @@ -0,0 +1,342 @@ +/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "mesh_types.h" +#include "mesh_kernel.h" +#include "mesh_trace.h" +#include "mesh.h" + +#include "model_opcode.h" +#include "server_common.h" +#include "state_binding.h" +#include "state_transition.h" +#include "generic_server.h" +#include "lighting_server.h" + +#define MINDIFF (2.25e-308) + +static float bt_mesh_sqrt(float square) +{ + float root, last, diff; + + root = square / 3.0; + diff = 1; + + if (square <= 0) { + return 0; + } + + do { + last = root; + root = (root + square / root) / 2.0; + diff = root - last; + } while (diff > MINDIFF || diff < -MINDIFF); + + return root; +} + +static s32_t bt_mesh_ceiling(float num) +{ + s32_t inum = (s32_t)num; + + if (num == (float)inum) { + return inum; + } + + return inum + 1; +} + +u16_t bt_mesh_convert_lightness_actual_to_linear(u16_t actual) +{ + float tmp = ((float) actual / UINT16_MAX); + + return bt_mesh_ceiling(UINT16_MAX * tmp * tmp); +} + +u16_t bt_mesh_convert_lightness_linear_to_actual(u16_t linear) +{ + return (u16_t) (UINT16_MAX * bt_mesh_sqrt(((float) linear / UINT16_MAX))); +} + +s16_t bt_mesh_convert_temperature_to_gen_level(u16_t temp, u16_t min, u16_t max) +{ + float tmp = (temp - min) * UINT16_MAX / (max - min); + return (s16_t) (tmp + INT16_MIN); +} + +u16_t bt_mesh_covert_gen_level_to_temperature(s16_t level, u16_t min, u16_t max) +{ + float diff = (float) (max - min) / UINT16_MAX; + u16_t tmp = (u16_t) ((level - INT16_MIN) * diff); + return (u16_t) (min + tmp); +} + +s16_t bt_mesh_convert_hue_to_level(u16_t hue) +{ + return (s16_t) (hue + INT16_MIN); +} + +u16_t bt_mesh_convert_level_to_hue(s16_t level) +{ + return (u16_t) (level - INT16_MIN); +} + +s16_t bt_mesh_convert_saturation_to_level(u16_t saturation) +{ + return (s16_t) (saturation + INT16_MIN); +} + +u16_t bt_mesh_convert_level_to_saturation(s16_t level) +{ + return (u16_t) (level - INT16_MIN); +} + +int bt_mesh_update_binding_state(struct bt_mesh_model *model, + bt_mesh_server_state_type_t type, + bt_mesh_server_state_value_t *value) +{ + if (model == NULL || model->user_data == NULL || + value == NULL || type > BIND_STATE_MAX) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + switch (type) { + case GENERIC_ONOFF_STATE: { + if (model->id != BLE_MESH_MODEL_ID_GEN_ONOFF_SRV) { + BT_ERR("%s, Not a Generic OnOff Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_gen_onoff_srv *srv = model->user_data; + bt_mesh_server_stop_transition(&srv->transition); + srv->state.onoff = value->gen_onoff.onoff; + gen_onoff_publish(model); + break; + } + case GENERIC_LEVEL_STATE: { + if (model->id != BLE_MESH_MODEL_ID_GEN_LEVEL_SRV) { + BT_ERR("%s, Not a Generic Level Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_gen_level_srv *srv = model->user_data; + bt_mesh_server_stop_transition(&srv->transition); + srv->state.level = value->gen_level.level; + gen_level_publish(model); + break; + } + case GENERIC_ONPOWERUP_STATE: { + if (model->id != BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV) { + BT_ERR("%s, Not a Generic Power OnOff Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_gen_power_onoff_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Generic Power OnOff Server state", __func__); + return -EINVAL; + } + + srv->state->onpowerup = value->gen_onpowerup.onpowerup; + gen_onpowerup_publish(model); + break; + } + case GENERIC_POWER_ACTUAL_STATE: { + if (model->id != BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV) { + BT_ERR("%s, Not a Generic Power Level Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_gen_power_level_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Generic Power Level Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->state->power_actual = value->gen_power_actual.power; + /** + * Whenever the Generic Power Actual state is changed to a non-zero value + * as a result of a non-transactional message or a completed sequence of + * transactional messages, the value of the Generic Power Last state shall + * be set to the value of the Generic Power Actual state. + */ + if (srv->state->power_actual) { + srv->state->power_last = srv->state->power_actual; + } + gen_power_level_publish(model, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + break; + } + case LIGHT_LIGHTNESS_ACTUAL_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) { + BT_ERR("%s, Not a Light Lightness Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_lightness_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light Lightness Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->actual_transition); + srv->state->lightness_actual = value->light_lightness_actual.lightness; + light_lightness_publish(model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + break; + } + case LIGHT_LIGHTNESS_LINEAR_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) { + BT_ERR("%s, Not a Light Lightness Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_lightness_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light Lightness Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->linear_transition); + srv->state->lightness_linear = value->light_lightness_linear.lightness; + light_lightness_publish(model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + break; + } + case LIGHT_CTL_LIGHTNESS_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_CTL_SRV) { + BT_ERR("%s, Not a Light CTL Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_ctl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light CTL Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->state->lightness = value->light_ctl_lightness.lightness; + light_ctl_publish(model, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + break; + } + case LIGHT_CTL_TEMP_DELTA_UV_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV) { + BT_ERR("%s, Not a Light CTL Temperature Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_ctl_temp_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light CTL Temperature Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->state->temperature = value->light_ctl_temp_delta_uv.temperature; + srv->state->delta_uv = value->light_ctl_temp_delta_uv.delta_uv; + light_ctl_publish(model, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + break; + } + case LIGHT_HSL_LIGHTNESS_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_HSL_SRV) { + BT_ERR("%s, Not a Light HSL Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_hsl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->state->lightness = value->light_hsl_lightness.lightness; + light_hsl_publish(model, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + break; + } + case LIGHT_HSL_HUE_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV) { + BT_ERR("%s, Not a Light HSL Hue Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_hsl_hue_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Hue Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->state->hue = value->light_hsl_hue.hue; + light_hsl_publish(model, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + break; + } + case LIGHT_HSL_SATURATION_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV) { + BT_ERR("%s, Not a Light HSL Saturation Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_hsl_sat_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light HSL Saturation Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->state->saturation = value->light_hsl_saturation.saturation; + light_hsl_publish(model, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + break; + } + case LIGHT_XYL_LIGHTNESS_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_XYL_SRV) { + BT_ERR("%s, Not a Light xyL Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_xyl_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Light xyL Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->state->lightness = value->light_xyl_lightness.lightness; + light_xyl_publish(model, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + break; + } + case LIGHT_LC_LIGHT_ONOFF_STATE: { + if (model->id != BLE_MESH_MODEL_ID_LIGHT_LC_SRV) { + BT_ERR("%s, Not a Light LC Server Model, id 0x%04x", __func__, model->id); + return -EINVAL; + } + + struct bt_mesh_light_lc_srv *srv = model->user_data; + if (srv->lc == NULL) { + BT_ERR("%s, Invalid Light LC Server state", __func__); + return -EINVAL; + } + + bt_mesh_server_stop_transition(&srv->transition); + srv->lc->state.light_onoff = value->light_lc_light_onoff.onoff; + light_lc_publish(model, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + break; + } + default: + BT_WARN("%s, Unknown binding state type 0x%02x", __func__, type); + return -EINVAL; + } + + return 0; +} + diff --git a/components/bt/esp_ble_mesh/mesh_models/server/state_transition.c b/components/bt/esp_ble_mesh/mesh_models/server/state_transition.c new file mode 100644 index 000000000..da05cec19 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/state_transition.c @@ -0,0 +1,1034 @@ +/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models + * + * Copyright (c) 2018 Vikrant More + * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "mesh_types.h" +#include "mesh_kernel.h" +#include "mesh_trace.h" +#include "mesh.h" +#include "model_opcode.h" + +#include "server_common.h" +#include "state_binding.h" +#include "state_transition.h" +#include "generic_server.h" +#include "lighting_server.h" +#include "time_scene_server.h" + +#include "btc_ble_mesh_generic_model.h" +#include "btc_ble_mesh_lighting_model.h" +#include "btc_ble_mesh_time_scene_model.h" +#include "btc_ble_mesh_sensor_model.h" + +/* Function to calculate Remaining Time (Start) */ + +void bt_mesh_server_calc_remain_time(struct bt_mesh_state_transition *transition) +{ + u8_t steps, resolution; + s32_t duration_remainder; + s64_t now; + + if (transition->just_started) { + transition->remain_time = transition->trans_time; + } else { + now = k_uptime_get(); + duration_remainder = transition->total_duration - + (now - transition->start_timestamp); + if (duration_remainder > 620000) { + /* > 620 seconds -> resolution = 0b11 [10 minutes] */ + resolution = 0x03; + steps = duration_remainder / 600000; + } else if (duration_remainder > 62000) { + /* > 62 seconds -> resolution = 0b10 [10 seconds] */ + resolution = 0x02; + steps = duration_remainder / 10000; + } else if (duration_remainder > 6200) { + /* > 6.2 seconds -> resolution = 0b01 [1 seconds] */ + resolution = 0x01; + steps = duration_remainder / 1000; + } else if (duration_remainder > 0) { + /* <= 6.2 seconds -> resolution = 0b00 [100 ms] */ + resolution = 0x00; + steps = duration_remainder / 100; + } else { + resolution = 0x00; + steps = 0x00; + } + + transition->remain_time = (resolution << 6) | steps; + } +} + +/* Function to calculate Remaining Time (End) */ + +static void tt_values_calculator(struct bt_mesh_state_transition *transition) +{ + u8_t steps_multiplier, resolution; + + resolution = (transition->trans_time >> 6); + steps_multiplier = (transition->trans_time & 0x3F); + + switch (resolution) { + case 0: /* 100ms */ + transition->total_duration = steps_multiplier * 100; + break; + case 1: /* 1 second */ + transition->total_duration = steps_multiplier * 1000; + break; + case 2: /* 10 seconds */ + transition->total_duration = steps_multiplier * 10000; + break; + case 3: /* 10 minutes */ + transition->total_duration = steps_multiplier * 600000; + break; + } + + transition->counter = ((float) transition->total_duration / 100); + + if (transition->counter > BLE_MESH_DEVICE_SPECIFIC_RESOLUTION) { + transition->counter = BLE_MESH_DEVICE_SPECIFIC_RESOLUTION; + } +} + +static void transition_time_values(struct bt_mesh_state_transition *transition, + u8_t trans_time, u8_t delay) +{ + transition->trans_time = trans_time; + transition->delay = delay; + + if (trans_time == 0U) { + return; + } + + tt_values_calculator(transition); + transition->quo_tt = transition->total_duration / transition->counter; +} + +void generic_onoff_tt_values(struct bt_mesh_gen_onoff_srv *srv, + u8_t trans_time, u8_t delay) +{ + return transition_time_values(&srv->transition, trans_time, delay); +} + +void generic_level_tt_values(struct bt_mesh_gen_level_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_level = + ((float) (srv->state.level - srv->state.target_level) / srv->transition.counter); +} + +void generic_power_level_tt_values(struct bt_mesh_gen_power_level_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_level = + ((float) (srv->state->power_actual - srv->state->target_power_actual) / srv->transition.counter); +} + +void light_lightness_actual_tt_values(struct bt_mesh_light_lightness_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->actual_transition, trans_time, delay); + srv->tt_delta_lightness_actual = + ((float) (srv->state->lightness_actual - srv->state->target_lightness_actual) / srv->actual_transition.counter); +} + +void light_lightness_linear_tt_values(struct bt_mesh_light_lightness_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->linear_transition, trans_time, delay); + srv->tt_delta_lightness_linear = + ((float) (srv->state->lightness_linear - srv->state->target_lightness_linear) / srv->linear_transition.counter); +} + +void light_ctl_tt_values(struct bt_mesh_light_ctl_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_lightness = + ((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter); + srv->tt_delta_temperature = + ((float) (srv->state->temperature - srv->state->target_temperature) / srv->transition.counter); + srv->tt_delta_delta_uv = + ((float) (srv->state->delta_uv - srv->state->target_delta_uv) / srv->transition.counter); +} + +void light_ctl_temp_tt_values(struct bt_mesh_light_ctl_temp_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_temperature = + ((float) (srv->state->temperature - srv->state->target_temperature) / srv->transition.counter); + srv->tt_delta_delta_uv = + ((float) (srv->state->delta_uv - srv->state->target_delta_uv) / srv->transition.counter); +} + +void light_hsl_tt_values(struct bt_mesh_light_hsl_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_lightness = + ((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter); + srv->tt_delta_hue = + ((float) (srv->state->hue - srv->state->target_hue) / srv->transition.counter); + srv->tt_delta_saturation = + ((float) (srv->state->saturation - srv->state->target_saturation) / srv->transition.counter); +} + +void light_hsl_hue_tt_values(struct bt_mesh_light_hsl_hue_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_hue = + ((float) (srv->state->hue - srv->state->target_hue) / srv->transition.counter); +} + +void light_hsl_sat_tt_values(struct bt_mesh_light_hsl_sat_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_saturation = + ((float) (srv->state->saturation - srv->state->target_saturation) / srv->transition.counter); +} + +void light_xyl_tt_values(struct bt_mesh_light_xyl_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); + srv->tt_delta_lightness = + ((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter); + srv->tt_delta_x = + ((float) (srv->state->x - srv->state->target_x) / srv->transition.counter); + srv->tt_delta_y = + ((float) (srv->state->y - srv->state->target_y) / srv->transition.counter); +} + +void light_lc_tt_values(struct bt_mesh_light_lc_srv *srv, + u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); +} + +void scene_tt_values(struct bt_mesh_scene_srv *srv, u8_t trans_time, u8_t delay) +{ + transition_time_values(&srv->transition, trans_time, delay); +} + +static void transition_timer_start(struct bt_mesh_state_transition *transition) +{ + transition->start_timestamp = k_uptime_get(); + k_delayed_work_submit_periodic(&transition->timer, K_MSEC(transition->quo_tt)); + bt_mesh_atomic_set_bit(transition->flag, BLE_MESH_TRANS_TIMER_START); +} + +static void transition_timer_stop(struct bt_mesh_state_transition *transition) +{ + k_delayed_work_cancel(&transition->timer); + bt_mesh_atomic_clear_bit(transition->flag, BLE_MESH_TRANS_TIMER_START); +} + +/* Timers related handlers & threads (Start) */ +void generic_onoff_work_handler(struct k_work *work) +{ + struct bt_mesh_gen_onoff_srv *srv = + CONTAINER_OF(work, struct bt_mesh_gen_onoff_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_gen_server_state_change_t change = {0}; + + if (srv == NULL || srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_generic_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.gen_onoff_set.onoff = srv->state.onoff; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + /** + * Because binary states cannot support transitions, when changing to + * 0x01 (On), the Generic OnOff state shall change immediately when + * the transition starts, and when changing to 0x00, the state shall + * change when the transition finishes. + */ + if (srv->state.target_onoff == BLE_MESH_STATE_ON) { + srv->state.onoff = BLE_MESH_STATE_ON; + change.gen_onoff_set.onoff = srv->state.onoff; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + } + transition_timer_start(&srv->transition); + } + + bt_mesh_generic_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state.onoff = srv->state.target_onoff; + if (srv->state.target_onoff != BLE_MESH_STATE_ON) { + change.gen_onoff_set.onoff = srv->state.onoff; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + } + } + + gen_onoff_publish(srv->model); + + bt_mesh_generic_server_unlock(); + return; +} + +void generic_level_work_handler(struct k_work *work) +{ + struct bt_mesh_gen_level_srv *srv = + CONTAINER_OF(work, struct bt_mesh_gen_level_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_gen_server_state_change_t change = {0}; + + if (srv == NULL || srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_generic_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_LEVEL_SET: + case BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK: + change.gen_level_set.level = srv->state.level; + break; + case BLE_MESH_MODEL_OP_GEN_DELTA_SET: + case BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK: + change.gen_delta_set.level = srv->state.level; + break; + case BLE_MESH_MODEL_OP_GEN_MOVE_SET: + case BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK: + change.gen_move_set.level = srv->state.level; + break; + } + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_generic_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state.level -= srv->tt_delta_level; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state.level = srv->state.target_level; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_GEN_LEVEL_SET: + case BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK: + change.gen_level_set.level = srv->state.level; + break; + case BLE_MESH_MODEL_OP_GEN_DELTA_SET: + case BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK: + change.gen_delta_set.level = srv->state.level; + break; + case BLE_MESH_MODEL_OP_GEN_MOVE_SET: + case BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK: + change.gen_move_set.level = srv->state.level; + break; + } + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + gen_level_publish(srv->model); + + bt_mesh_generic_server_unlock(); + return; +} + +void generic_power_level_work_handler(struct k_work *work) +{ + struct bt_mesh_gen_power_level_srv *srv = + CONTAINER_OF(work, struct bt_mesh_gen_power_level_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_gen_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_generic_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.gen_power_level_set.power = srv->state->power_actual; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_generic_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state->power_actual -= srv->tt_delta_level; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + + srv->state->power_actual = srv->state->target_power_actual; + /** + * Whenever the Generic Power Actual state is changed to a non-zero value + * as a result of a non-transactional message or a completed sequence of + * transactional messages, the value of the Generic Power Last state shall + * be set to the value of the Generic Power Actual state. + */ + if (srv->state->power_actual) { + srv->state->power_last = srv->state->power_actual; + } + } + + change.gen_power_level_set.power = srv->state->power_actual; + bt_mesh_generic_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + gen_power_level_publish(srv->model, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS); + + bt_mesh_generic_server_unlock(); + return; +} + +void light_lightness_actual_work_handler(struct k_work *work) +{ + struct bt_mesh_light_lightness_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_lightness_srv, actual_transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->actual_transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->actual_transition.timer.work._reserved; + + if (srv->actual_transition.just_started) { + srv->actual_transition.just_started = false; + if (srv->actual_transition.counter == 0U) { + change.lightness_set.lightness = srv->state->lightness_actual; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->actual_transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->actual_transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->actual_transition.counter != 0U) { + srv->actual_transition.counter--; + srv->state->lightness_actual -= srv->tt_delta_lightness_actual; + } + + if (srv->actual_transition.counter == 0U) { + transition_timer_stop(&srv->actual_transition); + + srv->state->lightness_actual = srv->state->target_lightness_actual; + /** + * Whenever the Light Lightness Actual state is changed with a non- + * transactional message or a completed sequence of transactional + * messages to a non-zero value, the value of the Light Lightness + * Last shall be set to the value of the Light Lightness Actual. + */ + if (srv->state->lightness_actual) { + srv->state->lightness_last = srv->state->lightness_actual; + } + } + + change.lightness_set.lightness = srv->state->lightness_actual; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_lightness_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_lightness_linear_work_handler(struct k_work *work) +{ + struct bt_mesh_light_lightness_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_lightness_srv, linear_transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->linear_transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->linear_transition.timer.work._reserved; + + if (srv->linear_transition.just_started) { + srv->linear_transition.just_started = false; + if (srv->linear_transition.counter == 0U) { + change.lightness_linear_set.lightness = srv->state->lightness_linear; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->linear_transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->linear_transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->linear_transition.counter != 0U) { + srv->linear_transition.counter--; + srv->state->lightness_linear -= srv->tt_delta_lightness_linear; + } + + if (srv->linear_transition.counter == 0U) { + transition_timer_stop(&srv->linear_transition); + srv->state->lightness_linear = srv->state->target_lightness_linear; + } + + change.lightness_linear_set.lightness = srv->state->lightness_linear; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_lightness_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_ctl_work_handler(struct k_work *work) +{ + struct bt_mesh_light_ctl_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_ctl_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.ctl_set.lightness = srv->state->lightness; + change.ctl_set.temperature = srv->state->temperature; + change.ctl_set.delta_uv = srv->state->delta_uv; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state->lightness -= srv->tt_delta_lightness; + srv->state->temperature -= srv->tt_delta_temperature; + srv->state->delta_uv -= srv->tt_delta_delta_uv; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state->lightness = srv->state->target_lightness; + srv->state->temperature = srv->state->target_temperature; + srv->state->delta_uv = srv->state->target_delta_uv; + } + + change.ctl_set.lightness = srv->state->lightness; + change.ctl_set.temperature = srv->state->temperature; + change.ctl_set.delta_uv = srv->state->delta_uv; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_ctl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_ctl_temp_work_handler(struct k_work *work) +{ + struct bt_mesh_light_ctl_temp_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_ctl_temp_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.ctl_temp_set.temperature = srv->state->temperature; + change.ctl_temp_set.delta_uv = srv->state->delta_uv; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state->temperature -= srv->tt_delta_temperature; + srv->state->delta_uv -= srv->tt_delta_delta_uv; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state->temperature = srv->state->target_temperature; + srv->state->delta_uv = srv->state->target_delta_uv; + } + + change.ctl_temp_set.temperature = srv->state->temperature; + change.ctl_temp_set.delta_uv = srv->state->delta_uv; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_ctl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_hsl_work_handler(struct k_work *work) +{ + struct bt_mesh_light_hsl_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_hsl_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.hsl_set.lightness = srv->state->lightness; + change.hsl_set.hue = srv->state->hue; + change.hsl_set.saturation = srv->state->saturation; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state->lightness -= srv->tt_delta_lightness; + srv->state->hue -= srv->tt_delta_hue; + srv->state->saturation -= srv->tt_delta_saturation; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state->lightness = srv->state->target_lightness; + srv->state->hue = srv->state->target_hue; + srv->state->saturation = srv->state->target_saturation; + } + + change.hsl_set.lightness = srv->state->lightness; + change.hsl_set.hue = srv->state->hue; + change.hsl_set.saturation = srv->state->saturation; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_hsl_hue_work_handler(struct k_work *work) +{ + struct bt_mesh_light_hsl_hue_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_hsl_hue_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.hsl_hue_set.hue = srv->state->hue; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state->hue -= srv->tt_delta_hue; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state->hue = srv->state->target_hue; + } + + change.hsl_hue_set.hue = srv->state->hue; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_hsl_sat_work_handler(struct k_work *work) +{ + struct bt_mesh_light_hsl_sat_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_hsl_sat_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.hsl_saturation_set.saturation = srv->state->saturation; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state->saturation -= srv->tt_delta_saturation; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state->saturation = srv->state->target_saturation; + } + + change.hsl_saturation_set.saturation = srv->state->saturation; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_xyl_work_handler(struct k_work *work) +{ + struct bt_mesh_light_xyl_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_xyl_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.xyl_set.lightness = srv->state->lightness; + change.xyl_set.x = srv->state->x; + change.xyl_set.y = srv->state->y; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + srv->state->lightness -= srv->tt_delta_lightness; + srv->state->x -= srv->tt_delta_x; + srv->state->y -= srv->tt_delta_y; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state->lightness = srv->state->target_lightness; + srv->state->x = srv->state->target_x; + srv->state->y = srv->state->target_y; + } + + change.xyl_set.lightness = srv->state->lightness; + change.xyl_set.x = srv->state->x; + change.xyl_set.y = srv->state->y; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + light_xyl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void light_lc_work_handler(struct k_work *work) +{ + struct bt_mesh_light_lc_srv *srv = + CONTAINER_OF(work, struct bt_mesh_light_lc_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_light_server_state_change_t change = {0}; + + if (srv == NULL || srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_light_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.lc_light_onoff_set.onoff = srv->lc->state.light_onoff; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + /** + * Because binary states cannot support transitions, when changing to + * 0x01 (On), the Generic OnOff state shall change immediately when + * the transition starts, and when changing to 0x00, the state shall + * change when the transition finishes. + */ + if (srv->lc->state.target_light_onoff == BLE_MESH_STATE_ON) { + srv->lc->state.light_onoff = BLE_MESH_STATE_ON; + bt_mesh_light_server_state_change_t change = { + .lc_light_onoff_set.onoff = srv->lc->state.light_onoff, + }; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + } + transition_timer_start(&srv->transition); + } + + bt_mesh_light_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->lc->state.light_onoff = srv->lc->state.target_light_onoff; + if (srv->lc->state.light_onoff != BLE_MESH_STATE_ON) { + change.lc_light_onoff_set.onoff = srv->lc->state.light_onoff; + bt_mesh_lighting_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + } + } + + light_lc_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS); + + bt_mesh_light_server_unlock(); + return; +} + +void scene_recall_work_handler(struct k_work *work) +{ + struct bt_mesh_scene_srv *srv = + CONTAINER_OF(work, struct bt_mesh_scene_srv, transition.timer.work); + struct bt_mesh_msg_ctx *ctx = NULL; + bt_mesh_time_scene_server_state_change_t change = {0}; + + if (srv == NULL || srv->state == NULL || + srv->transition.timer.work._reserved == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + bt_mesh_time_scene_server_lock(); + + ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved; + + if (srv->transition.just_started) { + srv->transition.just_started = false; + if (srv->transition.counter == 0U) { + change.scene_recall.scene_number = srv->state->current_scene; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START); + } else { + transition_timer_start(&srv->transition); + } + + bt_mesh_time_scene_server_unlock(); + return; + } + + if (srv->transition.counter != 0U) { + srv->transition.counter--; + } + + if (srv->transition.counter == 0U) { + transition_timer_stop(&srv->transition); + srv->state->current_scene = srv->state->target_scene; + srv->state->in_progress = false; + srv->state->target_scene = INVALID_SCENE_NUMBER; + } + + change.scene_recall.scene_number = srv->state->current_scene; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change)); + + scene_publish(srv->model, ctx, BLE_MESH_MODEL_OP_SCENE_STATUS); + + bt_mesh_time_scene_server_unlock(); + return; +} + +/* Timers related handlers & threads (End) */ + +void bt_mesh_server_stop_transition(struct bt_mesh_state_transition *transition) +{ + memset(transition, 0x0, offsetof(struct bt_mesh_state_transition, flag)); + if (bt_mesh_atomic_test_and_clear_bit(transition->flag, BLE_MESH_TRANS_TIMER_START)) { + k_delayed_work_cancel(&transition->timer); + } +} + +void bt_mesh_server_start_transition(struct bt_mesh_state_transition *transition) +{ + if (transition->delay) { + k_delayed_work_submit(&transition->timer, K_MSEC(5 * transition->delay)); + bt_mesh_atomic_set_bit(transition->flag, BLE_MESH_TRANS_TIMER_START); + } else { + k_work_submit(&transition->timer.work); + } +} + +/* Messages handlers (End) */ diff --git a/components/bt/esp_ble_mesh/mesh_models/server/time_scene_server.c b/components/bt/esp_ble_mesh/mesh_models/server/time_scene_server.c new file mode 100644 index 000000000..fec69b166 --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/time_scene_server.c @@ -0,0 +1,1424 @@ +// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "osi/mutex.h" + +#include "mesh_types.h" +#include "mesh_kernel.h" +#include "mesh_trace.h" +#include "mesh.h" +#include "access.h" +#include "model_opcode.h" +#include "transport.h" + +#include "server_common.h" +#include "state_binding.h" +#include "state_transition.h" +#include "time_scene_server.h" + +#include "btc_ble_mesh_time_scene_model.h" + +static osi_mutex_t time_scene_server_mutex; + +static void bt_mesh_time_scene_server_mutex_new(void) +{ + if (!time_scene_server_mutex) { + osi_mutex_new(&time_scene_server_mutex); + __ASSERT(time_scene_server_mutex, "%s, fail", __func__); + } +} + +void bt_mesh_time_scene_server_lock(void) +{ + osi_mutex_lock(&time_scene_server_mutex, OSI_MUTEX_MAX_TIMEOUT); +} + +void bt_mesh_time_scene_server_unlock(void) +{ + osi_mutex_unlock(&time_scene_server_mutex); +} + +/* message handlers (Start) */ + +/* Time Server & Time Setup Server message handlers */ +static void send_time_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish, u16_t opcode) +{ + struct net_buf_simple *msg = NULL; + u8_t zero[5] = {0}; + u8_t length = 1 + 10; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, opcode); + switch (opcode) { + case BLE_MESH_MODEL_OP_TIME_STATUS: + if (model->id == BLE_MESH_MODEL_ID_TIME_SRV) { + struct bt_mesh_time_srv *srv = model->user_data; + net_buf_simple_add_mem(msg, srv->state->time.tai_seconds, TAI_SECONDS_LEN); + if (memcmp(srv->state->time.tai_seconds, zero, TAI_SECONDS_LEN)) { + net_buf_simple_add_u8(msg, srv->state->time.subsecond); + /** + * Set the Uncertainty field to a value that is a sum of the value of + * the Uncertainty state and an estimated time it will take the message + * to be processed before being sent on the radio interface. + * + * TODO: how to estimate the processing time? + */ + net_buf_simple_add_u8(msg, srv->state->time.uncertainty); + net_buf_simple_add_le16(msg, + (srv->state->time.tai_utc_delta_curr << 1) | srv->state->time.time_authority); + net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr); + } + } else if (model->id == BLE_MESH_MODEL_ID_TIME_SETUP_SRV) { + struct bt_mesh_time_setup_srv *srv = model->user_data; + net_buf_simple_add_mem(msg, srv->state->time.tai_seconds, TAI_SECONDS_LEN); + if (memcmp(srv->state->time.tai_seconds, zero, TAI_SECONDS_LEN)) { + net_buf_simple_add_u8(msg, srv->state->time.subsecond); + net_buf_simple_add_u8(msg, srv->state->time.uncertainty); + net_buf_simple_add_le16(msg, + (srv->state->time.tai_utc_delta_curr << 1) | srv->state->time.time_authority); + net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr); + } + } + break; + case BLE_MESH_MODEL_OP_TIME_ZONE_STATUS: + if (model->id == BLE_MESH_MODEL_ID_TIME_SRV) { + struct bt_mesh_time_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr); + net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_new); + net_buf_simple_add_mem(msg, srv->state->time.tai_zone_change, TAI_OF_ZONE_CHANGE_LEN); + } else if (model->id == BLE_MESH_MODEL_ID_TIME_SETUP_SRV) { + struct bt_mesh_time_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr); + net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_new); + net_buf_simple_add_mem(msg, srv->state->time.tai_zone_change, TAI_OF_ZONE_CHANGE_LEN); + } + break; + case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS: + if (model->id == BLE_MESH_MODEL_ID_TIME_SRV) { + struct bt_mesh_time_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_curr); + net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_new); + net_buf_simple_add_mem(msg, srv->state->time.tai_delta_change, TAI_OF_DELTA_CHANGE_LEN); + } else if (model->id == BLE_MESH_MODEL_ID_TIME_SETUP_SRV) { + struct bt_mesh_time_setup_srv *srv = model->user_data; + net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_curr); + net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_new); + net_buf_simple_add_mem(msg, srv->state->time.tai_delta_change, TAI_OF_DELTA_CHANGE_LEN); + } + break; + case BLE_MESH_MODEL_OP_TIME_ROLE_STATUS: { + struct bt_mesh_time_setup_srv *srv = model->user_data; + net_buf_simple_add_u8(msg, srv->state->time_role); + break; + } + default: + BT_WARN("%s, Unknown Time status opcode 0x%04x", __func__, opcode); + if (publish == false) { + bt_mesh_free_buf(msg); + } + return; + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void time_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_server_rsp_ctrl *rsp_ctrl = NULL; + u8_t zero[5] = {0}; + u16_t opcode, val; + u8_t prev_ttl; + + if (model->user_data == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_TIME_SRV: { + struct bt_mesh_time_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Time Server state", __func__); + return; + } + rsp_ctrl = &srv->rsp_ctrl; + break; + } + case BLE_MESH_MODEL_ID_TIME_SETUP_SRV: { + struct bt_mesh_time_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Time Setup Server state", __func__); + return; + } + rsp_ctrl = &srv->rsp_ctrl; + break; + } + default: + BT_ERR("%s, Invalid Time Server 0x%04x", __func__, model->id); + return; + } + + if (rsp_ctrl->get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + if (ctx->recv_op != BLE_MESH_MODEL_OP_TIME_STATUS) { + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_TIME_GET: + opcode = BLE_MESH_MODEL_OP_TIME_STATUS; + break; + case BLE_MESH_MODEL_OP_TIME_STATUS: { + struct bt_mesh_time_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, Invalid Time Server state", __func__); + return; + } + if (srv->state->time_role != TIME_RELAY && + srv->state->time_role != TIME_CLINET) { + /** + * If the value of the Time Role state of the element is 0x00 (None) or + * 0x01 (Time Authority), the message shall be ignored. + */ + return; + } + if (rsp_ctrl->status_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_status_msg_t status = {0}; + memcpy(status.time_status.tai_seconds, buf->data, TAI_SECONDS_LEN); + net_buf_simple_pull(buf, TAI_SECONDS_LEN); + if (memcmp(status.time_status.tai_seconds, zero, TAI_SECONDS_LEN)) { + if (buf->len != TAI_SECONDS_LEN) { + BT_ERR("%s, Invalid Time Status length %d", __func__, buf->len + TAI_SECONDS_LEN); + return; + } + status.time_status.subsecond = net_buf_simple_pull_u8(buf); + status.time_status.uncertainty = net_buf_simple_pull_u8(buf); + val = net_buf_simple_pull_le16(buf); + status.time_status.time_authority = val & BIT(0); + status.time_status.tai_utc_delta = (val >> 1) & BIT_MASK(15); + status.time_status.time_zone_offset = net_buf_simple_pull_u8(buf); + } + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_STATUS_MSG, model, ctx, (const u8_t *)&status, sizeof(status)); + return; + } + memcpy(srv->state->time.tai_seconds, buf->data, TAI_SECONDS_LEN); + net_buf_simple_pull(buf, TAI_SECONDS_LEN); + /** + * If the TAI Seconds field is 0x0000000000 the Subsecond, Uncertainty, + * Time Authority, TAI-UTC Delta and Time Zone Offset fields shall be + * omitted; otherwise these fields shall be present. + */ + if (memcmp(srv->state->time.tai_seconds, zero, TAI_SECONDS_LEN)) { + if (buf->len != TAI_SECONDS_LEN) { + BT_ERR("%s, Invalid Time Status length %d", __func__, buf->len + TAI_SECONDS_LEN); + return; + } + srv->state->time.subsecond = net_buf_simple_pull_u8(buf); + srv->state->time.uncertainty = net_buf_simple_pull_u8(buf); + val = net_buf_simple_pull_le16(buf); + srv->state->time.tai_utc_delta_curr = (val >> 1) & BIT_MASK(15); + srv->state->time.time_zone_offset_curr = net_buf_simple_pull_u8(buf); + } + + bt_mesh_time_scene_server_state_change_t change = {0}; + memcpy(change.time_status.tai_seconds, srv->state->time.tai_seconds, TAI_SECONDS_LEN); + change.time_status.subsecond = srv->state->time.subsecond; + change.time_status.uncertainty = srv->state->time.uncertainty; + change.time_status.time_authority = srv->state->time.time_authority; + change.time_status.tai_utc_delta_curr = srv->state->time.subsecond; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (model->pub == NULL || model->pub->msg == NULL || + model->pub->addr == BLE_MESH_ADDR_UNASSIGNED) { + return; + } + prev_ttl = model->pub->ttl; + if (srv->state->time_role == TIME_RELAY) { + /** + * Shall publish a Time Status message using TTL = 0 if the value of the + * Time Role state is 0x02 (Time Relay) and the Publish Address for the + * Time Server model is not set to unassigned address. + */ + model->pub->ttl = 0U; + } + send_time_status(model, NULL, true, BLE_MESH_MODEL_OP_TIME_STATUS); + /* Restore model publication ttl value */ + model->pub->ttl = prev_ttl; + return; + } + case BLE_MESH_MODEL_OP_TIME_ZONE_GET: + opcode = BLE_MESH_MODEL_OP_TIME_ZONE_STATUS; + break; + case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET: + opcode = BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS; + break; + case BLE_MESH_MODEL_OP_TIME_ROLE_GET: + opcode = BLE_MESH_MODEL_OP_TIME_ROLE_STATUS; + break; + default: + BT_WARN("%s, Unknown Time Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + send_time_status(model, ctx, false, opcode); + return; +} + +static void time_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_time_setup_srv *srv = model->user_data; + bt_mesh_time_scene_server_state_change_t change = {0}; + u16_t opcode, val; + u8_t role; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_TIME_SET: + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = {0}; + memcpy(set.time_set.tai_seconds, buf->data, TAI_SECONDS_LEN); + net_buf_simple_pull(buf, TAI_SECONDS_LEN); + set.time_set.subsecond = net_buf_simple_pull_u8(buf); + set.time_set.uncertainty = net_buf_simple_pull_u8(buf); + val = net_buf_simple_pull_le16(buf); + set.time_set.time_authority = val & BIT(0); + set.time_set.tai_utc_delta = (val >> 1) & BIT_MASK(15); + set.time_set.time_zone_offset = net_buf_simple_pull_u8(buf); + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + memcpy(srv->state->time.tai_seconds, buf->data, TAI_SECONDS_LEN); + net_buf_simple_pull(buf, TAI_SECONDS_LEN); + srv->state->time.subsecond = net_buf_simple_pull_u8(buf); + srv->state->time.uncertainty = net_buf_simple_pull_u8(buf); + val = net_buf_simple_pull_le16(buf); + srv->state->time.time_authority = val & BIT(0); + srv->state->time.tai_utc_delta_curr = (val >> 1) & BIT_MASK(15); + srv->state->time.time_zone_offset_curr = net_buf_simple_pull_u8(buf); + opcode = BLE_MESH_MODEL_OP_TIME_STATUS; + break; + case BLE_MESH_MODEL_OP_TIME_ZONE_SET: + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = {0}; + set.time_zone_set.time_zone_offset_new = net_buf_simple_pull_u8(buf); + memcpy(set.time_zone_set.tai_zone_change, buf->data, TAI_OF_ZONE_CHANGE_LEN); + net_buf_simple_pull(buf, TAI_OF_ZONE_CHANGE_LEN); + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + srv->state->time.time_zone_offset_new = net_buf_simple_pull_u8(buf); + memcpy(srv->state->time.tai_zone_change, buf->data, TAI_OF_ZONE_CHANGE_LEN); + net_buf_simple_pull(buf, TAI_OF_ZONE_CHANGE_LEN); + opcode = BLE_MESH_MODEL_OP_TIME_ZONE_STATUS; + break; + case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET: + val = net_buf_simple_pull_le16(buf); + if ((val >> 15) & BIT(0)) { + BT_ERR("%s, Invalid Padding value 1", __func__); + return; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = {0}; + set.tai_utc_delta_set.tai_utc_delta_new = val & BIT_MASK(15); + memcpy(set.tai_utc_delta_set.tai_delta_change, buf->data, TAI_OF_DELTA_CHANGE_LEN); + net_buf_simple_pull(buf, TAI_OF_DELTA_CHANGE_LEN); + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + srv->state->time.tai_utc_delta_new = val & BIT_MASK(15); + memcpy(srv->state->time.tai_delta_change, buf->data, TAI_OF_DELTA_CHANGE_LEN); + net_buf_simple_pull(buf, TAI_OF_DELTA_CHANGE_LEN); + opcode = BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS; + break; + case BLE_MESH_MODEL_OP_TIME_ROLE_SET: + role = net_buf_simple_pull_u8(buf); + if (role > TIME_CLINET) { + BT_ERR("%s, Invalid Time Role 0x%02x", __func__, role); + return; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = { + .time_role_set.time_role = role, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + srv->state->time_role = role; + opcode = BLE_MESH_MODEL_OP_TIME_ROLE_STATUS; + break; + default: + BT_ERR("%s, Unknown Time Set opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_TIME_SET: + memcpy(change.time_set.tai_seconds, srv->state->time.tai_seconds, TAI_SECONDS_LEN); + change.time_set.subsecond = srv->state->time.subsecond; + change.time_set.uncertainty = srv->state->time.uncertainty; + change.time_set.time_authority = srv->state->time.time_authority; + change.time_set.tai_utc_delta_curr = srv->state->time.subsecond; + break; + case BLE_MESH_MODEL_OP_TIME_ZONE_SET: + change.time_zone_set.time_zone_offset_new = srv->state->time.time_zone_offset_new; + memcpy(change.time_zone_set.tai_zone_change, srv->state->time.tai_zone_change, TAI_OF_ZONE_CHANGE_LEN); + break; + case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET: + change.tai_utc_delta_set.tai_utc_delta_new = srv->state->time.tai_utc_delta_new; + memcpy(change.tai_utc_delta_set.tai_delta_change, srv->state->time.tai_delta_change, TAI_OF_DELTA_CHANGE_LEN); + break; + case BLE_MESH_MODEL_OP_TIME_ROLE_SET: + change.time_role_set.role = srv->state->time_role; + break; + default: + return; + } + + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + /* Send corresponding time status message */ + send_time_status(model, ctx, false, opcode); + return; +} + +/* Scene Server & Scene Setup Server message handlers */ +static void send_scene_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + bool publish) +{ + struct bt_mesh_scene_srv *srv = model->user_data; + struct net_buf_simple *msg = NULL; + u8_t length = 1 + 6; + + if (publish == false) { + msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, length); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SCENE_STATUS); + /** + * If the message is sent as a reply to the Scene Recall message, the + * Status Code field identifies the result of the related operation; + * otherwise, the Status Code field shall be set to Success. + */ + if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_GET) { + net_buf_simple_add_u8(msg, SCENE_SUCCESS); + } else { + net_buf_simple_add_u8(msg, srv->state->status_code); + } + net_buf_simple_add_le16(msg, srv->state->current_scene); + /** + * When an element is in the process of changing the Scene state, the + * Target Scene field identifies the target Scene Number of the target + * Scene state the element is to reach. + * When an element is not in the process of changing the Scene state, + * the Target Scene field shall be omitted. + */ + if (srv->transition.counter) { + bt_mesh_server_calc_remain_time(&srv->transition); + net_buf_simple_add_le16(msg, srv->state->target_scene); + net_buf_simple_add_u8(msg, srv->transition.remain_time); + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void send_scene_register_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u8_t status_code, bool publish) +{ + struct bt_mesh_scene_setup_srv *srv = model->user_data; + struct scene_register *scene = NULL; + struct net_buf_simple *msg = NULL; + u16_t total_len = 9; + u16_t i; + + if (ctx == NULL && publish == false) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + if (publish == false) { + msg = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)); + if (msg == NULL) { + BT_ERR("%s, Failed to allocate memory", __func__); + return; + } + } else { + msg = bt_mesh_server_get_pub_msg(model, 5); + if (msg == NULL) { + return; + } + } + + bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS); + net_buf_simple_add_u8(msg, status_code); + net_buf_simple_add_le16(msg, srv->state->current_scene); + + for (i = 0U; i < srv->state->scene_count; i++) { + scene = &srv->state->scenes[i]; + if (scene->scene_number != INVALID_SCENE_NUMBER) { + total_len += SCENE_NUMBER_LEN; + if ((publish == false && total_len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)) || + (publish == true && total_len > msg->size + BLE_MESH_SERVER_TRANS_MIC_SIZE)) { + /* Add this in case the message is too long */ + break; + } + net_buf_simple_add_le16(msg, scene->scene_number); + } + } + + if (publish == false) { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL)); + bt_mesh_free_buf(msg); + } else { + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model)); + } + return; +} + +static void scene_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_scene_srv *srv = model->user_data; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_SCENE_GET: + send_scene_status(model, ctx, false); + return; + case BLE_MESH_MODEL_OP_SCENE_REGISTER_GET: + /** + * When a Scene Server receives a Scene Register Get message, it shall + * respond with a Scene Register Status message, setting the Status + * Code field to Success. + */ + send_scene_register_status(model, ctx, SCENE_SUCCESS, false); + return; + default: + BT_WARN("%s, Unknown Scene Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } +} + +void scene_publish(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, u16_t opcode) +{ + struct bt_mesh_scene_srv *srv = model->user_data; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + send_scene_status(model, ctx, true); + return; +} + +static void scene_recall(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_scene_srv *srv = model->user_data; + struct scene_register *scene = NULL; + u8_t tid, trans_time, delay; + u16_t scene_number; + bool optional; + s64_t now; + u16_t i; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + scene_number = net_buf_simple_pull_le16(buf); + if (scene_number == INVALID_SCENE_NUMBER) { + BT_ERR("%s, Invalid Scene Number 0x0000", __func__); + return; + } + tid = net_buf_simple_pull_u8(buf); + + if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) { + return; + } + + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = { + .scene_recall.op_en = optional, + .scene_recall.scene_number = scene_number, + .scene_recall.tid = tid, + .scene_recall.trans_time = trans_time, + .scene_recall.delay = delay, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + for (i = 0U; i < srv->state->scene_count; i++) { + scene = &srv->state->scenes[i]; + if (scene->scene_number == scene_number) { + break; + } + } + if (i == srv->state->scene_count) { + BT_WARN("%s, Scene Number 0x%04x not exist", __func__, scene_number); + srv->state->status_code = SCENE_NOT_FOUND; + if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) { + send_scene_status(model, ctx, false); + } + send_scene_status(model, ctx, true); + return; + } + srv->state->status_code = SCENE_SUCCESS; + + /* Mesh Model Spec doesn't mention about this operation. */ + if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) { + if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) { + send_scene_status(model, ctx, false); + } + send_scene_status(model, ctx, true); + /* In this condition, no event will be callback to application layer */ + return; + } + + bt_mesh_time_scene_server_lock(); + + bt_mesh_server_stop_transition(&srv->transition); + bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now); + + srv->state->in_progress = false; + /** + * When the scene transition is not in progress, the value of the Target + * Scene state shall be set to 0x0000. + */ + srv->state->target_scene = INVALID_SCENE_NUMBER; + + /** + * If the target state is equal to the current state, the transition + * shall not be started and is considered complete. + */ + if (srv->state->current_scene != scene_number) { + scene_tt_values(srv, trans_time, delay); + } else { + if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) { + send_scene_status(model, ctx, false); + } + send_scene_status(model, ctx, true); + + bt_mesh_time_scene_server_state_change_t change = { + .scene_recall.scene_number = scene_number, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + bt_mesh_time_scene_server_unlock(); + return; + } + + /* Copy the ctx of the received message */ + if (srv->transition.timer.work._reserved) { + memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx)); + } + + /* For Instantaneous Transition */ + if (srv->transition.counter == 0U) { + srv->state->current_scene = scene_number; + } else { + /** + * When a scene transition is in progress, the value of the Current + * Scene state shall be set to 0x0000. + */ + srv->state->in_progress = true; + srv->state->current_scene = INVALID_SCENE_NUMBER; + srv->state->target_scene = scene_number; + } + + srv->transition.just_started = true; + if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) { + send_scene_status(model, ctx, false); + } + send_scene_status(model, ctx, true); + + bt_mesh_time_scene_server_unlock(); + + bt_mesh_server_start_transition(&srv->transition); + return; +} + +static void scene_action(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_scene_setup_srv *srv = model->user_data; + struct scene_register *scene = NULL; + u16_t scene_number; + u16_t i; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + scene_number = net_buf_simple_pull_le16(buf); + if (scene_number == INVALID_SCENE_NUMBER) { + BT_ERR("%s, Invalid Scene number 0x0000", __func__); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_SCENE_STORE: + case BLE_MESH_MODEL_OP_SCENE_STORE_UNACK: { + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = { + .scene_store.scene_number = scene_number, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + /* Try to find a matching Scene Number */ + for (i = 0U; i < srv->state->scene_count; i++) { + scene = &srv->state->scenes[i]; + if (scene->scene_number == scene_number) { + srv->state->status_code = SCENE_SUCCESS; + srv->state->current_scene = scene_number; + break; + } + } + /* Try to find a unset entry if no matching Scene Number is found */ + if (i == srv->state->scene_count) { + BT_DBG("%s, No matching Scene Number 0x%04x found", __func__, scene_number); + for (i = 0U; i < srv->state->scene_count; i++) { + scene = &srv->state->scenes[i]; + if (scene->scene_number == INVALID_SCENE_NUMBER) { + scene->scene_number = scene_number; + srv->state->status_code = SCENE_SUCCESS; + srv->state->current_scene = scene_number; + break; + } + } + if (i == srv->state->scene_count) { + BT_WARN("%s, Scene Register full", __func__); + srv->state->status_code = SCENE_REG_FULL; + /* Get the Scene Number of the currently active scene */ + for (i = 0; i < srv->state->scene_count; i++) { + scene = &srv->state->scenes[i]; + if (scene->scene_number != INVALID_SCENE_NUMBER) { + srv->state->current_scene = scene->scene_number; + break; + } + } + if (i == srv->state->scene_count) { + /* A value of 0x0000 when no scene is active */ + srv->state->current_scene = INVALID_SCENE_NUMBER; + } + } + } + + if (srv->state->in_progress == true) { + /** + * When the scene transition is in progress and a new Scene Number is + * stored in the Scene Register as a result of Scene Store operation, + * the Target Scene state shall be set to the new Scene Number. + */ + srv->state->target_scene = scene_number; + } + if (srv->state->status_code == SCENE_SUCCESS) { + bt_mesh_time_scene_server_state_change_t change = { + .scene_store.scene_number = scene_number, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + } + break; + } + case BLE_MESH_MODEL_OP_SCENE_DELETE: + case BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK: { + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = { + .scene_delete.scene_number = scene_number, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + for (i = 0U; i < srv->state->scene_count; i++) { + scene = &srv->state->scenes[i]; + if (scene->scene_number == scene_number) { + scene->scene_number = INVALID_SCENE_NUMBER; + break; + } + } + if (i == srv->state->scene_count) { + BT_WARN("%s, Scene Number 0x%04x not exist", __func__, scene_number); + /** + * When a Scene Server receives a Scene Delete message with the Scene + * Number value that does not match a Scene Number stored within the + * Scene Register state, it shall respond with the Scene Register + * Status message, setting the Status Code field to Success. + */ + } + srv->state->status_code = SCENE_SUCCESS; + if (srv->state->current_scene == scene_number) { + /** + * When the Current Scene Number is deleted from a Scene Register state + * as a result of Scene Delete operation, the Current Scene state shall + * be set to 0x0000. + */ + srv->state->current_scene = INVALID_SCENE_NUMBER; + } else { + /** + * MMDL/SR/SCES/BV-02-C requires response with Current Scene set to the + * latest Scene Number, but this is not mentioned in the spec. + * + * TODO: Do we need a timestamp for each newly added scene? + */ + for (i = srv->state->scene_count; i > 0; i--) { + scene = &srv->state->scenes[i - 1]; + if (scene->scene_number != INVALID_SCENE_NUMBER) { + srv->state->current_scene = scene->scene_number; + break; + } + } + if (i == 0U) { + /* A value of 0x0000 when no scene is active */ + srv->state->current_scene = INVALID_SCENE_NUMBER; + } + } + + if (srv->state->target_scene == scene_number && + srv->state->in_progress == true) { + /** + * When the scene transition is in progress and the target Scene Number + * is deleted from a Scene Register state as a result of Scene Delete + * operation, the Target Scene state shall be set to 0x0000. + */ + srv->state->target_scene = INVALID_SCENE_NUMBER; + + /** + * When a scene is deleted when a scene transition to the deleted Scene + * Number is in progress, the scene transition shall be terminated, but + * individual model transitions shall not be terminated. + */ + struct bt_mesh_scene_srv *scene_srv = NULL; + struct bt_mesh_model *scene_model = NULL; + + scene_model = bt_mesh_model_find(bt_mesh_model_elem(model), BLE_MESH_MODEL_ID_SCENE_SRV); + if (scene_model == NULL) { + BT_ERR("%s, Scene Server is not present in the element", __func__); + break; + } + + scene_srv = scene_model->user_data; + if (scene_srv == NULL || scene_srv->state == NULL) { + BT_ERR("%s, Invalid Scene Server parameter", __func__); + break; + } + + if (srv->state != scene_srv->state) { + /** + * Add this in case the Scene Setup Server is extending the Scene + * Server in another element. + */ + BT_WARN("%s, Different Scene state in Scene Server & Scene Setup Server", __func__); + break; + } + + scene_srv->state->in_progress = false; + bt_mesh_server_stop_transition(&scene_srv->transition); + } + + bt_mesh_time_scene_server_state_change_t change = { + .scene_delete.scene_number = scene_number, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + break; + } + default: + BT_ERR("%s, Unknown Scene setup action opcode 0x%04x", __func__, ctx->recv_op); + return; + } + + if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_STORE || + ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_DELETE) { + send_scene_register_status(model, ctx, srv->state->status_code, false); + } + send_scene_register_status(model, NULL, srv->state->status_code, true); + + return; +} + +static u16_t get_schedule_reg_bit(struct bt_mesh_scheduler_state *state) +{ + u16_t val = 0; + u8_t i; + + for (i = 0U; i < state->schedule_count; i++) { + if (state->schedules[i].in_use) { + val |= (1 << i); + } + } + + return val; +} + +static u64_t get_schedule_reg_state(struct bt_mesh_scheduler_state *state, u8_t index) +{ + struct schedule_register *reg = &state->schedules[index]; + u64_t val; + + val = ((u64_t)(reg->year) << 4) | index; + val |= ((u64_t)(reg->day) << 23) | ((u64_t)(reg->month) << 11); + val |= ((u64_t)(reg->minute) << 33) | ((u64_t)(reg->hour) << 28); + val |= ((u64_t)(reg->day_of_week) << 45) | ((u64_t)(reg->second) << 39); + val |= ((u64_t)(reg->trans_time) << 56) | ((u64_t)(reg->action) << 52); + + return val; +} + +static void send_scheduler_act_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + u8_t index) +{ + NET_BUF_SIMPLE_DEFINE(msg, 1 + 10 + BLE_MESH_SERVER_TRANS_MIC_SIZE); + u64_t value; + + bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS); + switch (model->id) { + case BLE_MESH_MODEL_ID_SCHEDULER_SRV: { + struct bt_mesh_scheduler_srv *srv = model->user_data; + value = get_schedule_reg_state(srv->state, index); + net_buf_simple_add_le32(&msg, (u32_t)value); + net_buf_simple_add_le32(&msg, (u32_t)(value >> 32)); + net_buf_simple_add_le16(&msg, srv->state->schedules[index].scene_number); + break; + } + case BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV: { + struct bt_mesh_scheduler_setup_srv *srv = model->user_data; + value = get_schedule_reg_state(srv->state, index); + net_buf_simple_add_le32(&msg, (u32_t)value); + net_buf_simple_add_le32(&msg, (u32_t)(value >> 32)); + net_buf_simple_add_le16(&msg, srv->state->schedules[index].scene_number); + break; + } + default: + BT_ERR("%s, Invalid Scheduler Server 0x%04x", __func__, model->id); + return; + } + + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL)); + return; +} + +static void scheduler_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + struct bt_mesh_scheduler_srv *srv = model->user_data; + NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE); + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + switch (ctx->recv_op) { + case BLE_MESH_MODEL_OP_SCHEDULER_GET: { + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, NULL, 0); + return; + } + + bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_SCHEDULER_STATUS); + net_buf_simple_add_le16(&msg, get_schedule_reg_bit(srv->state)); + BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL)); + return; + } + case BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET: { + u8_t index = net_buf_simple_pull_u8(buf); + if (index > SCHEDULE_ENTRY_MAX_INDEX) { + BT_ERR("%s, Invalid Scheduler Register Entry index 0x%02x", __func__, index); + return; + } + + if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_get_msg_t get = { + .scheduler_act_get.index = index, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get)); + return; + } + + send_scheduler_act_status(model, ctx, index); + return; + } + default: + BT_WARN("%s, Unknown Scheduler Get opcode 0x%04x", __func__, ctx->recv_op); + return; + } +} + +static void scheduler_act_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + /** + * A recommended implementation of the Scheduler should calculate the value + * of the TAI Seconds of the next scheduled event and put it in a queue of + * scheduled events sorted by time. Every second, the first event in the + * queue is compared with the value of the Time state. The first event is + * executed if it is less than or equal to the Time state and then removed + * from the queue. After execution, the Repeat Flag shall be checked, and + * the next occurrence of the scheduled event is calculated and put in the + * queue. + */ + struct bt_mesh_scheduler_setup_srv *srv = model->user_data; + u8_t index, year, day, hour, minute, second, day_of_week, action, trans_time; + u16_t month, scene_number; + u64_t value; + + if (srv == NULL || srv->state == NULL) { + BT_ERR("%s, Invalid model user_data", __func__); + return; + } + + value = net_buf_simple_pull_le32(buf); + value |= ((u64_t)net_buf_simple_pull_le32(buf) << 32); + + index = value & BIT_MASK(4); + year = (value >> 4) & BIT_MASK(7); + month = (value >> 11) & BIT_MASK(12); + day = (value >> 23) & BIT_MASK(5); + hour = (value >> 28) & BIT_MASK(5); + minute = (value >> 33) & BIT_MASK(6); + second = (value >> 39) & BIT_MASK(6); + day_of_week = (value >> 45) & BIT_MASK(7); + action = (value >> 52) & BIT_MASK(4); + trans_time = (value >> 56) & BIT_MASK(8); + + if (index > SCHEDULE_ENTRY_MAX_INDEX) { + BT_ERR("%s, Invalid Scheduler Register Entry index 0x%02x", __func__, index); + return; + } + + if (year > SCHEDULE_YEAR_ANY_YEAR) { + BT_ERR("%s, Invalid Scheduler Register year 0x%02x", __func__, year); + return; + } + + if (hour > SCHEDULE_HOUR_ONCE_A_DAY) { + BT_ERR("%s, Invalid Scheduler Register hour 0x%02x", __func__, hour); + return; + } + + if (action > SCHEDULE_ACT_SCENE_RECALL && action != SCHEDULE_ACT_NO_ACTION) { + BT_ERR("%s, Invalid Scheduler Register action 0x%02x", __func__, action); + return; + } + + scene_number = net_buf_simple_pull_le16(buf); + + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) { + bt_mesh_time_scene_server_recv_set_msg_t set = { + .scheduler_act_set.index = index, + .scheduler_act_set.year = year, + .scheduler_act_set.month = month, + .scheduler_act_set.day = day, + .scheduler_act_set.hour = hour, + .scheduler_act_set.minute = minute, + .scheduler_act_set.second = second, + .scheduler_act_set.day_of_week = day_of_week, + .scheduler_act_set.action = action, + .scheduler_act_set.trans_time = trans_time, + .scheduler_act_set.scene_number = scene_number, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set)); + return; + } + + srv->state->schedules[index].in_use = true; + srv->state->schedules[index].year = year; + srv->state->schedules[index].month = month; + srv->state->schedules[index].day = day; + srv->state->schedules[index].hour = hour; + srv->state->schedules[index].minute = minute; + srv->state->schedules[index].second = second; + srv->state->schedules[index].day_of_week = day_of_week; + srv->state->schedules[index].action = action; + srv->state->schedules[index].trans_time = trans_time; + srv->state->schedules[index].scene_number = scene_number; + + bt_mesh_time_scene_server_state_change_t change = { + .scheduler_act_set.index = index, + .scheduler_act_set.year = year, + .scheduler_act_set.month = month, + .scheduler_act_set.day = day, + .scheduler_act_set.hour = hour, + .scheduler_act_set.minute = minute, + .scheduler_act_set.second = second, + .scheduler_act_set.day_of_week = day_of_week, + .scheduler_act_set.action = action, + .scheduler_act_set.trans_time = trans_time, + .scheduler_act_set.scene_number = scene_number, + }; + bt_mesh_time_scene_server_cb_evt_to_btc( + BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change)); + + if (ctx->recv_op == BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET) { + send_scheduler_act_status(model, ctx, index); + } + + return; +} + +/* message handlers (End) */ + +/* Mapping of message handlers for Time Server (0x1200) */ +const struct bt_mesh_model_op time_srv_op[] = { + { BLE_MESH_MODEL_OP_TIME_GET, 0, time_get }, + { BLE_MESH_MODEL_OP_TIME_STATUS, 5, time_get }, + { BLE_MESH_MODEL_OP_TIME_ZONE_GET, 0, time_get }, + { BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET, 0, time_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Time Setup Server (0x1201) */ +const struct bt_mesh_model_op time_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_TIME_SET, 10, time_set }, + { BLE_MESH_MODEL_OP_TIME_ZONE_SET, 6, time_set }, + { BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET, 7, time_set }, + { BLE_MESH_MODEL_OP_TIME_ROLE_GET, 0, time_get }, + { BLE_MESH_MODEL_OP_TIME_ROLE_SET, 1, time_set }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Scene Server (0x1203) */ +const struct bt_mesh_model_op scene_srv_op[] = { + { BLE_MESH_MODEL_OP_SCENE_GET, 0, scene_get }, + { BLE_MESH_MODEL_OP_SCENE_RECALL, 3, scene_recall }, + { BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK, 3, scene_recall }, + { BLE_MESH_MODEL_OP_SCENE_REGISTER_GET, 0, scene_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Scene Setup Server (0x1204) */ +const struct bt_mesh_model_op scene_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_SCENE_STORE, 2, scene_action }, + { BLE_MESH_MODEL_OP_SCENE_STORE_UNACK, 2, scene_action }, + { BLE_MESH_MODEL_OP_SCENE_DELETE, 2, scene_action }, + { BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK, 2, scene_action }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Scheduler Server (0x1206) */ +const struct bt_mesh_model_op scheduler_srv_op[] = { + { BLE_MESH_MODEL_OP_SCHEDULER_GET, 0, scheduler_get }, + { BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET, 1, scheduler_get }, + BLE_MESH_MODEL_OP_END, +}; + +/* Mapping of message handlers for Scheduler Setup Server (0x1207) */ +const struct bt_mesh_model_op scheduler_setup_srv_op[] = { + { BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET, 10, scheduler_act_set }, + { BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK, 10, scheduler_act_set }, + BLE_MESH_MODEL_OP_END, +}; + +static int check_scene_server_init(struct bt_mesh_scenes_state *state) +{ + u16_t i; + + if (state->scene_count == 0U || state->scenes == NULL) { + BT_ERR("%s, Invalid Scene state", __func__); + return -EINVAL; + } + + for (i = 0U; i < state->scene_count; i++) { + if (state->scenes[i].scene_value == NULL) { + BT_ERR("%s, Invalid Scene value, index %d", __func__, i); + return -EINVAL; + } + } + + return 0; +} + +static int time_scene_server_init(struct bt_mesh_model *model) +{ + if (model->user_data == NULL) { + BT_ERR("%s, No Time Scene Server context provided, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + switch (model->id) { + case BLE_MESH_MODEL_ID_TIME_SRV: { + struct bt_mesh_time_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Time State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_TIME_SETUP_SRV: { + struct bt_mesh_time_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Time State", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_SCENE_SRV: { + struct bt_mesh_scene_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Scene State", __func__); + return -EINVAL; + } + if (check_scene_server_init(srv->state)) { + return -EINVAL; + } + if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) { + bt_mesh_server_alloc_ctx(&srv->transition.timer.work); + k_delayed_work_init(&srv->transition.timer, scene_recall_work_handler); + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_SCENE_SETUP_SRV: { + struct bt_mesh_scene_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Scene State", __func__); + return -EINVAL; + } + if (check_scene_server_init(srv->state)) { + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_SCHEDULER_SRV: { + struct bt_mesh_scheduler_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Scheduler State", __func__); + return -EINVAL; + } + if (srv->state->schedule_count == 0U || srv->state->schedules == NULL) { + BT_ERR("%s, NULL Register Schedule", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + case BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV: { + struct bt_mesh_scheduler_setup_srv *srv = model->user_data; + if (srv->state == NULL) { + BT_ERR("%s, NULL Scheduler State", __func__); + return -EINVAL; + } + if (srv->state->schedule_count == 0U || srv->state->schedules == NULL) { + BT_ERR("%s, NULL Register Schedule", __func__); + return -EINVAL; + } + srv->model = model; + break; + } + default: + BT_WARN("%s, Unknown Time Scene Server Model, model_id 0x%04x", __func__, model->id); + return -EINVAL; + } + + bt_mesh_time_scene_server_mutex_new(); + + return 0; +} + +int bt_mesh_time_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Time Server has no publication support", __func__); + return -EINVAL; + } + + /** + * When this model is present on an Element, the corresponding Time Setup + * Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_TIME_SETUP_SRV) == NULL) { + BT_WARN("%s, Time Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return time_scene_server_init(model); +} + +int bt_mesh_time_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + /* This model does not support subscribing nor publishing */ + if (model->pub) { + BT_ERR("%s, Time Setup Server shall not support publication", __func__); + return -EINVAL; + } + + return time_scene_server_init(model); +} + +int bt_mesh_scene_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Scene Server has no publication support", __func__); + return -EINVAL; + } + + /* The model may be present only on the Primary element of a node. */ + if (primary == false) { + BT_WARN("%s, Scene Server is not on the Primary element", __func__); + /* Just give a warning here, continue with the initialization */ + } + /** + * When this model is present on an Element, the corresponding Scene Setup + * Server model shall also be present. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_SCENE_SETUP_SRV) == NULL) { + BT_WARN("%s, Scene Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return time_scene_server_init(model); +} + +int bt_mesh_scene_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + /* The model may be present only on the Primary element of a node. */ + if (primary == false) { + BT_WARN("%s, Scene Setup Server is not on the Primary element", __func__); + /* Just give a warning here, continue with the initialization */ + } + return time_scene_server_init(model); +} + +int bt_mesh_scheduler_srv_init(struct bt_mesh_model *model, bool primary) +{ + if (model->pub == NULL) { + BT_ERR("%s, Scheduler Server has no publication support", __func__); + return -EINVAL; + } + + /* The model may be present only on the Primary element of a node. */ + if (primary == false) { + BT_WARN("%s, Scheduler Server is not on the Primary element", __func__); + /* Just give a warning here, continue with the initialization */ + } + /** + * When this model is present on an Element, the corresponding Scheduler + * Setup Server model shall also be present. The model requires the Time + * Server model shall be present on the element. + */ + struct bt_mesh_elem *element = bt_mesh_model_elem(model); + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV) == NULL) { + BT_WARN("%s, Scheduler Setup Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_TIME_SRV) == NULL) { + BT_WARN("%s, Time Server is not present", __func__); + /* Just give a warning here, continue with the initialization */ + } + return time_scene_server_init(model); +} + +int bt_mesh_scheduler_setup_srv_init(struct bt_mesh_model *model, bool primary) +{ + /* The model may be present only on the Primary element of a node. */ + if (primary == false) { + BT_WARN("%s, Scheduler Setup Server is not on the Primary element", __func__); + /* Just give a warning here, continue with the initialization */ + } + return time_scene_server_init(model); +} \ No newline at end of file diff --git a/components/bt/sdkconfig.rename b/components/bt/sdkconfig.rename index 2affb7cb7..8c67aa5d3 100644 --- a/components/bt/sdkconfig.rename +++ b/components/bt/sdkconfig.rename @@ -223,3 +223,5 @@ CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK CONFIG_BT_BLE_HOST_Q CONFIG_SMP_ENABLE CONFIG_BT_SMP_ENABLE CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT + +CONFIG_BLE_MESH_GATT_PROXY CONFIG_BLE_MESH_GATT_PROXY_SERVER \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/ble_mesh_demo_main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/ble_mesh_demo_main.c deleted file mode 100644 index e4af32a4c..000000000 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/ble_mesh_demo_main.c +++ /dev/null @@ -1,496 +0,0 @@ -/* main.c - Application main entry point */ - -/* - * Copyright (c) 2017 Intel Corporation - * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include "esp_log.h" -#include "nvs_flash.h" - -#include "esp_ble_mesh_common_api.h" -#include "esp_ble_mesh_provisioning_api.h" -#include "esp_ble_mesh_networking_api.h" -#include "esp_ble_mesh_config_model_api.h" -#include "esp_ble_mesh_generic_model_api.h" - -#include "board.h" -#include "ble_mesh_demo_init.h" - -#define CID_ESP 0x02E5 - -#define MSG_SEND_TTL 3 -#define MSG_SEND_REL false -#define MSG_TIMEOUT 0 /* 0 indicates that timeout value from menuconfig will be used */ -#define MSG_ROLE ROLE_NODE - -extern struct _led_state led_state[3]; - -static uint8_t dev_uuid[16] = { 0xdd, 0xdd }; -static uint16_t node_net_idx = ESP_BLE_MESH_KEY_UNUSED; -static uint16_t node_app_idx = ESP_BLE_MESH_KEY_UNUSED; -static uint8_t remote_onoff = LED_OFF; - -/* The remote node address shall be input through UART1, see board.c */ -uint16_t remote_addr = ESP_BLE_MESH_ADDR_UNASSIGNED; - -static esp_ble_mesh_client_t onoff_client; - -static esp_ble_mesh_cfg_srv_t config_server = { - .relay = ESP_BLE_MESH_RELAY_DISABLED, - .beacon = ESP_BLE_MESH_BEACON_ENABLED, -#if defined(CONFIG_BLE_MESH_FRIEND) - .friend_state = ESP_BLE_MESH_FRIEND_ENABLED, -#else - .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED, -#endif -#if defined(CONFIG_BLE_MESH_GATT_PROXY) - .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED, -#else - .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED, -#endif - .default_ttl = 7, - - /* 3 transmissions with 20ms interval */ - .net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20), - .relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20), -}; - -ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_srv_pub, 2 + 1, MSG_ROLE); -ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_cli_pub, 2 + 1, MSG_ROLE); - -static esp_ble_mesh_model_op_t onoff_op[] = { - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0), - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2), - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2), - /* Each model operation struct array must use this terminator - * as the end tag of the operation uint. */ - ESP_BLE_MESH_MODEL_OP_END, -}; - -static esp_ble_mesh_model_t root_models[] = { - ESP_BLE_MESH_MODEL_CFG_SRV(&config_server), - ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op, - &onoff_srv_pub, &led_state[0]), - ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI(&onoff_cli_pub, &onoff_client), -}; - -static esp_ble_mesh_elem_t elements[] = { - ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE), -}; - -static esp_ble_mesh_comp_t composition = { - .cid = CID_ESP, - .elements = elements, - .element_count = ARRAY_SIZE(elements), -}; - -/* Disable OOB security for SILabs Android app */ -static esp_ble_mesh_prov_t provision = { - .uuid = dev_uuid, -#if 0 - .output_size = 4, - .output_actions = ESP_BLE_MESH_DISPLAY_NUMBER, - .input_actions = ESP_BLE_MESH_PUSH, - .input_size = 4, -#else - .output_size = 0, - .output_actions = 0, -#endif -}; - -static int output_number(esp_ble_mesh_output_action_t action, uint32_t number) -{ - board_output_number(action, number); - return 0; -} - -static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index) -{ - ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr); - ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index); - board_prov_complete(); - node_net_idx = net_idx; -} - -static void gen_onoff_get_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t length, uint8_t *data) -{ - struct _led_state *led = (struct _led_state *)model->user_data; - uint8_t send_data; - esp_err_t err; - - ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current); - - send_data = led->current; - /* Send Generic OnOff Status as a response to Generic OnOff Get */ - err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(send_data), &send_data); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__); - return; - } -} - -static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t length, uint8_t *data) -{ - struct _led_state *led = (struct _led_state *)model->user_data; - uint8_t prev_onoff; - esp_err_t err; - - prev_onoff = led->previous; - led->current = data[0]; - remote_onoff = led->current; - - ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current); - - board_led_operation(led->pin, led->current); - - /* If Generic OnOff state is changed, and the publish address of Generic OnOff Server - * model is valid, Generic OnOff Status will be published. - */ - if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) { - ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current); - err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(led->current), &led->current, ROLE_NODE); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__); - return; - } - } -} - -static void gen_onoff_set_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t length, uint8_t *data) -{ - struct net_buf_simple *msg = model->pub->msg; - struct _led_state *led = (struct _led_state *)model->user_data; - uint8_t prev_onoff, send_data; - esp_err_t err; - - prev_onoff = led->previous; - led->current = data[0]; - remote_onoff = led->current; - - ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current); - - board_led_operation(led->pin, led->current); - - send_data = led->current; - /* Send Generic OnOff Status as a response to Generic OnOff Get */ - err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(send_data), &send_data); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__); - return; - } - - /* If Generic OnOff state is changed, and the publish address of Generic OnOff Server - * model is valid, Generic OnOff Status will be published. - */ - if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) { - ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current); - bt_mesh_model_msg_init(msg, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS); - err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(send_data), &send_data, ROLE_NODE); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__); - return; - } - } -} - -static char *esp_ble_mesh_prov_event_to_str(esp_ble_mesh_prov_cb_event_t event) -{ - switch (event) { - case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT: - return "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT"; - case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT: - return "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT"; - case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT: - return "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT"; - case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT: - return "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT"; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT: - return "ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT"; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT: - return "ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT"; - case ESP_BLE_MESH_NODE_PROV_INPUT_EVT: - return "ESP_BLE_MESH_NODE_PROV_INPUT_EVT"; - case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT: - return "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT"; - case ESP_BLE_MESH_NODE_PROV_RESET_EVT: - return "ESP_BLE_MESH_NODE_PROV_RESET_EVT"; - default: - return "Invalid BLE Mesh provision event"; - } - - return NULL; -} - -static void esp_ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, - esp_ble_mesh_prov_cb_param_t *param) -{ - ESP_LOGI(TAG, "%s, event = %s", __func__, esp_ble_mesh_prov_event_to_str(event)); - - switch (event) { - case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code); - break; - case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code); - break; - case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT, bearer %s", - param->node_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT"); - break; - case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT, bearer %s", - param->node_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT"); - break; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT: - output_number(param->node_prov_output_num.action, param->node_prov_output_num.number); - break; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT: - break; - case ESP_BLE_MESH_NODE_PROV_INPUT_EVT: - break; - case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT: - prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr, - param->node_prov_complete.flags, param->node_prov_complete.iv_index); - break; - case ESP_BLE_MESH_NODE_PROV_RESET_EVT: - break; - case ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT, err_code %d", param->node_set_unprov_dev_name_comp.err_code); - break; - default: - break; - } - - return; -} - -static esp_err_t esp_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common, - esp_ble_mesh_generic_client_set_state_t *set, - esp_ble_mesh_model_t *model, uint32_t opcode, - uint8_t onoff) -{ - if (!common || !set || !model) { - return ESP_ERR_INVALID_ARG; - } - - common->opcode = opcode; - common->model = model; - common->ctx.net_idx = node_net_idx; - common->ctx.app_idx = node_app_idx; - common->ctx.addr = remote_addr; - common->ctx.send_ttl = MSG_SEND_TTL; - common->ctx.send_rel = MSG_SEND_REL; - common->msg_timeout = MSG_TIMEOUT; - common->msg_role = MSG_ROLE; - set->onoff_set.op_en = false; - set->onoff_set.onoff = onoff; - set->onoff_set.tid = 0x0; - - return ESP_OK; -} - - -static void esp_ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, - esp_ble_mesh_model_cb_param_t *param) -{ - esp_ble_mesh_client_common_param_t common = {0}; - int err; - - switch (event) { - case ESP_BLE_MESH_MODEL_OPERATION_EVT: { - if (!param->model_operation.model || !param->model_operation.model->op || !param->model_operation.ctx) { - ESP_LOGE(TAG, "ESP_BLE_MESH_MODEL_OPERATION_EVT parameter is NULL"); - return; - } - if (node_app_idx == ESP_BLE_MESH_KEY_UNUSED) { - /* Generic OnOff Server/Client Models need to bind with the same app key */ - node_app_idx = param->model_operation.ctx->app_idx; - } - switch (param->model_operation.opcode) { - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: - gen_onoff_get_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - break; - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: { - esp_ble_mesh_generic_client_set_state_t set_state = {0}; - gen_onoff_set_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - /* This node has a Generic OnOff Client and Server Model. - * When Generic OnOff Server Model receives a Generic OnOff Set message, after - * this message is been handled, the Generic OnOff Client Model will send the - * Generic OnOff Set message to another node(contains Generic OnOff Server Model) - * identified by the remote_addr. - */ - esp_ble_mesh_set_msg_common(&common, &set_state, onoff_client.model, - ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, remote_onoff); - err = esp_ble_mesh_generic_client_set_state(&common, &set_state); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__); - return; - } - break; - } - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK: { - esp_ble_mesh_generic_client_set_state_t set_state = {0}; - gen_onoff_set_unack_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - /* This node has a Generic OnOff Client and Server Model. - * When Generic OnOff Client Model receives a Generic OnOff Set Unack message, - * after this message is been handled, the Generic OnOff Client Model will send - * the Generic OnOff Set Unack message to another node(contains Generic OnOff - * Server Model) identified by the remote_addr. - */ - esp_ble_mesh_set_msg_common(&common, &set_state, onoff_client.model, - ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, remote_onoff); - err = esp_ble_mesh_generic_client_set_state(&common, &set_state); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Generic OnOff Set Unack failed", __func__); - return; - } - break; - } - default: - break; - } - break; - } - case ESP_BLE_MESH_MODEL_SEND_COMP_EVT: - break; - case ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT: - break; - default: - break; - } - return; -} - -static void esp_ble_mesh_generic_cb(esp_ble_mesh_generic_client_cb_event_t event, - esp_ble_mesh_generic_client_cb_param_t *param) -{ - uint32_t opcode; - int err; - - ESP_LOGI(TAG, "%s: event is %d, error code is %d, opcode is 0x%x", - __func__, event, param->error_code, param->params->opcode); - - opcode = param->params->opcode; - - switch (event) { - case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT"); - switch (opcode) { - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: - ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: onoff %d", param->status_cb.onoff_status.present_onoff); - break; - default: - break; - } - break; - case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT"); - switch (opcode) { - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: - ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: onoff %d", param->status_cb.onoff_status.present_onoff); - break; - default: - break; - } - break; - case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT"); - break; - case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT: { - ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT"); - switch (opcode) { - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: { - esp_ble_mesh_client_common_param_t common = {0}; - esp_ble_mesh_generic_client_set_state_t set_state = {0}; - /* If failed to get the response of Generic OnOff Set, resend Generic OnOff Set */ - esp_ble_mesh_set_msg_common(&common, &set_state, onoff_client.model, - ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, remote_onoff); - err = esp_ble_mesh_generic_client_set_state(&common, &set_state); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__); - return; - } - break; - } - default: - break; - } - break; - } - default: - break; - } - return; -} - -static int ble_mesh_init(void) -{ - int err = 0; - - esp_ble_mesh_register_prov_callback(esp_ble_mesh_prov_cb); - esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb); - esp_ble_mesh_register_generic_client_callback(esp_ble_mesh_generic_cb); - - err = esp_ble_mesh_init(&provision, &composition); - if (err) { - ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err); - return err; - } - - esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT); - - ESP_LOGI(TAG, "BLE Mesh Node initialized"); - - board_led_operation(LED_G, LED_ON); - - return err; -} - -void app_main(void) -{ - int err; - - ESP_LOGI(TAG, "Initializing..."); - - board_init(); - - err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK(err); - - err = bluetooth_init(); - if (err) { - ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err); - return; - } - - ble_mesh_get_dev_uuid(dev_uuid); - - /* Initialize the Bluetooth Mesh Subsystem */ - err = ble_mesh_init(); - if (err) { - ESP_LOGE(TAG, "Bluetooth mesh init failed (err %d)", err); - } -} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/board.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/board.c deleted file mode 100644 index d81bc5881..000000000 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/board.c +++ /dev/null @@ -1,115 +0,0 @@ -/* board.c - Board-specific hooks */ - -/* - * Copyright (c) 2017 Intel Corporation - * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "driver/uart.h" -#include "esp_log.h" - -#include "esp_ble_mesh_provisioning_api.h" -#include "board.h" - -#define TAG "BOARD" - -#define MESH_UART_NUM UART_NUM_1 -#define MESH_UART (&UART1) - -#define UART_BUF_SIZE 128 - -#define UART1_TX_PIN GPIO_NUM_16 -#define UART1_RX_PIN GPIO_NUM_17 - -extern uint16_t remote_addr; - -struct _led_state led_state[3] = { - { LED_OFF, LED_OFF, LED_R, "red" }, - { LED_OFF, LED_OFF, LED_G, "green" }, - { LED_OFF, LED_OFF, LED_B, "blue" }, -}; - -void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number) -{ - ESP_LOGI(TAG, "Board output number %d", number); -} - -void board_prov_complete(void) -{ - board_led_operation(LED_G, LED_OFF); -} - -void board_led_operation(uint8_t pin, uint8_t onoff) -{ - for (int i = 0; i < ARRAY_SIZE(led_state); i++) { - if (led_state[i].pin != pin) { - continue; - } - if (onoff == led_state[i].previous) { - ESP_LOGW(TAG, "led %s is already %s", - led_state[i].name, (onoff ? "on" : "off")); - return; - } - gpio_set_level(pin, onoff); - led_state[i].previous = onoff; - return; - } - ESP_LOGE(TAG, "LED is not found!"); -} - -static void board_uart_task(void *p) -{ - uint8_t *data = calloc(1, UART_BUF_SIZE); - uint32_t input; - - while (1) { - int len = uart_read_bytes(MESH_UART_NUM, data, UART_BUF_SIZE, 100 / portTICK_RATE_MS); - if (len > 0) { - input = strtoul((const char *)data, NULL, 16); - remote_addr = input & 0xFFFF; - ESP_LOGI(TAG, "%s: input 0x%08x, remote_addr 0x%04x", __func__, input, remote_addr); - memset(data, 0, UART_BUF_SIZE); - } - } - - vTaskDelete(NULL); -} - -static void board_led_init(void) -{ - for (int i = 0; i < ARRAY_SIZE(led_state); i++) { - gpio_pad_select_gpio(led_state[i].pin); - gpio_set_direction(led_state[i].pin, GPIO_MODE_OUTPUT); - gpio_set_level(led_state[i].pin, LED_OFF); - led_state[i].previous = LED_OFF; - } -} - -static void board_uart_init(void) -{ - uart_config_t uart_config = { - .baud_rate = 115200, - .data_bits = UART_DATA_8_BITS, - .parity = UART_PARITY_DISABLE, - .stop_bits = UART_STOP_BITS_1, - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE - }; - uart_param_config(MESH_UART_NUM, &uart_config); - uart_set_pin(MESH_UART_NUM, UART1_TX_PIN, UART1_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); - uart_driver_install(MESH_UART_NUM, UART_BUF_SIZE * 2, 0, 0, NULL, 0); -} - -void board_init(void) -{ - board_led_init(); - board_uart_init(); - xTaskCreate(board_uart_task, "board_uart_task", 2048, NULL, 5, NULL); -} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.c index 5cf017bdc..b8d1775b3 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.c @@ -72,7 +72,7 @@ esp_ble_mesh_comp_t *ble_mesh_get_component(uint16_t model_id) return comp; } -void ble_mesh_node_init() +void ble_mesh_node_init(void) { uint16_t i; @@ -100,7 +100,7 @@ void ble_mesh_set_node_prestore_params(uint16_t netkey_index, uint16_t unicast_a xSemaphoreGive(ble_mesh_node_sema); } -void ble_mesh_node_statistics_get() +void ble_mesh_node_statistics_get(void) { xSemaphoreTake(ble_mesh_node_sema, portMAX_DELAY); ESP_LOGI(TAG, "statistics:%d,%d\n", ble_mesh_node_statistics.statistics, ble_mesh_node_statistics.package_num); @@ -156,7 +156,7 @@ int ble_mesh_node_statistics_init(uint16_t package_num) return 0; } -void ble_mesh_node_statistics_destroy() +void ble_mesh_node_statistics_destroy(void) { if (ble_mesh_node_statistics.package_index != NULL) { free(ble_mesh_node_statistics.package_index); diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.h index 06c876fd6..d7feee5fe 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.h +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_adapter.h @@ -85,13 +85,13 @@ extern SemaphoreHandle_t ble_mesh_node_sema; } \ }while(0) \ -void ble_mesh_node_init(); +void ble_mesh_node_init(void); void ble_mesh_set_node_prestore_params(uint16_t netkey_index, uint16_t unicast_addr); esp_ble_mesh_model_t *ble_mesh_get_model(uint16_t model_id); esp_ble_mesh_comp_t *ble_mesh_get_component(uint16_t model_id); -void ble_mesh_node_statistics_get(); +void ble_mesh_node_statistics_get(void); int ble_mesh_node_statistics_accumultate(uint8_t *data, uint32_t value, uint16_t type); int ble_mesh_node_statistics_init(uint16_t package_num); -void ble_mesh_node_statistics_destroy(); +void ble_mesh_node_statistics_destroy(void); #endif //_BLE_MESH_ADAOTER_H_ diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_cfg_srv_model.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_cfg_srv_model.c index 4fa715f0c..91d8fe396 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_cfg_srv_model.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_cfg_srv_model.c @@ -53,7 +53,7 @@ esp_ble_mesh_cfg_srv_t cfg_srv = { #else .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED, #endif -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED, #else .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED, diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_decl.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_decl.h index 22ab3a7f5..2e983265d 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_decl.h +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_decl.h @@ -11,18 +11,18 @@ #include "esp_ble_mesh_defs.h" // Register system functions -void register_system(); +void register_system(void); // Register blutooth -void register_bluetooth(); +void register_bluetooth(void); // Register mesh node cmd -void ble_mesh_register_mesh_node(); +void ble_mesh_register_mesh_node(void); // Register mesh config server and generic server operation cmd -void ble_mesh_register_server(); +void ble_mesh_register_server(void); #if (CONFIG_BLE_MESH_CFG_CLI) // Register mesh config client operation cmd -void ble_mesh_register_configuration_client_model(); +void ble_mesh_register_configuration_client_model(void); #endif diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_main.c index f1f963552..5dba3a050 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_main.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_main.c @@ -36,7 +36,7 @@ #define MOUNT_PATH "/data" #define HISTORY_PATH MOUNT_PATH "/history.txt" -static void initialize_filesystem() +static void initialize_filesystem(void) { static wl_handle_t wl_handle; const esp_vfs_fat_mount_config_t mount_config = { @@ -51,7 +51,7 @@ static void initialize_filesystem() } #endif // CONFIG_STORE_HISTORY -static void initialize_console() +static void initialize_console(void) { /* Disable buffering on stdin and stdout */ setvbuf(stdin, NULL, _IONBF, 0); @@ -63,11 +63,11 @@ static void initialize_console() esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install(CONFIG_CONSOLE_UART_NUM, + ESP_ERROR_CHECK( uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM, 256, 0, 0, NULL, 0) ); /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); /* Initialize the console */ esp_console_config_t console_config = { diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_system.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_system.c index cc8805dbf..88c0a6a0a 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_system.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_console_system.c @@ -28,11 +28,11 @@ #define CONFIG_ESPTOOLPY_PORT "Which is choosen by Users for CMake" #endif -static void register_free(); -static void register_restart(); -static void register_make(); +static void register_free(void); +static void register_restart(void); +static void register_make(void); -void register_system() +void register_system(void) { register_free(); register_restart(); @@ -47,7 +47,7 @@ static int restart(int argc, char **argv) esp_restart(); } -static void register_restart() +static void register_restart(void) { const esp_console_cmd_t cmd = { .command = "restart", @@ -66,7 +66,7 @@ static int free_mem(int argc, char **argv) return 0; } -static void register_free() +static void register_free(void) { const esp_console_cmd_t cmd = { .command = "free", @@ -169,7 +169,7 @@ R"(MONITOR return 0; } -static void register_make() +static void register_make(void) { const esp_console_cmd_t cmd = { .command = "make", diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_node_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_node_cmd.c index 919e69f77..375c224c6 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_node_cmd.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_node_cmd.c @@ -86,18 +86,18 @@ ble_mesh_node_status node_status = { SemaphoreHandle_t ble_mesh_node_sema; -void ble_mesh_register_node_cmd(); +void ble_mesh_register_node_cmd(void); // Register callback function void ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_param_t *param); void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_cb_param_t *param); -void ble_mesh_register_mesh_node() +void ble_mesh_register_mesh_node(void) { ble_mesh_register_node_cmd(); } -int ble_mesh_register_node_cb() +int ble_mesh_register_node_cb(int argc, char** argv) { ESP_LOGD(TAG, "enter %s\n", __func__); ble_mesh_node_init(); @@ -364,7 +364,7 @@ int ble_mesh_node_enable_bearer(int argc, char **argv) return err; } -int ble_mesh_node_reset() +int ble_mesh_node_reset(int argc, char** argv) { esp_err_t err; ESP_LOGD(TAG, "enter %s\n", __func__); @@ -437,7 +437,7 @@ int ble_mesh_node_enter_network_auto(int argc, char **argv) return err; } -void ble_mesh_register_node_cmd() +void ble_mesh_register_node_cmd(void) { const esp_console_cmd_t register_cmd = { .command = "bmreg", diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_server_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_server_cmd.c index e2ae583bf..6fcb41d4f 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_server_cmd.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/ble_mesh_register_server_cmd.c @@ -18,7 +18,7 @@ #include "ble_mesh_console_lib.h" #include "ble_mesh_adapter.h" -void ble_mesh_register_server_operation(); +void ble_mesh_register_server_operation(void); typedef struct { struct arg_str *data; @@ -29,7 +29,7 @@ typedef struct { } ble_mesh_publish_message; ble_mesh_publish_message msg_publish; -void ble_mesh_register_server() +void ble_mesh_register_server(void) { ble_mesh_register_server_operation(); } @@ -63,7 +63,7 @@ int ble_mesh_module_publish_message(int argc, char **argv) return err; } -void ble_mesh_register_server_operation() +void ble_mesh_register_server_operation(void) { msg_publish.data = arg_str1("d", NULL, "", "message data"); msg_publish.opcode = arg_int1("o", NULL, "", "operation opcode"); diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/register_bluetooth.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/register_bluetooth.c index e6b03ed59..64358ba60 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/register_bluetooth.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/main/register_bluetooth.c @@ -18,27 +18,27 @@ #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" -void register_ble_address(); +void register_ble_address(void); -void register_bluetooth() +void register_bluetooth(void) { register_ble_address(); } -int bt_mac() +int bt_mac(int argc, char** argv) { const uint8_t *mac = esp_bt_dev_get_address(); printf("+BTMAC:"MACSTR"\n", MAC2STR(mac)); return 0; } -void register_ble_address() +void register_ble_address(void) { const esp_console_cmd_t cmd = { .command = "btmac", .help = "get BT mac address", .hint = NULL, - .func = (esp_console_cmd_func_t)&bt_mac, + .func = &bt_mac, }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/sdkconfig.defaults b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/sdkconfig.defaults index ae7c2c27b..5920b6a5d 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node/sdkconfig.defaults @@ -26,7 +26,7 @@ CONFIG_BLE_MESH_PROV=y CONFIG_BLE_MESH_NET_BUF_POOL_USAGE=y CONFIG_BLE_MESH_PROXY=y CONFIG_BLE_MESH_PB_GATT=y -CONFIG_BLE_MESH_GATT_PROXY=y +CONFIG_BLE_MESH_GATT_PROXY_SERVER=y CONFIG_BLE_MESH_NODE_ID_TIMEOUT=60 CONFIG_BLE_MESH_PROXY_FILTER_SIZE=1 CONFIG_BLE_MESH_SUBNET_COUNT=1 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.c index 754b0115f..eded5787b 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.c @@ -77,7 +77,7 @@ esp_ble_mesh_comp_t *ble_mesh_get_component(uint16_t model_id) return comp; } -void ble_mesh_node_init() +void ble_mesh_node_init(void) { uint16_t i; @@ -129,7 +129,7 @@ void ble_mesh_create_send_data(char *data, uint16_t byte_num, uint16_t sequence_ } } -void ble_mesh_test_performance_client_model_get() +void ble_mesh_test_performance_client_model_get(void) { uint32_t i, j; uint32_t sum_time = 0; @@ -155,7 +155,7 @@ void ble_mesh_test_performance_client_model_get() xSemaphoreGive(ble_mesh_test_perf_sema); } -void ble_mesh_test_performance_client_model_get_received_percent() +void ble_mesh_test_performance_client_model_get_received_percent(void) { uint32_t i, j; uint32_t max_time = 1400; @@ -283,7 +283,7 @@ int ble_mesh_test_performance_client_model_init(uint16_t node_num, uint32_t test return 0; } -void ble_mesh_test_performance_client_model_destroy() +void ble_mesh_test_performance_client_model_destroy(void) { if (test_perf_statistics.time != NULL) { free(test_perf_statistics.time); diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.h index bdc083a21..305026c1a 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.h +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_adapter.h @@ -106,18 +106,18 @@ extern SemaphoreHandle_t ble_mesh_test_perf_sema; } \ }while(0) \ -void ble_mesh_node_init(); +void ble_mesh_node_init(void); void ble_mesh_set_node_prestore_params(uint16_t netkey_index, uint16_t unicast_addr); esp_ble_mesh_model_t *ble_mesh_get_model(uint16_t model_id); esp_ble_mesh_comp_t *ble_mesh_get_component(uint16_t model_id); void ble_mesh_create_send_data(char *data, uint16_t byte_num, uint16_t sequence_num, uint32_t opcode); -void ble_mesh_test_performance_client_model_get(); -void ble_mesh_test_performance_client_model_get_received_percent(); +void ble_mesh_test_performance_client_model_get(void); +void ble_mesh_test_performance_client_model_get_received_percent(void); void ble_mesh_test_performance_client_model_accumulate_statistics(uint32_t value); int ble_mesh_test_performance_client_model_accumulate_time(uint16_t time, uint8_t *data, uint8_t ack_ttl, uint16_t length); int ble_mesh_test_performance_client_model_init(uint16_t node_num, uint32_t test_num, uint8_t ttl); -void ble_mesh_test_performance_client_model_destroy(); +void ble_mesh_test_performance_client_model_destroy(void); #endif //_BLE_MESH_ADAPTER_H_ \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_cfg_srv_model.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_cfg_srv_model.c index 705ad8d48..7ff71bb91 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_cfg_srv_model.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_cfg_srv_model.c @@ -50,7 +50,7 @@ esp_ble_mesh_cfg_srv_t cfg_srv = { #else .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED, #endif -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED, #else .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED, diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_decl.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_decl.h index 90e52a61d..3ba4f496d 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_decl.h +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_decl.h @@ -11,28 +11,28 @@ #include "esp_ble_mesh_defs.h" // Register system functions -void register_system(); +void register_system(void); // Register bluetooth -void register_bluetooth(); +void register_bluetooth(void); // Register mesh node cmd -void ble_mesh_register_mesh_node(); +void ble_mesh_register_mesh_node(void); // Register Test Perf client cmd -void ble_mesh_register_mesh_test_performance_client(); +void ble_mesh_register_mesh_test_performance_client(void); #if (CONFIG_BLE_MESH_CFG_CLI) // Register mesh config client operation cmd -void ble_mesh_register_configuration_client_model(); +void ble_mesh_register_configuration_client_model(void); #endif #if (CONFIG_BLE_MESH_GENERIC_ONOFF_CLI) // Register mesh client operation cmd -void ble_mesh_register_gen_onoff_client(); +void ble_mesh_register_gen_onoff_client(void); #endif #if CONFIG_BLE_MESH_PROVISIONER // Regitster mesh provisioner cmd -void ble_mesh_register_mesh_provisioner(); +void ble_mesh_register_mesh_provisioner(void); #endif diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_main.c index d9d4a9e4e..a60f70ee2 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_main.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_main.c @@ -39,7 +39,7 @@ #define MOUNT_PATH "/data" #define HISTORY_PATH MOUNT_PATH "/history.txt" -static void initialize_filesystem() +static void initialize_filesystem(void) { static wl_handle_t wl_handle; const esp_vfs_fat_mount_config_t mount_config = { @@ -54,7 +54,7 @@ static void initialize_filesystem() } #endif // CONFIG_STORE_HISTORY -static void initialize_console() +static void initialize_console(void) { /* Disable buffering on stdin and stdout */ setvbuf(stdin, NULL, _IONBF, 0); @@ -66,11 +66,11 @@ static void initialize_console() esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install(CONFIG_CONSOLE_UART_NUM, + ESP_ERROR_CHECK( uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM, 256, 0, 0, NULL, 0) ); /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); /* Initialize the console */ esp_console_config_t console_config = { diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_system.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_system.c index d3dc6c12f..de76b11ae 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_system.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_console_system.c @@ -24,11 +24,11 @@ #define CONFIG_ESPTOOLPY_PORT "Which is choosen by Users for CMake" #endif -static void register_free(); -static void register_restart(); -static void register_make(); +static void register_free(void); +static void register_restart(void); +static void register_make(void); -void register_system() +void register_system(void) { register_free(); register_restart(); @@ -43,7 +43,7 @@ static int restart(int argc, char **argv) esp_restart(); } -static void register_restart() +static void register_restart(void) { const esp_console_cmd_t cmd = { .command = "restart", @@ -62,7 +62,7 @@ static int free_mem(int argc, char **argv) return 0; } -static void register_free() +static void register_free(void) { const esp_console_cmd_t cmd = { .command = "free", @@ -165,7 +165,7 @@ R"(MONITOR return 0; } -static void register_make() +static void register_make(void) { const esp_console_cmd_t cmd = { .command = "make", diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_cfg_client_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_cfg_client_cmd.c index 53a10d38d..59bae35ce 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_cfg_client_cmd.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_cfg_client_cmd.c @@ -33,11 +33,11 @@ typedef struct { } ble_mesh_client_get_set_state_t; ble_mesh_client_get_set_state_t configuration_client_model_operation; -void ble_mesh_register_configuration_client_model_command(); +void ble_mesh_register_configuration_client_model_command(void); void ble_mesh_configuration_client_model_cb(esp_ble_mesh_cfg_client_cb_event_t event, esp_ble_mesh_cfg_client_cb_param_t *param); -void ble_mesh_register_configuration_client_model() +void ble_mesh_register_configuration_client_model(void) { ble_mesh_register_configuration_client_model_command(); } @@ -362,7 +362,7 @@ int ble_mesh_configuration_client_model_operation(int argc, char **argv) } -void ble_mesh_register_configuration_client_model_command() +void ble_mesh_register_configuration_client_model_command(void) { configuration_client_model_operation.action_type = arg_str1("z", NULL, "", "action type"); configuration_client_model_operation.set_state = arg_str0("x", NULL, "", "set state"); diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_gen_onoff_client_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_gen_onoff_client_cmd.c index 6f34a1b27..f9caa8931 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_gen_onoff_client_cmd.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_gen_onoff_client_cmd.c @@ -32,11 +32,11 @@ typedef struct { } ble_mesh_gen_onoff_state_t; ble_mesh_gen_onoff_state_t gen_onoff_state; -void ble_mesh_register_gen_onoff_client_command(); +void ble_mesh_register_gen_onoff_client_command(void); void ble_mesh_generic_onoff_client_model_cb(esp_ble_mesh_generic_client_cb_event_t event, esp_ble_mesh_generic_client_cb_param_t *param); -void ble_mesh_register_gen_onoff_client() +void ble_mesh_register_gen_onoff_client(void) { ble_mesh_register_gen_onoff_client_command(); } @@ -152,7 +152,7 @@ int ble_mesh_generic_onoff_client_model(int argc, char **argv) return err; } -void ble_mesh_register_gen_onoff_client_command() +void ble_mesh_register_gen_onoff_client_command(void) { gen_onoff_state.action_type = arg_str1("z", NULL, "", "action type"); gen_onoff_state.opcode = arg_int0("o", NULL, "", "message opcode"); diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_test_perf_client_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_test_perf_client_cmd.c index e46efc8ec..b6b4c898f 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_test_perf_client_cmd.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_reg_test_perf_client_cmd.c @@ -47,9 +47,9 @@ typedef struct { } ble_mesh_test_perf_client_model_statistics_t; ble_mesh_test_perf_client_model_statistics_t test_perf_client_model_statistics; -void ble_mesh_performance_client_model_command(); +void ble_mesh_performance_client_model_command(void); -void ble_mesh_register_mesh_test_performance_client() +void ble_mesh_register_mesh_test_performance_client(void) { ble_mesh_performance_client_model_command(); } @@ -177,7 +177,7 @@ int ble_mesh_test_performance_client_model_performance(int argc, char **argv) return 0; } -void ble_mesh_performance_client_model_command() +void ble_mesh_performance_client_model_command(void) { test_perf_client_model.action_type = arg_str1("z", NULL, "", "action type"); test_perf_client_model.playload_byte = arg_int0("p", NULL, "", "playload byte"); diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_node_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_node_cmd.c index 0e0775aca..b9bd565c4 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_node_cmd.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_node_cmd.c @@ -65,18 +65,18 @@ ble_mesh_node_status node_status = { SemaphoreHandle_t ble_mesh_node_sema; -void ble_mesh_register_node_cmd(); +void ble_mesh_register_node_cmd(void); // Register callback function void ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_param_t *param); void ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_cb_param_t *param); -void ble_mesh_register_mesh_node() +void ble_mesh_register_mesh_node(void) { ble_mesh_register_node_cmd(); } -int ble_mesh_register_node_cb() +int ble_mesh_register_node_cb(int argc, char** argv) { ESP_LOGD(TAG, "enter %s\n", __func__); ble_mesh_node_init(); @@ -405,7 +405,7 @@ int ble_mesh_provisioner_enable_bearer(int argc, char **argv) return err; } -void ble_mesh_register_node_cmd() +void ble_mesh_register_node_cmd(void) { const esp_console_cmd_t register_cmd = { .command = "bmreg", diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_provisioner_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_provisioner_cmd.c index fea5d8274..d36aed92f 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_provisioner_cmd.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/ble_mesh_register_provisioner_cmd.c @@ -80,12 +80,12 @@ typedef struct { } ble_mesh_provisioner_add_key_t; ble_mesh_provisioner_add_key_t provisioner_add_key; -void ble_mesh_regist_provisioner_cmd(); +void ble_mesh_regist_provisioner_cmd(void); void ble_mesh_prov_adv_cb(const esp_ble_mesh_bd_addr_t addr, const esp_ble_mesh_addr_type_t addr_type, const uint8_t adv_type, const uint8_t *dev_uuid, uint16_t oob_info, esp_ble_mesh_prov_bearer_t bearer); -void ble_mesh_register_mesh_provisioner() +void ble_mesh_register_mesh_provisioner(void) { ble_mesh_regist_provisioner_cmd(); } @@ -101,7 +101,7 @@ void ble_mesh_prov_adv_cb(const esp_ble_mesh_bd_addr_t addr, const esp_ble_mesh_ ESP_LOGD(TAG, "exit %s\n", __func__); } -int ble_mesh_provisioner_register() +int ble_mesh_provisioner_register(int argc, char** argv) { ESP_LOGD(TAG, "enter %s \n", __func__); // esp_ble_mesh_register_unprov_adv_pkt_callback(ble_mesh_prov_adv_cb); @@ -322,7 +322,7 @@ int ble_mesh_provision_bind_local_model(int argc, char **argv) return err; } -void ble_mesh_regist_provisioner_cmd() +void ble_mesh_regist_provisioner_cmd(void) { const esp_console_cmd_t prov_register = { .command = "bmpreg", diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/register_bluetooth.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/register_bluetooth.c index 6b856c30f..129617e7e 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/register_bluetooth.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/main/register_bluetooth.c @@ -18,9 +18,9 @@ #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" -void register_ble_address(); +void register_ble_address(void); -void register_bluetooth() +void register_bluetooth(void) { register_ble_address(); } @@ -32,7 +32,7 @@ int bt_mac(int argc, char** argv) return 0; } -void register_ble_address() +void register_ble_address(void) { const esp_console_cmd_t cmd = { .command = "btmac", diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/sdkconfig.defaults b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/sdkconfig.defaults index 2ef2832fb..18210534d 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner/sdkconfig.defaults @@ -21,13 +21,13 @@ CONFIG_BLE_MESH_PROVISIONER=y CONFIG_BLE_MESH_WAIT_FOR_PROV_MAX_DEV_NUM=20 CONFIG_BLE_MESH_MAX_PROV_NODES=20 CONFIG_BLE_MESH_PBA_SAME_TIME=10 -CONFIG_BLE_MESH_PBG_SAME_TIME=4 +CONFIG_BLE_MESH_PBG_SAME_TIME=3 CONFIG_BLE_MESH_PROVISIONER_SUBNET_COUNT=3 CONFIG_BLE_MESH_PROVISIONER_APP_KEY_COUNT=9 CONFIG_BLE_MESH_PB_ADV=y CONFIG_BLE_MESH_NET_BUF_POOL_USAGE=y CONFIG_BLE_MESH_PB_GATT=y -CONFIG_BLE_MESH_GATT_PROXY=y +CONFIG_BLE_MESH_GATT_PROXY_SERVER=y CONFIG_BLE_MESH_RELAY=y CONFIG_BLE_MESH_LOW_POWER= CONFIG_BLE_MESH_FRIEND= diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/main/ble_mesh_demo_main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/main/ble_mesh_demo_main.c index 1a48a0687..27e93638d 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/main/ble_mesh_demo_main.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/main/ble_mesh_demo_main.c @@ -52,7 +52,7 @@ static esp_ble_mesh_cfg_srv_t config_server = { #else .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED, #endif -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED, #else .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED, @@ -574,7 +574,7 @@ static esp_err_t ble_mesh_init(void) void app_main(void) { - int err; + esp_err_t err; ESP_LOGI(TAG, "Initializing..."); diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/sdkconfig.defaults b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/sdkconfig.defaults index 9dd5ca01d..b1a37395f 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/sdkconfig.defaults @@ -28,7 +28,7 @@ CONFIG_BLE_MESH_PROVISIONER_APP_KEY_COUNT=3 CONFIG_BLE_MESH_PB_ADV=y CONFIG_BLE_MESH_NET_BUF_POOL_USAGE=y CONFIG_BLE_MESH_PB_GATT=y -CONFIG_BLE_MESH_GATT_PROXY=y +CONFIG_BLE_MESH_GATT_PROXY_SERVER=n CONFIG_BLE_MESH_RELAY=y CONFIG_BLE_MESH_LOW_POWER= CONFIG_BLE_MESH_FRIEND= diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/main/ble_mesh_demo_main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/main/ble_mesh_demo_main.c index 7fe64220e..2bf300309 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/main/ble_mesh_demo_main.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/main/ble_mesh_demo_main.c @@ -24,6 +24,7 @@ #include "esp_ble_mesh_provisioning_api.h" #include "esp_ble_mesh_config_model_api.h" #include "esp_ble_mesh_generic_model_api.h" +#include "esp_ble_mesh_local_data_operation_api.h" #include "board.h" #include "esp_fast_prov_operation.h" @@ -58,7 +59,7 @@ esp_ble_mesh_cfg_srv_t config_server = { #else .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED, #endif -#if defined(CONFIG_BLE_MESH_GATT_PROXY) +#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED, #else .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED, @@ -95,15 +96,12 @@ example_fast_prov_server_t fast_prov_server = { .state = STATE_IDLE, }; -static esp_ble_mesh_model_op_t onoff_op[] = { - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0), - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2), - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2), - ESP_BLE_MESH_MODEL_OP_END, +ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 3, ROLE_FAST_PROV); +static esp_ble_mesh_gen_onoff_srv_t onoff_server = { + .rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP, + .rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP, }; -ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 1, ROLE_FAST_PROV); - static esp_ble_mesh_model_op_t fast_prov_srv_op[] = { ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET, 3), ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD, 16), @@ -124,8 +122,7 @@ static esp_ble_mesh_model_op_t fast_prov_cli_op[] = { static esp_ble_mesh_model_t root_models[] = { ESP_BLE_MESH_MODEL_CFG_SRV(&config_server), ESP_BLE_MESH_MODEL_CFG_CLI(&config_client), - ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op, - &onoff_pub, &led_state[1]), + ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub, &onoff_server), }; static esp_ble_mesh_model_t vnd_models[] = { @@ -158,29 +155,11 @@ static esp_ble_mesh_prov_t prov = { .iv_index = 0x00, }; -static void gen_onoff_get_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t len, uint8_t *data) +static void example_change_led_state(uint8_t onoff) { - struct _led_state *led = NULL; - uint8_t send_data; - esp_err_t err; + struct _led_state *led = &led_state[1]; - led = (struct _led_state *)model->user_data; - if (!led) { - ESP_LOGE(TAG, "%s: Failed to get generic onoff server model user_data", __func__); - return; - } - - send_data = led->current; - - /* Sends Generic OnOff Status as a reponse to Generic OnOff Get */ - err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(send_data), &send_data); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Failed to send Generic OnOff Status message", __func__); - return; - } + board_led_operation(led->pin, onoff); /* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will * start the timer used to disable fast provisioning functionality. @@ -190,37 +169,6 @@ static void gen_onoff_get_handler(esp_ble_mesh_model_t *model, } } -static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t len, uint8_t *data) -{ - struct _led_state *led = NULL; - - led = (struct _led_state *)model->user_data; - if (!led) { - ESP_LOGE(TAG, "%s: Failed to get generic onoff server model user_data", __func__); - return; - } - - led->current = data[0]; - gpio_set_level(led->pin, led->current); - - /* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will - * start the timer used to disable fast provisioning functionality. - */ - if (!bt_mesh_atomic_test_and_set_bit(fast_prov_server.srv_flags, DISABLE_FAST_PROV_START)) { - k_delayed_work_submit(&fast_prov_server.disable_fast_prov_timer, DISABLE_FAST_PROV_TIMEOUT); - } -} - -static void gen_onoff_set_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t len, uint8_t *data) -{ - gen_onoff_set_unack_handler(model, ctx, len, data); - gen_onoff_get_handler(model, ctx, len, data); -} - static void node_prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index) { ESP_LOGI(TAG, "net_idx: 0x%04x, unicast_addr: 0x%04x", net_idx, addr); @@ -484,14 +432,6 @@ static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event } opcode = param->model_operation.opcode; switch (opcode) { - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: - gen_onoff_set_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - break; - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK: - gen_onoff_set_unack_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - break; case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET: case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD: case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR: @@ -704,14 +644,14 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t __func__, event, param->ctx.recv_op, param->ctx.addr); switch (event) { - case ESP_BLE_MESH_CFG_SERVER_RECV_MSG_EVT: + case ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT: switch (param->ctx.recv_op) { case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: ESP_LOGI(TAG, "Config Server get Config AppKey Add"); - err = example_handle_config_app_key_add_evt(param->status_cb.app_key_add.app_idx); + err = example_handle_config_app_key_add_evt(param->value.state_change.appkey_add.app_idx); if (err != ESP_OK) { ESP_LOGE(TAG, "%s: Failed to bind app_idx 0x%04x with non-config models", - __func__, param->status_cb.app_key_add.app_idx); + __func__, param->value.state_change.appkey_add.app_idx); return; } break; @@ -724,6 +664,27 @@ static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t } } +static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event, + esp_ble_mesh_generic_server_cb_param_t *param) +{ + ESP_LOGI(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x", + event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst); + + switch (event) { + case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT: + ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT"); + if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET || + param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) { + ESP_LOGI(TAG, "onoff 0x%02x", param->value.state_change.onoff_set.onoff); + example_change_led_state(param->value.state_change.onoff_set.onoff); + } + break; + default: + ESP_LOGW(TAG, "Unknown Generic Server event 0x%02x", event); + break; + } +} + static esp_err_t ble_mesh_init(void) { esp_err_t err; @@ -732,6 +693,7 @@ static esp_err_t ble_mesh_init(void) esp_ble_mesh_register_custom_model_callback(example_ble_mesh_custom_model_cb); esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb); esp_ble_mesh_register_config_server_callback(example_ble_mesh_config_server_cb); + esp_ble_mesh_register_generic_server_callback(example_ble_mesh_generic_server_cb); err = esp_ble_mesh_init(&prov, &comp); if (err != ESP_OK) { diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/sdkconfig.defaults b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/sdkconfig.defaults index 3cce34438..41a148bdf 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/sdkconfig.defaults @@ -36,7 +36,7 @@ CONFIG_BLE_MESH_APP_KEY_COUNT=3 CONFIG_BLE_MESH_MODEL_KEY_COUNT=3 CONFIG_BLE_MESH_MODEL_GROUP_COUNT=3 CONFIG_BLE_MESH_PB_GATT=y -CONFIG_BLE_MESH_GATT_PROXY=y +CONFIG_BLE_MESH_GATT_PROXY_SERVER=y CONFIG_BLE_MESH_RELAY=y CONFIG_BLE_MESH_LOW_POWER= CONFIG_BLE_MESH_FRIEND= diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/ble_mesh_demo_main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/ble_mesh_demo_main.c deleted file mode 100644 index 4c5e16eb8..000000000 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/ble_mesh_demo_main.c +++ /dev/null @@ -1,358 +0,0 @@ -/* main.c - Application main entry point */ - -/* - * Copyright (c) 2017 Intel Corporation - * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include "esp_log.h" -#include "nvs_flash.h" - -#include "esp_ble_mesh_defs.h" -#include "esp_ble_mesh_common_api.h" -#include "esp_ble_mesh_networking_api.h" -#include "esp_ble_mesh_provisioning_api.h" -#include "esp_ble_mesh_config_model_api.h" - -#include "board.h" -#include "ble_mesh_demo_init.h" - -#define CID_ESP 0x02E5 - -extern struct _led_state led_state[3]; - -static uint8_t dev_uuid[16] = { 0xdd, 0xdd }; - -static esp_ble_mesh_cfg_srv_t config_server = { - .relay = ESP_BLE_MESH_RELAY_DISABLED, - .beacon = ESP_BLE_MESH_BEACON_ENABLED, -#if defined(CONFIG_BLE_MESH_FRIEND) - .friend_state = ESP_BLE_MESH_FRIEND_ENABLED, -#else - .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED, -#endif -#if defined(CONFIG_BLE_MESH_GATT_PROXY) - .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED, -#else - .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED, -#endif - .default_ttl = 7, - /* 3 transmissions with 20ms interval */ - .net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20), - .relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20), -}; - -ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub, 2 + 1, ROLE_NODE); - -static esp_ble_mesh_model_op_t onoff_op[] = { - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET, 0), - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET, 2), - ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2), - /* Each model operation struct array must use this terminator - * as the end tag of the operation uint. */ - ESP_BLE_MESH_MODEL_OP_END, -}; - -static esp_ble_mesh_model_t root_models[] = { - ESP_BLE_MESH_MODEL_CFG_SRV(&config_server), - ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op, - &onoff_pub, &led_state[0]), -}; - -static esp_ble_mesh_model_t extend_model_0[] = { - ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op, - &onoff_pub, &led_state[1]), -}; - -static esp_ble_mesh_model_t extend_model_1[] = { - ESP_BLE_MESH_SIG_MODEL(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, onoff_op, - &onoff_pub, &led_state[2]), -}; - -static esp_ble_mesh_elem_t elements[] = { - ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE), - ESP_BLE_MESH_ELEMENT(0, extend_model_0, ESP_BLE_MESH_MODEL_NONE), - ESP_BLE_MESH_ELEMENT(0, extend_model_1, ESP_BLE_MESH_MODEL_NONE), -}; - -static esp_ble_mesh_comp_t composition = { - .cid = CID_ESP, - .elements = elements, - .element_count = ARRAY_SIZE(elements), -}; - -/* Disable OOB security for SILabs Android app */ -static esp_ble_mesh_prov_t provision = { - .uuid = dev_uuid, -#if 0 - .output_size = 4, - .output_actions = ESP_BLE_MESH_DISPLAY_NUMBER, - .input_actions = ESP_BLE_MESH_PUSH, - .input_size = 4, -#else - .output_size = 0, - .output_actions = 0, -#endif -}; - -static int output_number(esp_ble_mesh_output_action_t action, uint32_t number) -{ - board_output_number(action, number); - return 0; -} - -static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index) -{ - ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr); - ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index); - board_prov_complete(); -} - -static void gen_onoff_get_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t length, uint8_t *data) -{ - struct _led_state *led = (struct _led_state *)model->user_data; - uint8_t send_data; - esp_err_t err; - - ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current); - - send_data = led->current; - /* Send Generic OnOff Status as a response to Generic OnOff Get */ - err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(send_data), &send_data); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__); - return; - } -} - -static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t length, uint8_t *data) -{ - struct _led_state *led = (struct _led_state *)model->user_data; - uint8_t prev_onoff; - esp_err_t err; - - prev_onoff = led->previous; - led->current = data[0]; - - ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current); - - board_led_operation(led->pin, led->current); - - /* If Generic OnOff state is changed, and the publish address of Generic OnOff Server - * model is valid, Generic OnOff Status will be published. - */ - if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) { - ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current); - err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(led->current), &led->current, ROLE_NODE); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__); - return; - } - } -} - -static void gen_onoff_set_handler(esp_ble_mesh_model_t *model, - esp_ble_mesh_msg_ctx_t *ctx, - uint16_t length, uint8_t *data) -{ - struct _led_state *led = (struct _led_state *)model->user_data; - uint8_t prev_onoff, send_data; - esp_err_t err; - - prev_onoff = led->previous; - led->current = data[0]; - - ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current); - - board_led_operation(led->pin, led->current); - - send_data = led->current; - /* Send Generic OnOff Status as a response to Generic OnOff Get */ - err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(send_data), &send_data); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Generic OnOff Status failed", __func__); - return; - } - - /* If Generic OnOff state is changed, and the publish address of Generic OnOff Server - * model is valid, Generic OnOff Status will be published. - */ - if (prev_onoff != led->current && model->pub->publish_addr != ESP_BLE_MESH_ADDR_UNASSIGNED) { - ESP_LOGI(TAG, "Publish previous 0x%02x current 0x%02x", prev_onoff, led->current); - err = esp_ble_mesh_model_publish(model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, - sizeof(send_data), &send_data, ROLE_NODE); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: Publish Generic OnOff Status failed", __func__); - return; - } - } -} - -static char *esp_ble_mesh_prov_event_to_str(esp_ble_mesh_prov_cb_event_t event) -{ - switch (event) { - case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT: - return "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT"; - case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT: - return "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT"; - case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT: - return "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT"; - case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT: - return "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT"; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT: - return "ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT"; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT: - return "ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT"; - case ESP_BLE_MESH_NODE_PROV_INPUT_EVT: - return "ESP_BLE_MESH_NODE_PROV_INPUT_EVT"; - case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT: - return "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT"; - case ESP_BLE_MESH_NODE_PROV_RESET_EVT: - return "ESP_BLE_MESH_NODE_PROV_RESET_EVT"; - default: - return "Invalid BLE Mesh provision event"; - } - - return NULL; -} - -static void esp_ble_mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event, - esp_ble_mesh_prov_cb_param_t *param) -{ - ESP_LOGI(TAG, "%s, event = %s", __func__, esp_ble_mesh_prov_event_to_str(event)); - switch (event) { - case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code); - break; - case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code); - break; - case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT, bearer %s", - param->node_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT"); - break; - case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT, bearer %s", - param->node_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT"); - break; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT: - output_number(param->node_prov_output_num.action, param->node_prov_output_num.number); - break; - case ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT: - break; - case ESP_BLE_MESH_NODE_PROV_INPUT_EVT: - break; - case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT: - prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr, - param->node_prov_complete.flags, param->node_prov_complete.iv_index); - break; - case ESP_BLE_MESH_NODE_PROV_RESET_EVT: - break; - case ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT: - ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT, err_code %d", param->node_set_unprov_dev_name_comp.err_code); - break; - default: - break; - } - return; -} - -static void esp_ble_mesh_model_cb(esp_ble_mesh_model_cb_event_t event, - esp_ble_mesh_model_cb_param_t *param) -{ - switch (event) { - case ESP_BLE_MESH_MODEL_OPERATION_EVT: { - if (!param->model_operation.model || !param->model_operation.model->op || !param->model_operation.ctx) { - ESP_LOGE(TAG, "ESP_BLE_MESH_MODEL_OPERATION_EVT parameter is NULL"); - return; - } - switch (param->model_operation.opcode) { - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: - gen_onoff_get_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - break; - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: - gen_onoff_set_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - break; - case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK: - gen_onoff_set_unack_handler(param->model_operation.model, param->model_operation.ctx, - param->model_operation.length, param->model_operation.msg); - break; - default: - break; - } - break; - } - case ESP_BLE_MESH_MODEL_SEND_COMP_EVT: - break; - case ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT: - break; - default: - break; - } -} - -static esp_err_t ble_mesh_init(void) -{ - int err = 0; - - esp_ble_mesh_register_prov_callback(esp_ble_mesh_prov_cb); - esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb); - - err = esp_ble_mesh_init(&provision, &composition); - if (err) { - ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err); - return err; - } - - esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT); - - ESP_LOGI(TAG, "BLE Mesh Node initialized"); - - board_led_operation(LED_G, LED_ON); - - return err; -} - -void app_main(void) -{ - int err; - - ESP_LOGI(TAG, "Initializing..."); - - board_init(); - - err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK(err); - - err = bluetooth_init(); - if (err) { - ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err); - return; - } - - ble_mesh_get_dev_uuid(dev_uuid); - - /* Initialize the Bluetooth Mesh Subsystem */ - err = ble_mesh_init(); - if (err) { - ESP_LOGE(TAG, "Bluetooth mesh init failed (err %d)", err); - } -} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/board.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/board.c deleted file mode 100644 index 50035a7dd..000000000 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/main/board.c +++ /dev/null @@ -1,130 +0,0 @@ -/* board.c - Board-specific hooks */ - -/* - * Copyright (c) 2017 Intel Corporation - * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "driver/gpio.h" -#include "esp_log.h" -#include "board.h" -#include "esp_ble_mesh_provisioning_api.h" - -#define TAG "BOARD" - -#define INTR_FLAG_DEFAULT 0 - -static xQueueHandle s_evt_queue; - -struct _led_state led_state[3] = { - { LED_OFF, LED_OFF, LED_R, "red" }, - { LED_OFF, LED_OFF, LED_G, "green" }, - { LED_OFF, LED_OFF, LED_B, "blue" }, -}; - -void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number) -{ - ESP_LOGI(TAG, "Board output number %d", number); -} - -void board_prov_complete(void) -{ - board_led_operation(LED_G, LED_OFF); -} - -void board_led_operation(uint8_t pin, uint8_t onoff) -{ - for (int i = 0; i < 3; i++) { - if (led_state[i].pin != pin) { - continue; - } - if (onoff == led_state[i].previous) { - ESP_LOGW(TAG, "led %s is already %s", - led_state[i].name, (onoff ? "on" : "off")); - return; - } - gpio_set_level(pin, onoff); - led_state[i].previous = onoff; - return; - } - - ESP_LOGE(TAG, "LED is not found!"); -} - -static void board_led_init(void) -{ - for (int i = 0; i < 3; i++) { - gpio_pad_select_gpio(led_state[i].pin); - gpio_set_direction(led_state[i].pin, GPIO_MODE_OUTPUT); - gpio_set_level(led_state[i].pin, LED_OFF); - led_state[i].previous = LED_OFF; - } -} - -static void IRAM_ATTR switch_isr_handler(void *arg) -{ - uint32_t gpio_num = (uint32_t) arg; - xQueueSendFromISR(s_evt_queue, &gpio_num, NULL); -} - -static void switch_key_init(uint32_t key) -{ - gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_NEGEDGE; - io_conf.pin_bit_mask = 1 << key; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pull_up_en = 1; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - - gpio_set_intr_type(key, GPIO_INTR_NEGEDGE); - gpio_install_isr_service(INTR_FLAG_DEFAULT); - gpio_isr_handler_add(key, switch_isr_handler, (void *)key); -} - -static void switch_task_entry(void *arg) -{ - while (1) { - uint32_t io_num; - if (xQueueReceive(s_evt_queue, &io_num, portMAX_DELAY) == pdTRUE) { - uint8_t onoff = led_state[0].previous; - ESP_LOGI(TAG, "GPIO[%d] intr, val: %d", io_num, gpio_get_level(io_num)); - board_led_operation(LED_R, !onoff); - led_state[0].previous = !onoff; - //TODO: publish state change message - } - } -} - -static void switch_init(gpio_num_t gpio_num) -{ - s_evt_queue = xQueueCreate(3, sizeof(uint32_t)); - if (!s_evt_queue) { - return; - } - - BaseType_t ret = xTaskCreate(switch_task_entry, "switch", 4096, NULL, 4, NULL); - if (ret == pdFAIL) { - goto fail; - } - - switch_key_init(gpio_num); - return; - -fail: - vQueueDelete(s_evt_queue); -} - -void board_init(void) -{ - board_led_init(); - switch_init(GPIO_NUM_18); -} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt similarity index 90% rename from examples/bluetooth/esp_ble_mesh/ble_mesh_node/CMakeLists.txt rename to examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt index d8b91b1ef..4b36e55e6 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/CMakeLists.txt +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ble_mesh_node) +project(onoff_client) diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/Makefile b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile similarity index 87% rename from examples/bluetooth/esp_ble_mesh/ble_mesh_node/Makefile rename to examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile index 87313e4ab..a47e6fd08 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/Makefile +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := ble_mesh_node +PROJECT_NAME := onoff_client COMPONENT_ADD_INCLUDEDIRS := components/include diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/README.md b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/README.md similarity index 100% rename from examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/README.md rename to examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/README.md diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/CMakeLists.txt new file mode 100644 index 000000000..6c385ee21 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/CMakeLists.txt @@ -0,0 +1,7 @@ + +set(COMPONENT_SRCS "button.c" + "button_obj.cpp") + +set(COMPONENT_ADD_INCLUDEDIRS ". include") + +register_component() diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/Kconfig b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/Kconfig new file mode 100644 index 000000000..308410a69 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/Kconfig @@ -0,0 +1,21 @@ +menu "Button" + + choice BUTTON_TIMER_IMPLEMENT + bool "Button Timer Mode" + default BUTTON_USE_ESP_TIMER + help + Choose a implementation of timer for button instance. + + config BUTTON_USE_RTOS_TIMER + bool "Use FreeRTOS Timer" + + config BUTTON_USE_ESP_TIMER + bool "Use ESP Timer" + endchoice + + config BUTTON_IO_GLITCH_FILTER_TIME_MS + int "IO glitch filter timer ms (10~100)" + range 10 100 + default 50 + +endmenu \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/README.md b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/README.md new file mode 100644 index 000000000..6f61910cf --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/README.md @@ -0,0 +1,47 @@ +# Component: Button + +* This component defines a button as a well encapsulated object. +* A button device is defined by: + * GPIO number on which the button is attached. + * Active level which decided by peripheral hardware. + * Trigger mode which decides whether to call serial trigger callback during pressing + * Serial threshold seconds which decides that serial trigger callback will be called after how many seconds' pressing +* A button device can provide: + * One push event callback + * One release event callback + * One short-time tap event callback + * One serial trigger event callback + * Several long-time press event callback + We can set different jitter filters for all the events. + Once any of the long press callback is triggered, the short tap event will not be triggered. + This components are based on GPIO provided by idf and soft timer provided by FreeRTOS. + +* To use the button device, you need to : + * create a button object returned by iot_button_create(). + * Then hook different event callbacks to the button object. + * To free the object, you can call iot_button_delete to delete the button object and free the memory that used. + +* Todo: + * Add hardware timer mode(because sometimes soft-timer callback function is limited) + +### NOTE: +> All the event callback function are realized by FreeRTOS soft timer APIs, the callback must follow the rule: + + + +``` + Button callback functions execute in the context of the timer service task. + It is therefore essential that button callback functions never attempt to block. + For example, a button callback function must not call vTaskDelay(), vTaskDelayUntil(), or specify a non zero block time when accessing a queue or a semaphore. +``` + +> In addition: +> You can adjust the following macros within FreeRTOS to adjust the stack depth/queue length/task priority of the timer service. + + +``` +#define configUSE_TIMERS //enable soft-timer +#define configTIMER_TASK_PRIORITY // priority of the timers service task +#define configQueue_LENGTH // length of timer command queue +#define configTIMER_TASK_STACK_DEPTH // stack depth of the soft-timer +``` \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button.c new file mode 100644 index 000000000..ac391a5c3 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button.c @@ -0,0 +1,434 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/timers.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "iot_button.h" +#include "esp_timer.h" + +#define USE_ESP_TIMER CONFIG_BUTTON_USE_ESP_TIMER +#if USE_ESP_TIMER +#define STOP_TIMER(tmr) esp_timer_stop(tmr) +#define DELETE_TIMER(tmr) esp_timer_delete(tmr) +#else +#define STOP_TIMER(tmr) xTimerStop(tmr, portMAX_DELAY) +#define DELETE_TIMER(tmr) xTimerDelete(tmr, portMAX_DELAY); +#endif + +#define IOT_CHECK(tag, a, ret) if(!(a)) { \ + ESP_LOGE(tag,"%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__); \ + return (ret); \ + } +#define ERR_ASSERT(tag, param) IOT_CHECK(tag, (param) == ESP_OK, ESP_FAIL) +#define POINT_ASSERT(tag, param, ret) IOT_CHECK(tag, (param) != NULL, (ret)) + +typedef enum { + BUTTON_STATE_IDLE = 0, + BUTTON_STATE_PUSH, + BUTTON_STATE_PRESSED, +} button_status_t; + +typedef struct button_dev button_dev_t; +typedef struct btn_cb button_cb_t; + +struct btn_cb{ + TickType_t interval; + button_cb cb; + void* arg; + #if !USE_ESP_TIMER + TimerHandle_t tmr; + #else + esp_timer_handle_t tmr; + #endif + button_dev_t *pbtn; + button_cb_t *next_cb; +}; + +struct button_dev{ + uint8_t io_num; + uint8_t active_level; + uint32_t serial_thres_sec; + button_status_t state; + button_cb_t tap_short_cb; + button_cb_t tap_psh_cb; + button_cb_t tap_rls_cb; + button_cb_t press_serial_cb; + button_cb_t* cb_head; +}; + +#define BUTTON_GLITCH_FILTER_TIME_MS CONFIG_BUTTON_IO_GLITCH_FILTER_TIME_MS +static const char* TAG = "button"; + +// static void button_press_cb(xTimerHandle tmr) +static void button_press_cb(void* tmr) +{ + #if !USE_ESP_TIMER + button_cb_t* btn_cb = (button_cb_t*) pvTimerGetTimerID(tmr); + #else + button_cb_t* btn_cb = (button_cb_t*)(tmr); + #endif + + button_dev_t* btn = btn_cb->pbtn; + // low, then restart + if (btn->active_level == gpio_get_level(btn->io_num)) { + btn->state = BUTTON_STATE_PRESSED; + if (btn_cb->cb) { + btn_cb->cb(btn_cb->arg); + } + } +} + +// static void button_tap_psh_cb(xTimerHandle tmr) +static void button_tap_psh_cb(void* tmr) +{ + #if !USE_ESP_TIMER + button_cb_t* btn_cb = (button_cb_t*) pvTimerGetTimerID(tmr); + #else + button_cb_t* btn_cb = (button_cb_t*)(tmr); + #endif + + button_dev_t* btn = btn_cb->pbtn; + STOP_TIMER(btn->tap_rls_cb.tmr); + + int lv = gpio_get_level(btn->io_num); + + if (btn->active_level == lv) { + // high, then key is up + btn->state = BUTTON_STATE_PUSH; + if (btn->press_serial_cb.tmr) { + #if !USE_ESP_TIMER + xTimerChangePeriod(btn->press_serial_cb.tmr, btn->serial_thres_sec*1000 / portTICK_PERIOD_MS, portMAX_DELAY); + xTimerReset(btn->press_serial_cb.tmr, portMAX_DELAY); + #else + esp_timer_stop(btn->press_serial_cb.tmr); + esp_timer_start_once(btn->press_serial_cb.tmr, btn->serial_thres_sec * 1000 * 1000); + #endif + + } + if (btn->tap_psh_cb.cb) { + btn->tap_psh_cb.cb(btn->tap_psh_cb.arg); + } + } else { + // 50ms, check if this is a real key up + if (btn->tap_rls_cb.tmr) { + STOP_TIMER(btn->tap_rls_cb.tmr); + #if !USE_ESP_TIMER + xTimerReset(btn->tap_rls_cb.tmr, portMAX_DELAY); + #else + esp_timer_start_once(btn->tap_rls_cb.tmr, btn->tap_rls_cb.interval * portTICK_PERIOD_MS * 1000); + #endif + } + } +} + +static void button_tap_rls_cb(void* tmr) +{ + #if !USE_ESP_TIMER + button_cb_t* btn_cb = (button_cb_t*) pvTimerGetTimerID(tmr); + #else + button_cb_t* btn_cb = (button_cb_t*)(tmr); + #endif + button_dev_t* btn = btn_cb->pbtn; + STOP_TIMER(btn->tap_rls_cb.tmr); + + if (btn->active_level == gpio_get_level(btn->io_num)) { + + } else { + // high, then key is up + button_cb_t *pcb = btn->cb_head; + while (pcb != NULL) { + if (pcb->tmr != NULL) { + STOP_TIMER(pcb->tmr); + } + pcb = pcb->next_cb; + } + if (btn->press_serial_cb.tmr && btn->press_serial_cb.tmr != NULL) { + STOP_TIMER(btn->press_serial_cb.tmr); + } + if (btn->tap_short_cb.cb && btn->state == BUTTON_STATE_PUSH) { + btn->tap_short_cb.cb(btn->tap_short_cb.arg); + } + if(btn->tap_rls_cb.cb && btn->state != BUTTON_STATE_IDLE) { + btn->tap_rls_cb.cb(btn->tap_rls_cb.arg); + } + btn->state = BUTTON_STATE_IDLE; + } +} + +static void button_press_serial_cb(void* tmr) +{ + #if !USE_ESP_TIMER + button_dev_t* btn = (button_dev_t*) pvTimerGetTimerID(tmr); + #else + button_dev_t* btn = (button_dev_t*)(tmr); + #endif + + if (btn->press_serial_cb.cb) { + btn->press_serial_cb.cb(btn->press_serial_cb.arg); + } + #if !USE_ESP_TIMER + xTimerChangePeriod(btn->press_serial_cb.tmr, btn->press_serial_cb.interval, portMAX_DELAY); + xTimerReset(btn->press_serial_cb.tmr, portMAX_DELAY); + #else + esp_timer_stop(btn->press_serial_cb.tmr); + esp_timer_start_once(btn->press_serial_cb.tmr, btn->press_serial_cb.interval * portTICK_PERIOD_MS * 1000); + #endif +} + +static void button_gpio_isr_handler(void* arg) +{ + button_dev_t* btn = (button_dev_t*) arg; + portBASE_TYPE HPTaskAwoken = pdFALSE; + int level = gpio_get_level(btn->io_num); + if (level == btn->active_level) { + if (btn->tap_psh_cb.tmr) { + #if !USE_ESP_TIMER + xTimerStopFromISR(btn->tap_psh_cb.tmr, &HPTaskAwoken); + xTimerResetFromISR(btn->tap_psh_cb.tmr, &HPTaskAwoken); + #else + esp_timer_stop(btn->tap_psh_cb.tmr); + esp_timer_start_once(btn->tap_psh_cb.tmr, btn->tap_psh_cb.interval * portTICK_PERIOD_MS * 1000); + #endif + } + + button_cb_t *pcb = btn->cb_head; + while (pcb != NULL) { + if (pcb->tmr != NULL) { + #if !USE_ESP_TIMER + xTimerStopFromISR(pcb->tmr, &HPTaskAwoken); + xTimerResetFromISR(pcb->tmr, &HPTaskAwoken); + #else + esp_timer_stop(pcb->tmr); + esp_timer_start_once(pcb->tmr, pcb->interval * portTICK_PERIOD_MS * 1000); + #endif + } + pcb = pcb->next_cb; + } + } else { + // 50ms, check if this is a real key up + if (btn->tap_rls_cb.tmr) { + #if !USE_ESP_TIMER + xTimerStopFromISR(btn->tap_rls_cb.tmr, &HPTaskAwoken); + xTimerResetFromISR(btn->tap_rls_cb.tmr, &HPTaskAwoken); + #else + esp_timer_stop(btn->tap_rls_cb.tmr); + esp_timer_start_once(btn->tap_rls_cb.tmr, btn->tap_rls_cb.interval * portTICK_PERIOD_MS * 1000); + #endif + } + } + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +#if !USE_ESP_TIMER +static void button_free_tmr(xTimerHandle* tmr) +#else +static void button_free_tmr(esp_timer_handle_t *tmr) +#endif +{ + if (tmr && *tmr) { + STOP_TIMER(*tmr); + DELETE_TIMER(*tmr); + *tmr = NULL; + } +} + +esp_err_t iot_button_delete(button_handle_t btn_handle) +{ + POINT_ASSERT(TAG, btn_handle, ESP_ERR_INVALID_ARG); + button_dev_t* btn = (button_dev_t*) btn_handle; + gpio_set_intr_type(btn->io_num, GPIO_INTR_DISABLE); + gpio_isr_handler_remove(btn->io_num); + + button_free_tmr(&btn->tap_rls_cb.tmr); + button_free_tmr(&btn->tap_psh_cb.tmr); + button_free_tmr(&btn->tap_short_cb.tmr); + button_free_tmr(&btn->press_serial_cb.tmr); + + button_cb_t *pcb = btn->cb_head; + while (pcb != NULL) { + button_cb_t *cb_next = pcb->next_cb; + button_free_tmr(&pcb->tmr); + free(pcb); + pcb = cb_next; + } + free(btn); + return ESP_OK; +} + +button_handle_t iot_button_create(gpio_num_t gpio_num, button_active_t active_level) +{ + #if USE_ESP_TIMER + ets_printf("use esp timer !!!\n"); + esp_timer_init(); + #endif + + IOT_CHECK(TAG, gpio_num < GPIO_NUM_MAX, NULL); + button_dev_t* btn = (button_dev_t*) calloc(1, sizeof(button_dev_t)); + POINT_ASSERT(TAG, btn, NULL); + btn->active_level = active_level; + btn->io_num = gpio_num; + btn->state = BUTTON_STATE_IDLE; + btn->tap_rls_cb.arg = NULL; + btn->tap_rls_cb.cb = NULL; + btn->tap_rls_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_PERIOD_MS; + btn->tap_rls_cb.pbtn = btn; + #if !USE_ESP_TIMER + btn->tap_rls_cb.tmr = xTimerCreate("btn_rls_tmr", btn->tap_rls_cb.interval, pdFALSE, + &btn->tap_rls_cb, button_tap_rls_cb); + #else + esp_timer_create_args_t tmr_param_rls; + tmr_param_rls.arg = &btn->tap_rls_cb; + tmr_param_rls.callback = button_tap_rls_cb; + tmr_param_rls.dispatch_method = ESP_TIMER_TASK; + tmr_param_rls.name = "btn_rls_tmr"; + esp_timer_create(&tmr_param_rls, &btn->tap_rls_cb.tmr); + #endif + + btn->tap_psh_cb.arg = NULL; + btn->tap_psh_cb.cb = NULL; + btn->tap_psh_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_PERIOD_MS; + btn->tap_psh_cb.pbtn = btn; + #if !USE_ESP_TIMER + btn->tap_psh_cb.tmr = xTimerCreate("btn_psh_tmr", btn->tap_psh_cb.interval, pdFALSE, + &btn->tap_psh_cb, button_tap_psh_cb); + #else + esp_timer_create_args_t tmr_param_psh; + tmr_param_psh.arg = &btn->tap_psh_cb; + tmr_param_psh.callback = button_tap_psh_cb; + tmr_param_psh.dispatch_method = ESP_TIMER_TASK; + tmr_param_psh.name = "btn_psh_tmr"; + esp_timer_create(&tmr_param_psh, &btn->tap_psh_cb.tmr); + #endif + gpio_install_isr_service(0); + gpio_config_t gpio_conf; + gpio_conf.intr_type = GPIO_INTR_ANYEDGE; + gpio_conf.mode = GPIO_MODE_INPUT; + gpio_conf.pin_bit_mask = (1ULL << gpio_num); + gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE; + gpio_config(&gpio_conf); + gpio_isr_handler_add(gpio_num, button_gpio_isr_handler, btn); + return (button_handle_t) btn; +} + +esp_err_t iot_button_rm_cb(button_handle_t btn_handle, button_cb_type_t type) +{ + button_dev_t* btn = (button_dev_t*) btn_handle; + button_cb_t* btn_cb = NULL; + if (type == BUTTON_CB_PUSH) { + btn_cb = &btn->tap_psh_cb; + } else if (type == BUTTON_CB_RELEASE) { + btn_cb = &btn->tap_rls_cb; + } else if (type == BUTTON_CB_TAP) { + btn_cb = &btn->tap_short_cb; + } else if (type == BUTTON_CB_SERIAL) { + btn_cb = &btn->press_serial_cb; + } + btn_cb->cb = NULL; + btn_cb->arg = NULL; + btn_cb->pbtn = btn; + button_free_tmr(&btn_cb->tmr); + return ESP_OK; +} + +esp_err_t iot_button_set_serial_cb(button_handle_t btn_handle, uint32_t start_after_sec, TickType_t interval_tick, button_cb cb, void* arg) +{ + button_dev_t* btn = (button_dev_t*) btn_handle; + btn->serial_thres_sec = start_after_sec; + + if (btn->press_serial_cb.tmr == NULL) { + #if !USE_ESP_TIMER + btn->press_serial_cb.tmr = xTimerCreate("btn_serial_tmr", btn->serial_thres_sec*1000 / portTICK_PERIOD_MS, + pdFALSE, btn, button_press_serial_cb); + #else + esp_timer_create_args_t tmr_param_ser; + tmr_param_ser.arg = btn; + tmr_param_ser.callback = button_press_serial_cb; + tmr_param_ser.dispatch_method = ESP_TIMER_TASK; + tmr_param_ser.name = "btn_serial_tmr"; + esp_timer_create(&tmr_param_ser, &btn->press_serial_cb.tmr); + #endif + } + btn->press_serial_cb.arg = arg; + btn->press_serial_cb.cb = cb; + btn->press_serial_cb.interval = interval_tick; + btn->press_serial_cb.pbtn = btn; + #if !USE_ESP_TIMER + xTimerChangePeriod(btn->press_serial_cb.tmr, btn->serial_thres_sec*1000 / portTICK_PERIOD_MS, portMAX_DELAY); + #endif + return ESP_OK; +} + +esp_err_t iot_button_set_evt_cb(button_handle_t btn_handle, button_cb_type_t type, button_cb cb, void* arg) +{ + POINT_ASSERT(TAG, btn_handle, ESP_ERR_INVALID_ARG); + button_dev_t* btn = (button_dev_t*) btn_handle; + if (type == BUTTON_CB_PUSH) { + btn->tap_psh_cb.arg = arg; + btn->tap_psh_cb.cb = cb; + btn->tap_psh_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_RATE_MS; + btn->tap_psh_cb.pbtn = btn; + #if !USE_ESP_TIMER + xTimerChangePeriod(btn->tap_psh_cb.tmr, btn->tap_psh_cb.interval, portMAX_DELAY); + #endif + } else if (type == BUTTON_CB_RELEASE) { + btn->tap_rls_cb.arg = arg; + btn->tap_rls_cb.cb = cb; + btn->tap_rls_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_RATE_MS; + btn->tap_rls_cb.pbtn = btn; + #if !USE_ESP_TIMER + xTimerChangePeriod(btn->tap_rls_cb.tmr, btn->tap_psh_cb.interval, portMAX_DELAY); + #endif + } else if (type == BUTTON_CB_TAP) { + btn->tap_short_cb.arg = arg; + btn->tap_short_cb.cb = cb; + btn->tap_short_cb.interval = BUTTON_GLITCH_FILTER_TIME_MS / portTICK_RATE_MS; + btn->tap_short_cb.pbtn = btn; + } else if (type == BUTTON_CB_SERIAL) { + iot_button_set_serial_cb(btn_handle, 1, 1000 / portTICK_RATE_MS, cb, arg); + } + return ESP_OK; +} + +esp_err_t iot_button_add_custom_cb(button_handle_t btn_handle, uint32_t press_sec, button_cb cb, void* arg) +{ + POINT_ASSERT(TAG, btn_handle, ESP_ERR_INVALID_ARG); + IOT_CHECK(TAG, press_sec != 0, ESP_ERR_INVALID_ARG); + button_dev_t* btn = (button_dev_t*) btn_handle; + button_cb_t* cb_new = (button_cb_t*) calloc(1, sizeof(button_cb_t)); + POINT_ASSERT(TAG, cb_new, ESP_FAIL); + cb_new->arg = arg; + cb_new->cb = cb; + cb_new->interval = press_sec * 1000 / portTICK_PERIOD_MS; + cb_new->pbtn = btn; + #if !USE_ESP_TIMER + cb_new->tmr = xTimerCreate("btn_press_tmr", cb_new->interval, pdFALSE, cb_new, button_press_cb); + #else + esp_timer_create_args_t tmr_param_cus; + tmr_param_cus.arg = cb_new; + tmr_param_cus.callback = button_press_cb; + tmr_param_cus.dispatch_method = ESP_TIMER_TASK; + tmr_param_cus.name = "btn_press_custom_tmr"; + esp_timer_create(&tmr_param_cus, &cb_new->tmr); + #endif + cb_new->next_cb = btn->cb_head; + btn->cb_head = cb_new; + return ESP_OK; +} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button_obj.cpp b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button_obj.cpp new file mode 100644 index 000000000..bf49238e5 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/button_obj.cpp @@ -0,0 +1,48 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "iot_button.h" + +CButton::CButton(gpio_num_t gpio_num, button_active_t active_level) +{ + m_btn_handle = iot_button_create(gpio_num, active_level); +} + +CButton::~CButton() +{ + iot_button_delete(m_btn_handle); + m_btn_handle = NULL; +} + +esp_err_t CButton::set_evt_cb(button_cb_type_t type, button_cb cb, void* arg) +{ + return iot_button_set_evt_cb(m_btn_handle, type, cb, arg); +} + +esp_err_t CButton::set_serial_cb(button_cb cb, void* arg, TickType_t interval_tick, uint32_t start_after_sec) +{ + return iot_button_set_serial_cb(m_btn_handle, start_after_sec, interval_tick, cb, arg); +} + +esp_err_t CButton::add_custom_cb(uint32_t press_sec, button_cb cb, void* arg) +{ + return iot_button_add_custom_cb(m_btn_handle, press_sec, cb, arg); +} + +esp_err_t CButton::rm_cb(button_cb_type_t type) +{ + return iot_button_rm_cb(m_btn_handle, type); +} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/component.mk b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/component.mk similarity index 100% rename from examples/bluetooth/esp_ble_mesh/ble_mesh_client_model/main/component.mk rename to examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/component.mk diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/include/iot_button.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/include/iot_button.h new file mode 100644 index 000000000..6a2fa23c0 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/components/button/include/iot_button.h @@ -0,0 +1,230 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _IOT_BUTTON_H_ +#define _IOT_BUTTON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "driver/gpio.h" +#include "freertos/portmacro.h" +typedef void (* button_cb)(void*); +typedef void* button_handle_t; + +typedef enum { + BUTTON_ACTIVE_HIGH = 1, /*!