diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 1e2172e29..36d985d0d 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -304,6 +304,7 @@ if(CONFIG_BT_ENABLED) "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") @@ -359,7 +360,15 @@ if(CONFIG_BT_ENABLED) "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..7472572ff 100644 --- a/components/bt/component.mk +++ b/components/bt/component.mk @@ -143,16 +143,18 @@ COMPONENT_ADD_INCLUDEDIRS += esp_ble_mesh/mesh_core \ 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_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/mesh_models/server \ + esp_ble_mesh/api/core \ esp_ble_mesh/api/models endif 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 0c25c085d..6b644e003 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; @@ -165,8 +165,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 +177,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 +188,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_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_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/include/esp_ble_mesh_networking_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h index ae51b6081..5b351ba65 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/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index 762ad81d4..0d4f61367 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 @@ -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 */ @@ -1260,17 +757,6 @@ typedef enum { 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 */ @@ -1677,6 +1163,702 @@ typedef union { } 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 */ @@ -1731,22 +1913,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..663549eb3 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_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_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_lighting_model_api.c b/components/bt/esp_ble_mesh/api/models/esp_ble_mesh_lighting_model_api.c index 33dba45ab..e8c2d4a7b 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_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_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..d3a81ca66 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_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_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..cca4220c6 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_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_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_generic_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h index df9fb3c2d..a9a31528a 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_lighting_model_api.h b/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h index f0291a350..473491bde 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..9971a7f41 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..d3f85205f 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_generic_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_generic_model.c index a33ad6fca..bfc8d1978 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 @@ -534,3 +534,227 @@ 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__); + + 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_lighting_model.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_lighting_model.c index 9d75fbd97..d409fd9e7 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 @@ -379,3 +379,197 @@ 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__); + + 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 2946c2c3a..44a123ec2 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 @@ -48,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" @@ -176,6 +177,16 @@ void btc_ble_mesh_model_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; @@ -203,6 +214,11 @@ static void btc_ble_mesh_model_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; } @@ -422,7 +438,7 @@ static void btc_ble_mesh_model_send_comp_cb(esp_ble_mesh_model_t *model, esp_ble 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; + mesh_param.model_send_comp.ctx = ctx; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_MODEL; @@ -457,6 +473,29 @@ static void btc_ble_mesh_model_publish_comp_cb(esp_ble_mesh_model_t *model, int return; } +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}; + btc_msg_t msg = {0}; + bt_status_t ret; + + 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; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_MODEL; + msg.act = ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_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) { @@ -1230,6 +1269,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) { @@ -1240,8 +1318,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; @@ -1419,10 +1497,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: @@ -1447,6 +1736,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) { @@ -1887,6 +2177,13 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg) 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; 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..2312bc219 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 @@ -624,3 +624,276 @@ 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__); + + 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..f1f4d7a52 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 @@ -381,3 +381,99 @@ 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__); + + 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_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_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 2ff7ae4b1..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 @@ -69,6 +69,7 @@ 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 { @@ -215,6 +216,11 @@ 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); 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/access.c b/components/bt/esp_ble_mesh/mesh_core/access.c index 55a6d25c3..be22611e2 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, diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_kernel.h b/components/bt/esp_ble_mesh/mesh_core/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_core/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/mesh_kernel.c b/components/bt/esp_ble_mesh/mesh_core/mesh_kernel.c index 612d213d4..037126311 100644 --- a/components/bt/esp_ble_mesh/mesh_core/mesh_kernel.c +++ b/components/bt/esp_ble_mesh/mesh_core/mesh_kernel.c @@ -124,8 +124,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 +140,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_models/client/include/client_common.h b/components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h index 4cf2e890b..79aacaac3 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" @@ -136,5 +136,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/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..3e854344f --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/generic_server.c @@ -0,0 +1,2629 @@ +/* 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, 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, 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, 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, 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, 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..d0e1e452b --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/include/server_common.h @@ -0,0 +1,127 @@ +// 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 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..2e82f2283 --- /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..b3b7ab911 --- /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, 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, 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, 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, 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, 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, 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, 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, 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, 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..6c568025d --- /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..e0bf3f8df --- /dev/null +++ b/components/bt/esp_ble_mesh/mesh_models/server/server_common.c @@ -0,0 +1,237 @@ +// 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 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; + } + + /* 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(); + + 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) +{ + 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..0a75cd32c --- /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..dbf71fa19 --- /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..dd9ceaf00 --- /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, 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