kopia lustrzana https://github.com/espressif/esp-idf
1345 wiersze
58 KiB
C
1345 wiersze
58 KiB
C
/* AliGenie - Example
|
||
|
||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||
|
||
Unless required by applicable law or agreed to in writing, this
|
||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
CONDITIONS OF ANY KIND, either express or implied.
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <errno.h>
|
||
#include <math.h>
|
||
|
||
#include "esp_log.h"
|
||
#include "nvs_flash.h"
|
||
|
||
#include "mbedtls/sha256.h"
|
||
|
||
#include "esp_ble_mesh_common_api.h"
|
||
#include "esp_ble_mesh_networking_api.h"
|
||
#include "esp_ble_mesh_provisioning_api.h"
|
||
#include "esp_ble_mesh_config_model_api.h"
|
||
#include "esp_ble_mesh_health_model_api.h"
|
||
#include "esp_ble_mesh_generic_model_api.h"
|
||
#include "esp_ble_mesh_lighting_model_api.h"
|
||
#include "esp_ble_mesh_time_scene_model_api.h"
|
||
#include "esp_ble_mesh_local_data_operation_api.h"
|
||
|
||
#include "board.h"
|
||
#include "genie_mesh.h"
|
||
#include "ble_mesh_example_init.h"
|
||
#include "ble_mesh_example_nvs.h"
|
||
|
||
static const char *TAG = "genie_demo";
|
||
|
||
#define MESH_ELEM_COUNT 1
|
||
#define MESH_ELEM_STATE_COUNT MESH_ELEM_COUNT
|
||
|
||
nvs_handle_t NVS_HANDLE;
|
||
|
||
elem_state_t g_elem_state[MESH_ELEM_STATE_COUNT] = {0};
|
||
model_powerup_t g_powerup[MESH_ELEM_STATE_COUNT] = {0};
|
||
|
||
static uint8_t static_val[16] = {0x64, 0xda, 0x19, 0x8f, 0x58, 0xea, 0x55, 0x85,
|
||
0x75, 0x84, 0x0d, 0xbf, 0x4f, 0x6e, 0x36, 0x8f
|
||
};
|
||
|
||
static uint8_t dev_uuid[16] = {
|
||
0xA8, 0x01, // CID
|
||
0x71, // PID Bit0-3 ble adv version, 0x01
|
||
// bit4: One machine one secret
|
||
// bit5: Support OTA
|
||
// bit6~7:
|
||
// 00:BLE4.0
|
||
// 01:BLE4.2
|
||
// 10:BLE5.0
|
||
// 11:BLE5.0 above
|
||
0x7F, 0x2C, 0x00, 0x00, // ProductID // 00002C7F
|
||
0xda, 0x91, 0x01, 0x7a, 0xfa, 0x28, // MAC Address // 28fa7a0191da
|
||
#if GENIE_VENDOR_MODEL_VERSION == 0
|
||
0x00, // Feature Flag bit7-1:uuid version, version 0
|
||
// bit0 0: unprovisioned adv
|
||
// 1: silent adv
|
||
#elif GENIE_VENDOR_MODEL_VERSION == 1
|
||
0x02, // Feature Flag bit7-1:uuidversion, version 1
|
||
// bit0 0: unprovisioned adv
|
||
// 1: silent adv
|
||
#endif
|
||
0x00, 0x00, // RFU
|
||
};
|
||
|
||
static esp_ble_mesh_cfg_srv_t config_server = {
|
||
.relay = ESP_BLE_MESH_RELAY_ENABLED,
|
||
.beacon = ESP_BLE_MESH_BEACON_ENABLED,
|
||
#if defined(CONFIG_BLE_MESH_FRIEND)
|
||
.friend_state = ESP_BLE_MESH_FRIEND_ENABLED,
|
||
#else
|
||
.friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED,
|
||
#endif
|
||
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
|
||
.gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED,
|
||
#else
|
||
.gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED,
|
||
#endif
|
||
.default_ttl = 7,
|
||
/* 3 transmissions with 20ms interval */
|
||
.net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20),
|
||
/* 3 transmissions with 20ms interval */
|
||
.relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20),
|
||
};
|
||
|
||
uint8_t test_ids[1] = {0x00};
|
||
|
||
/** ESP BLE Mesh Health Server Model Context */
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(health_pub, 2 + 11, ROLE_NODE);
|
||
static esp_ble_mesh_health_srv_t health_server = {
|
||
.health_test.id_count = 1,
|
||
.health_test.test_ids = test_ids,
|
||
};
|
||
|
||
#ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_0, 2 + 3, ROLE_NODE);
|
||
static esp_ble_mesh_gen_onoff_srv_t onoff_server_0 = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
};
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
/* Light Lightness state related context */
|
||
static esp_ble_mesh_light_lightness_state_t lightness_state;
|
||
|
||
/* Light Lightness Server related context */
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(lightness_pub, 2 + 5, ROLE_NODE);
|
||
static esp_ble_mesh_light_lightness_srv_t lightness_server = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.state = &lightness_state,
|
||
};
|
||
|
||
/* Light Lightness Setup Server related context */
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(lightness_setup_pub, 2 + 5, ROLE_NODE);
|
||
static esp_ble_mesh_light_lightness_setup_srv_t lightness_setup_server = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.state = &lightness_state,
|
||
};
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
/* Light CTL state related context */
|
||
static esp_ble_mesh_light_ctl_state_t ctl_state;
|
||
|
||
/* Light CTL Server related context */
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(ctl_pub, 2 + 9, ROLE_NODE);
|
||
static esp_ble_mesh_light_ctl_srv_t ctl_server = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.state = &ctl_state,
|
||
};
|
||
|
||
/* Light CTL Setup Server related context */
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(ctl_setup_pub, 2 + 6, ROLE_NODE);
|
||
static esp_ble_mesh_light_ctl_setup_srv_t ctl_setup_server = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.state = &ctl_state,
|
||
};
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_HSL_SRV
|
||
/* Light HSL state related context */
|
||
static esp_ble_mesh_light_hsl_state_t hsl_state;
|
||
|
||
/* Light HSL Server related context */
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(hsl_pub, 2 + 9, ROLE_NODE);
|
||
static esp_ble_mesh_light_hsl_srv_t hsl_server = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.state = &hsl_state,
|
||
};
|
||
|
||
/* Light HSL Setup Server related context */
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(hsl_setup_pub, 2 + 9, ROLE_NODE);
|
||
static esp_ble_mesh_light_hsl_setup_srv_t hsl_setup_server = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.state = &hsl_state,
|
||
};
|
||
#endif
|
||
|
||
static esp_ble_mesh_model_t root_models[] = {
|
||
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
|
||
ESP_BLE_MESH_MODEL_HEALTH_SRV(&health_server, &health_pub),
|
||
#ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
|
||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_0, &onoff_server_0),
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
ESP_BLE_MESH_MODEL_LIGHT_LIGHTNESS_SRV(&lightness_pub, &lightness_server),
|
||
ESP_BLE_MESH_MODEL_LIGHT_LIGHTNESS_SETUP_SRV(&lightness_setup_pub, &lightness_setup_server),
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
ESP_BLE_MESH_MODEL_LIGHT_CTL_SRV(&ctl_pub, &ctl_server),
|
||
ESP_BLE_MESH_MODEL_LIGHT_CTL_SETUP_SRV(&ctl_setup_pub, &ctl_setup_server),
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_HSL_SRV
|
||
ESP_BLE_MESH_MODEL_LIGHT_HSL_SRV(&hsl_pub, &hsl_server),
|
||
ESP_BLE_MESH_MODEL_LIGHT_HSL_SETUP_SRV(&hsl_setup_pub, &hsl_setup_server),
|
||
#endif
|
||
};
|
||
|
||
/** @def g_vendor_model_alibaba_op
|
||
*
|
||
* @brief vendor model operations struct
|
||
*
|
||
*/
|
||
static esp_ble_mesh_model_op_t g_vendor_model_alibaba_op[] = {
|
||
ESP_BLE_MESH_MODEL_OP(GENIE_MESSAGE_OP_ATTR_GET_STATUS, 2),
|
||
ESP_BLE_MESH_MODEL_OP(GENIE_MESSAGE_OP_ATTR_SET_ACK, 2),
|
||
ESP_BLE_MESH_MODEL_OP(GENIE_MESSAGE_OP_ATTR_SET_UNACK, 2),
|
||
ESP_BLE_MESH_MODEL_OP(GENIE_MESSAGE_OP_ATTR_STATUS, 1),
|
||
ESP_BLE_MESH_MODEL_OP(GENIE_MESSAGE_OP_ATTR_INDICATION, 1),
|
||
ESP_BLE_MESH_MODEL_OP(GENIE_MESSAGE_OP_ATTR_CONFIRMATION, 1),
|
||
ESP_BLE_MESH_MODEL_OP(GENIE_MESSAGE_OP_ATTR_TRANSPARENT_MSG, 1),
|
||
ESP_BLE_MESH_MODEL_OP_END,
|
||
};
|
||
|
||
static esp_ble_mesh_model_t ali_vnd_models[] = {
|
||
ESP_BLE_MESH_VENDOR_MODEL(CID_ALIBABA, GENIE_VENDOR_MODEL_SRV_ID, g_vendor_model_alibaba_op, NULL, NULL),
|
||
};
|
||
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_1, 2 + 3, ROLE_NODE);
|
||
static esp_ble_mesh_gen_onoff_srv_t onoff_server_1 = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
|
||
};
|
||
|
||
ESP_BLE_MESH_MODEL_PUB_DEFINE(onoff_pub_2, 2 + 3, ROLE_NODE);
|
||
static esp_ble_mesh_gen_onoff_srv_t onoff_server_2 = {
|
||
.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
|
||
.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP,
|
||
};
|
||
|
||
static esp_ble_mesh_model_t extend_model_0[] = {
|
||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_1, &onoff_server_1),
|
||
};
|
||
|
||
static esp_ble_mesh_model_t extend_model_1[] = {
|
||
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(&onoff_pub_2, &onoff_server_2),
|
||
};
|
||
|
||
esp_ble_mesh_elem_t elements[] = {
|
||
ESP_BLE_MESH_ELEMENT(0, root_models, ali_vnd_models),
|
||
ESP_BLE_MESH_ELEMENT(0, extend_model_0, ESP_BLE_MESH_MODEL_NONE),
|
||
ESP_BLE_MESH_ELEMENT(0, extend_model_1, ESP_BLE_MESH_MODEL_NONE),
|
||
};
|
||
|
||
static esp_ble_mesh_comp_t composition = {
|
||
.cid = CID_ALIBABA,
|
||
.elements = elements,
|
||
.element_count = ARRAY_SIZE(elements),
|
||
};
|
||
|
||
/* Disable OOB security for SILabs Android app */
|
||
static esp_ble_mesh_prov_t provision = {
|
||
.uuid = dev_uuid,
|
||
.static_val = static_val,
|
||
.static_val_len = 16,
|
||
.output_size = 0, // not support output OOB
|
||
.output_actions = ESP_BLE_MESH_NO_OUTPUT,
|
||
.input_size = 0, // not support Input OOB
|
||
.input_actions = ESP_BLE_MESH_NO_INPUT,
|
||
};
|
||
|
||
static void light_color_set(uint16_t lightness, uint16_t hue, uint16_t saturation);
|
||
|
||
void set_silent_broadcast(void)
|
||
{
|
||
dev_uuid[13] |= GENIE_UNPROV_ADV_FEATURE_SILENT_ADV;
|
||
}
|
||
|
||
void set_unprovision_broadcast(void)
|
||
{
|
||
dev_uuid[13] &= ~GENIE_UNPROV_ADV_FEATURE_SILENT_ADV;
|
||
}
|
||
|
||
void user_prov_complete(uint16_t net_idx, uint16_t addr)
|
||
{
|
||
ENTER_FUNC();
|
||
// todo: add custom code
|
||
}
|
||
|
||
void user_prov_reset(void)
|
||
{
|
||
ENTER_FUNC();
|
||
// todo: add custom code
|
||
esp_restart();
|
||
}
|
||
|
||
void reset_light_para(void)
|
||
{
|
||
ENTER_FUNC();
|
||
uint8_t i = 0;
|
||
|
||
while (i < MESH_ELEM_STATE_COUNT) {
|
||
#ifdef CONFIG_MESH_SIMPLE_MODLE
|
||
g_elem_state[i].state.onoff[VALUE_TYPE_CUR] = GENIE_ONOFF_DEFAULT;
|
||
g_elem_state[i].state.onoff[VALUE_TYPE_TAR] = GENIE_ONOFF_DEFAULT;
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
g_elem_state[i].state.actual[VALUE_TYPE_CUR] = GENIE_LIGHTNESS_DEFAULT;
|
||
g_elem_state[i].state.actual[VALUE_TYPE_TAR] = GENIE_LIGHTNESS_DEFAULT;
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
g_elem_state[i].state.temp[VALUE_TYPE_CUR] = GENIE_CTL_TEMP_DEFAULT;
|
||
g_elem_state[i].state.temp[VALUE_TYPE_TAR] = GENIE_CTL_TEMP_DEFAULT;
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_TRANS
|
||
g_elem_state[i].state.trans = 0;
|
||
g_elem_state[i].state.delay = 0;
|
||
g_elem_state[i].state.trans_start_time = 0;
|
||
g_elem_state[i].state.trans_end_time = 0;
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
g_elem_state[i].powerup.last_actual = GENIE_LIGHTNESS_DEFAULT;
|
||
g_powerup [i].last_actual = GENIE_LIGHTNESS_DEFAULT;
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
g_elem_state[i].powerup.last_temp = GENIE_CTL_TEMP_DEFAULT;
|
||
g_powerup [i].last_temp = GENIE_CTL_TEMP_DEFAULT;
|
||
#endif
|
||
#endif
|
||
i++;
|
||
}
|
||
|
||
ble_mesh_nvs_store(NVS_HANDLE, POWERUP_KEY, g_powerup, sizeof(g_powerup));
|
||
}
|
||
|
||
void save_light_state(elem_state_t *p_elem)
|
||
{
|
||
ENTER_FUNC();
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
if (p_elem->state.actual[VALUE_TYPE_CUR] != 0) {
|
||
p_elem->powerup.last_actual = p_elem->state.actual[VALUE_TYPE_CUR];
|
||
g_powerup[p_elem->elem_index].last_actual = p_elem->state.actual[VALUE_TYPE_CUR];
|
||
}
|
||
ESP_LOGD(TAG, "elem %d, actual %d", p_elem->elem_index, g_powerup[p_elem->elem_index].last_actual);
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
p_elem->powerup.last_temp = p_elem->state.temp[VALUE_TYPE_CUR];
|
||
g_powerup[p_elem->elem_index].last_temp = p_elem->state.temp[VALUE_TYPE_CUR];
|
||
ESP_LOGD(TAG, "elem %d, temp %d", p_elem->elem_index, g_powerup[p_elem->elem_index].last_temp);
|
||
#endif
|
||
|
||
ble_mesh_nvs_store(NVS_HANDLE, POWERUP_KEY, g_powerup, sizeof(g_powerup));
|
||
}
|
||
|
||
void load_light_state(void)
|
||
{
|
||
ENTER_FUNC();
|
||
uint8_t i = 0;
|
||
bool exist = false;
|
||
esp_err_t ret = ESP_OK;
|
||
|
||
ret = ble_mesh_nvs_restore(NVS_HANDLE, POWERUP_KEY, g_powerup, sizeof(g_powerup), &exist);
|
||
|
||
if (ret == ESP_OK) {
|
||
while (i < MESH_ELEM_STATE_COUNT) {
|
||
memcpy(&g_elem_state[i].powerup, &g_powerup[i], sizeof(model_powerup_t));
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
ESP_LOGI(TAG, "elem %d, actual %d", i, g_powerup[i].last_actual);
|
||
if (g_powerup[i].last_actual) {
|
||
g_elem_state[i].state.actual[VALUE_TYPE_TAR] = g_powerup[i].last_actual;
|
||
}
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
ESP_LOGI(TAG, "elem %d, temp %d", i, g_powerup[i].last_temp);
|
||
if (g_powerup[i].last_temp) {
|
||
g_elem_state[i].state.temp[VALUE_TYPE_TAR] = g_powerup[i].last_temp;
|
||
}
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
if (g_elem_state[i].state.actual[VALUE_TYPE_TAR] == 0) {
|
||
g_elem_state[i].state.onoff[VALUE_TYPE_TAR] = 0;
|
||
} else {
|
||
g_elem_state[i].state.onoff[VALUE_TYPE_TAR] = 1;
|
||
}
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_TRANS
|
||
if (g_elem_state[i].state.onoff[VALUE_TYPE_TAR] == 0) {
|
||
g_elem_state[i].state.trans = 0;
|
||
g_elem_state[i].state.delay = 0;
|
||
g_elem_state[i].state.trans_start_time = 0;
|
||
g_elem_state[i].state.trans_end_time = 0;
|
||
} else {
|
||
g_elem_state[i].state.trans = 0x41;
|
||
g_elem_state[i].state.delay = 100;
|
||
g_elem_state[i].state.trans_start_time = k_uptime_get() + g_elem_state[i].state.delay * 5;
|
||
g_elem_state[i].state.trans_end_time = g_elem_state[i].state.trans_start_time + get_transition_time(g_elem_state[i].state.trans);
|
||
}
|
||
#endif
|
||
#endif
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void user_genie_event_handle(genie_event_t event, void *p_arg)
|
||
{
|
||
genie_event_t next_event = event;
|
||
|
||
ESP_LOGD(TAG, "event: %02d, %p", event, p_arg);
|
||
|
||
switch (event) {
|
||
case GENIE_EVT_RESET_BY_REPEAT_NOTIFY:
|
||
ESP_LOGI(TAG, "GENIE_EVT_RESET_BY_REPEAT_NOTIFY");
|
||
light_driver_breath_start(0, 255, 0); /**< green blink */
|
||
break;
|
||
case GENIE_EVT_SW_RESET:
|
||
case GENIE_EVT_HW_RESET_START:
|
||
ESP_LOGI(TAG, "GENIE_EVT_HW_RESET_START");
|
||
light_driver_breath_start(0, 255, 0); /**< green blink */
|
||
ble_mesh_nvs_erase(NVS_HANDLE, LIGHT_STATUS_STORE_KEY); // erase led status
|
||
reset_light_para();
|
||
break;
|
||
case GENIE_EVT_SDK_MESH_INIT:
|
||
ESP_LOGI(TAG, "GENIE_EVT_SDK_MESH_INIT");
|
||
break;
|
||
case GENIE_EVT_SDK_MESH_PROV_SUCCESS:
|
||
ESP_LOGI(TAG, "GENIE_EVT_SDK_MESH_PROV_SUCCESS");
|
||
|
||
g_elem_state[0].state.onoff[VALUE_TYPE_TAR] = 1;
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
g_elem_state[0].state.actual[VALUE_TYPE_TAR] = 0xFFFE;
|
||
g_indication_flag |= INDICATION_FLAG_LIGHTNESS;
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
g_elem_state[0].state.temp[VALUE_TYPE_TAR] = 0xFFFE;
|
||
g_indication_flag |= INDICATION_FLAG_CTL;
|
||
#endif
|
||
ESP_LOGI(TAG, "light_driver_breath_stop %s", __FUNCTION__);
|
||
light_driver_breath_stop();
|
||
// update led status
|
||
genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]);
|
||
break;
|
||
#ifdef CONFIG_MESH_MODEL_TRANS
|
||
case GENIE_EVT_SDK_TRANS_CYCLE:
|
||
#endif
|
||
case GENIE_EVT_SDK_ACTION_DONE: {
|
||
ESP_LOGI(TAG, "GENIE_EVT_SDK_ACTION_DONE");
|
||
elem_state_t *p_elem = (elem_state_t *)p_arg;
|
||
#ifdef CONFIG_MESH_MODEL_HSL_SRV
|
||
ESP_LOGI(TAG, "hue: %d, saturation: %d, lightness: %d", p_elem->state.hue[VALUE_TYPE_CUR], p_elem->state.saturation[VALUE_TYPE_CUR], p_elem->state.lightness[VALUE_TYPE_CUR]);
|
||
board_led_hsl(p_elem->elem_index, p_elem->state.hue[VALUE_TYPE_CUR], p_elem->state.saturation[VALUE_TYPE_CUR], p_elem->state.lightness[VALUE_TYPE_CUR]);
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
ESP_LOGI(TAG, "temperature: %d", p_elem->state.temp[VALUE_TYPE_CUR]);
|
||
board_led_temperature(p_elem->elem_index, p_elem->state.temp[VALUE_TYPE_CUR]);
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
ESP_LOGI(TAG, "lightness actual: %d", p_elem->state.actual[VALUE_TYPE_CUR]);
|
||
board_led_lightness(p_elem->elem_index, p_elem->state.actual[VALUE_TYPE_CUR]);
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
|
||
ESP_LOGI(TAG, "onoff: %d", p_elem->state.onoff[VALUE_TYPE_CUR]);
|
||
board_led_switch(p_elem->elem_index, p_elem->state.onoff[VALUE_TYPE_CUR]);
|
||
#endif
|
||
if (event == GENIE_EVT_SDK_ACTION_DONE) {
|
||
save_light_state(p_elem);
|
||
}
|
||
break;
|
||
}
|
||
case GENIE_EVT_HW_RESET_DONE:
|
||
ESP_LOGI(TAG, "GENIE_EVT_HW_RESET_DONE");
|
||
ble_mesh_nvs_erase(NVS_HANDLE, LIGHT_STATUS_STORE_KEY); // erase led status
|
||
// esp_restart();
|
||
break;
|
||
case GENIE_EVT_APP_FAC_QUIT:
|
||
ESP_LOGI(TAG, "GENIE_EVT_APP_FAC_QUIT");
|
||
break;
|
||
case GENIE_EVT_BUTTON_TAP:
|
||
ESP_LOGI(TAG, "GENIE_EVT_BUTTON_TAP");
|
||
g_elem_state[0].state.onoff[VALUE_TYPE_TAR] = !g_elem_state[0].state.onoff[VALUE_TYPE_TAR];
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
#endif
|
||
// update led status
|
||
next_event = GENIE_EVT_SDK_ANALYZE_MSG;
|
||
p_arg = &g_elem_state[0];
|
||
break;
|
||
case GENIE_EVT_SDK_COLOR_ACTION: {
|
||
ESP_LOGI(TAG, "GENIE_EVT_SDK_COLOR_ACTION");
|
||
#ifdef CONFIG_MESH_MODEL_HSL_SRV
|
||
uint8_t *p_data = p_arg;
|
||
|
||
uint16_t lightness = *p_data++;
|
||
lightness += (*p_data++ << 8);
|
||
|
||
uint16_t hue = *p_data++;
|
||
hue += (*p_data++ << 8);
|
||
|
||
uint16_t saturation = *p_data++;
|
||
saturation += (*p_data++ << 8);
|
||
|
||
light_color_set(lightness, hue, saturation);
|
||
#endif
|
||
break;
|
||
}
|
||
default:
|
||
ESP_LOGD(TAG, "unhandle this event: %2d", event);
|
||
break;
|
||
}
|
||
|
||
if (next_event != event) {
|
||
// send event to genie event loop
|
||
genie_event(next_event, p_arg);
|
||
}
|
||
}
|
||
|
||
esp_err_t local_operation(uint16_t app_idx)
|
||
{
|
||
ESP_LOGD(TAG, "app_idx: %d, primary element address: %d", app_idx, esp_ble_mesh_get_primary_element_address());
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_HEALTH_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_HEALTH_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_HEALTH_SRV, app_idx));
|
||
|
||
#ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, app_idx));
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address() + 1, BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address() + 1, BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address() + 1, BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, app_idx));
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address() + 2, BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address() + 2, BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address() + 2, BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, app_idx));
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, app_idx));
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV, app_idx));
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SRV, app_idx));
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV, app_idx));
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_HSL_SRV
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SRV, app_idx));
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), BLE_MESH_CID_NVAL, ESP_BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV, app_idx));
|
||
#endif
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), CID_ALIBABA, GENIE_VENDOR_MODEL_SRV_ID, GENIE_LIGHT_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_model_subscribe_group_addr(esp_ble_mesh_get_primary_element_address(), CID_ALIBABA, GENIE_VENDOR_MODEL_SRV_ID, GENIE_ALL_GROUP_ADDR));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_bind_app_key_to_local_model(esp_ble_mesh_get_primary_element_address(), CID_ALIBABA, GENIE_VENDOR_MODEL_SRV_ID, app_idx));
|
||
|
||
return ESP_OK;
|
||
}
|
||
|
||
#ifdef CONFIG_MESH_MODEL_HSL_SRV
|
||
void bind_onoff_with_hsl(elem_state_t *p_elem, value_type_t type)
|
||
{
|
||
ENTER_FUNC();
|
||
model_state_t *p_state = &p_elem->state;
|
||
|
||
ESP_LOGI(TAG, "hsl tar(%d, %d, %d)", p_state->hue[VALUE_TYPE_TAR], p_state->saturation[VALUE_TYPE_TAR], p_state->lightness[VALUE_TYPE_TAR]);
|
||
|
||
if (type == VALUE_TYPE_TAR) {
|
||
if (p_state->onoff[VALUE_TYPE_TAR] == 0) {
|
||
//turn on
|
||
p_state->onoff[VALUE_TYPE_TAR] = 1;
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
#endif
|
||
}
|
||
} else if (type == VALUE_TYPE_CUR) {
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
void bind_onoff_with_ctl(elem_state_t *p_elem, value_type_t type)
|
||
{
|
||
ENTER_FUNC();
|
||
model_state_t *p_state = &p_elem->state;
|
||
|
||
// ESP_LOGI(TAG, "temperature cur(%d) tar(%d)", p_state->temp[VALUE_TYPE_CUR], p_state->temp[VALUE_TYPE_TAR]);
|
||
if (type == VALUE_TYPE_TAR) {
|
||
if (p_state->onoff[VALUE_TYPE_TAR] == 0) {
|
||
//turn on
|
||
p_state->onoff[VALUE_TYPE_TAR] = 1;
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
#endif
|
||
}
|
||
} else if (type == VALUE_TYPE_CUR) {
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
void bind_onoff_with_lightness(elem_state_t *p_elem, value_type_t type)
|
||
{
|
||
ENTER_FUNC();
|
||
model_state_t *p_state = &p_elem->state;
|
||
|
||
ESP_LOGI(TAG, "lightness cur(%d) tar(%d)", p_state->actual[VALUE_TYPE_CUR], p_state->actual[VALUE_TYPE_TAR]);
|
||
if (type == VALUE_TYPE_TAR) {
|
||
if (p_state->actual[VALUE_TYPE_CUR] == 0 && p_state->actual[VALUE_TYPE_TAR] != 0) {
|
||
//turn on
|
||
p_state->onoff[VALUE_TYPE_TAR] = 1;
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
#endif
|
||
} else if (p_state->actual[VALUE_TYPE_CUR] != 1 && p_state->actual[VALUE_TYPE_TAR] == 0) {
|
||
//turn off
|
||
p_state->onoff[VALUE_TYPE_TAR] = 0;
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
#endif
|
||
}
|
||
} else if (type == VALUE_TYPE_CUR) {
|
||
if (p_state->actual[VALUE_TYPE_CUR] == 0 && p_state->actual[VALUE_TYPE_TAR] == 0) {
|
||
//turn off
|
||
p_state->onoff[VALUE_TYPE_CUR] = 0;
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
#endif
|
||
}
|
||
}
|
||
}
|
||
|
||
void bind_lightness_with_onoff(elem_state_t *p_elem, value_type_t type)
|
||
{
|
||
ENTER_FUNC();
|
||
model_state_t *p_state = &p_elem->state;
|
||
|
||
ESP_LOGI(TAG, "onoff cur(%d) tar(%d)", p_state->onoff[VALUE_TYPE_CUR], p_state->onoff[VALUE_TYPE_TAR]);
|
||
if (type == VALUE_TYPE_TAR) {
|
||
#ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
|
||
if (p_state->onoff[VALUE_TYPE_CUR] == 0 && p_state->onoff[VALUE_TYPE_TAR] == 1) {
|
||
//turn on, set default lightness
|
||
#ifdef CONFIG_MESH_SIMPLE_MODLE
|
||
if (p_elem->powerup.last_actual) {
|
||
p_state->actual[VALUE_TYPE_TAR] = p_elem->powerup.last_actual;
|
||
} else {
|
||
p_state->actual[VALUE_TYPE_TAR] = GENIE_LIGHTNESS_DEFAULT;
|
||
}
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_LIGHTNESS;
|
||
#endif
|
||
} else if (p_state->onoff[VALUE_TYPE_CUR] == 1 && p_state->onoff[VALUE_TYPE_TAR] == 0) {
|
||
//turn off, set zero
|
||
p_state->actual[VALUE_TYPE_TAR] = 0;
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_LIGHTNESS;
|
||
#endif
|
||
}
|
||
#endif
|
||
} else if (type == VALUE_TYPE_CUR) {
|
||
}
|
||
ESP_LOGI(TAG, "actual cur(%d) tar(%d)", p_state->actual[VALUE_TYPE_CUR], p_state->actual[VALUE_TYPE_TAR]);
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
void bind_ctl_with_onoff(elem_state_t *p_elem, value_type_t type)
|
||
{
|
||
ENTER_FUNC();
|
||
model_state_t *p_state = &p_elem->state;
|
||
|
||
ESP_LOGI(TAG, "onoff cur(%d) tar(%d)", p_state->onoff[VALUE_TYPE_CUR], p_state->onoff[VALUE_TYPE_TAR]);
|
||
if (type == VALUE_TYPE_TAR) {
|
||
#ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
|
||
if (p_state->onoff[VALUE_TYPE_CUR] == 0 && p_state->onoff[VALUE_TYPE_TAR] == 1) {
|
||
#ifdef CONFIG_MESH_SIMPLE_MODLE
|
||
//turn on, check temperature
|
||
ESP_LOGI(TAG, "temp cur(%d) tar(%d)", p_state->temp[VALUE_TYPE_CUR], p_state->temp[VALUE_TYPE_TAR]);
|
||
if (p_state->temp[VALUE_TYPE_CUR] != p_state->temp[VALUE_TYPE_TAR]) {
|
||
if (p_elem->powerup.last_temp) {
|
||
p_state->temp[VALUE_TYPE_TAR] = p_elem->powerup.last_temp;
|
||
} else {
|
||
p_state->temp[VALUE_TYPE_TAR] = GENIE_CTL_TEMP_DEFAULT;
|
||
}
|
||
#ifdef CONFIG_MESH_MODEL_VENDOR_SRV
|
||
g_indication_flag |= INDICATION_FLAG_CTL;
|
||
#endif
|
||
}
|
||
#endif
|
||
}
|
||
#endif
|
||
} else if (type == VALUE_TYPE_CUR) {
|
||
}
|
||
ESP_LOGI(TAG, "temp cur(%04x) tar(%04x)", p_state->temp[VALUE_TYPE_CUR], p_state->temp[VALUE_TYPE_TAR]);
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_HSL_SRV
|
||
static void light_color_set(uint16_t lightness, uint16_t hue, uint16_t saturation)
|
||
{
|
||
ENTER_FUNC();
|
||
ESP_LOGI(TAG, "hue: %d, saturation: %d, lightness: %d", hue, saturation, lightness);
|
||
|
||
g_elem_state[0].state.hue[VALUE_TYPE_TAR] = hue;
|
||
g_elem_state[0].state.saturation[VALUE_TYPE_TAR] = saturation;
|
||
g_elem_state[0].state.lightness[VALUE_TYPE_TAR] = lightness;
|
||
if (g_elem_state[0].state.hue[VALUE_TYPE_CUR] != g_elem_state[0].state.hue[VALUE_TYPE_TAR] || g_elem_state[0].state.saturation[VALUE_TYPE_CUR] != g_elem_state[0].state.saturation[VALUE_TYPE_TAR]
|
||
|| g_elem_state[0].state.lightness[VALUE_TYPE_CUR] != g_elem_state[0].state.lightness[VALUE_TYPE_TAR]) {
|
||
g_indication_flag |= INDICATION_FLAG_HSL;
|
||
|
||
/* Change corresponding binded states in root element */
|
||
bind_onoff_with_hsl(&g_elem_state[0], VALUE_TYPE_TAR);
|
||
|
||
if (esp_ble_mesh_node_is_provisioned()) {
|
||
// update led status
|
||
genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
static void light_ctl_set(uint32_t opcode, esp_ble_mesh_model_t *model,
|
||
esp_ble_mesh_msg_ctx_t *ctx,
|
||
uint16_t lightness, uint16_t temperature, uint16_t delta_uv)
|
||
{
|
||
ENTER_FUNC();
|
||
ESP_LOGI(TAG, "lightness 0x%d", lightness);
|
||
|
||
if (opcode == ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_SET) {
|
||
esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS,
|
||
sizeof(lightness), (uint8_t *)&lightness);
|
||
}
|
||
|
||
g_elem_state[0].state.actual[VALUE_TYPE_TAR] = lightness;
|
||
g_elem_state[0].state.temp[VALUE_TYPE_TAR] = temperature;
|
||
if (g_elem_state[0].state.actual[VALUE_TYPE_CUR] != g_elem_state[0].state.actual[VALUE_TYPE_TAR] || g_elem_state[0].state.temp[VALUE_TYPE_CUR] != g_elem_state[0].state.temp[VALUE_TYPE_TAR]) {
|
||
g_indication_flag |= INDICATION_FLAG_LIGHTNESS;
|
||
g_indication_flag |= INDICATION_FLAG_CTL;
|
||
|
||
esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS,
|
||
sizeof(g_elem_state[0].state.temp[VALUE_TYPE_CUR]), (uint8_t *)&g_elem_state[0].state.temp[VALUE_TYPE_CUR]);
|
||
|
||
/* Change corresponding binded states in root element */
|
||
bind_onoff_with_ctl(&g_elem_state[0], VALUE_TYPE_TAR);
|
||
|
||
if (esp_ble_mesh_node_is_provisioned()) {
|
||
// update led status
|
||
genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
static void light_lightness_actual_set(uint32_t opcode, esp_ble_mesh_model_t *model,
|
||
esp_ble_mesh_msg_ctx_t *ctx,
|
||
uint16_t lightness)
|
||
{
|
||
ENTER_FUNC();
|
||
ESP_LOGI(TAG, "lightness %d", lightness);
|
||
|
||
if (opcode == ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET) {
|
||
esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS,
|
||
sizeof(lightness), (uint8_t *)&lightness);
|
||
}
|
||
|
||
g_elem_state[0].state.actual[VALUE_TYPE_TAR] = lightness;
|
||
if (g_elem_state[0].state.actual[VALUE_TYPE_CUR] != g_elem_state[0].state.actual[VALUE_TYPE_TAR]) {
|
||
g_indication_flag |= INDICATION_FLAG_LIGHTNESS;
|
||
|
||
esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS,
|
||
sizeof(g_elem_state[0].state.actual[VALUE_TYPE_CUR]), (uint8_t *)&g_elem_state[0].state.actual[VALUE_TYPE_CUR]);
|
||
|
||
/* Change corresponding binded states in root element */
|
||
bind_onoff_with_lightness(&g_elem_state[0], VALUE_TYPE_TAR);
|
||
|
||
if (esp_ble_mesh_node_is_provisioned()) {
|
||
// update led status
|
||
genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void light_lightness_linear_set(uint32_t opcode, esp_ble_mesh_model_t *model,
|
||
esp_ble_mesh_msg_ctx_t *ctx,
|
||
uint16_t lightness)
|
||
{
|
||
ENTER_FUNC();
|
||
ESP_LOGI(TAG, "lightness 0x%d", lightness);
|
||
|
||
if (opcode == ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET) {
|
||
esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS,
|
||
sizeof(lightness), (uint8_t *)&lightness);
|
||
}
|
||
|
||
g_elem_state[0].state.linear[VALUE_TYPE_TAR] = lightness;
|
||
if (g_elem_state[0].state.linear[VALUE_TYPE_CUR] != g_elem_state[0].state.linear[VALUE_TYPE_TAR]) {
|
||
g_indication_flag |= INDICATION_FLAG_LIGHTNESS;
|
||
|
||
esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS,
|
||
sizeof(g_elem_state[0].state.linear[VALUE_TYPE_CUR]), (uint8_t *)&g_elem_state[0].state.linear[VALUE_TYPE_CUR]);
|
||
|
||
/* Change corresponding binded states in root element */
|
||
bind_onoff_with_lightness(&g_elem_state[0], VALUE_TYPE_TAR);
|
||
|
||
if (esp_ble_mesh_node_is_provisioned()) {
|
||
// update led status
|
||
genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
static void light_onoff_set(esp_ble_mesh_model_t *model,
|
||
esp_ble_mesh_msg_ctx_t *ctx, uint8_t onoff)
|
||
{
|
||
ENTER_FUNC();
|
||
uint16_t primary_addr = esp_ble_mesh_get_primary_element_address();
|
||
uint8_t elem_count = esp_ble_mesh_get_element_count();
|
||
elem_state_t *led_state = NULL;
|
||
|
||
g_elem_state[0].state.onoff[VALUE_TYPE_TAR] = onoff;
|
||
if (g_elem_state[0].state.onoff[VALUE_TYPE_CUR] != g_elem_state[0].state.onoff[VALUE_TYPE_TAR]) {
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
// g_elem_state[0].state.onoff[VALUE_TYPE_CUR] = g_elem_state[0].state.onoff[VALUE_TYPE_TAR];
|
||
|
||
if (ESP_BLE_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) {
|
||
for (uint8_t i = 0; i < elem_count; i++) {
|
||
if (ctx->recv_dst == (primary_addr + i)) {
|
||
led_state = &g_elem_state[i];
|
||
}
|
||
}
|
||
} else if (ESP_BLE_MESH_ADDR_IS_GROUP(ctx->recv_dst)) {
|
||
if (esp_ble_mesh_is_model_subscribed_to_group(model, ctx->recv_dst)) {
|
||
led_state = &g_elem_state[model->element->element_addr - primary_addr];
|
||
}
|
||
} else if (ctx->recv_dst == 0xFFFF) {
|
||
led_state = &g_elem_state[model->element->element_addr - primary_addr];
|
||
}
|
||
|
||
if (led_state != NULL) {
|
||
ESP_LOGI(TAG, "led onoff 0x%d", g_elem_state[0].state.onoff[VALUE_TYPE_TAR]);
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
// update lightness
|
||
bind_lightness_with_onoff(&g_elem_state[0], VALUE_TYPE_TAR);
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
// update ctl
|
||
bind_ctl_with_onoff(&g_elem_state[0], VALUE_TYPE_TAR);
|
||
#endif
|
||
// update led status
|
||
genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
||
{
|
||
ENTER_FUNC();
|
||
ESP_LOGI(TAG, "net_idx: 0x%04x, addr: 0x%04x", net_idx, addr);
|
||
ESP_LOGI(TAG, "flags: 0x%02x, iv_index: 0x%08x", flags, iv_index);
|
||
}
|
||
|
||
static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
|
||
esp_ble_mesh_prov_cb_param_t *param)
|
||
{
|
||
switch (event) {
|
||
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, err_code %d", param->prov_register_comp.err_code);
|
||
break;
|
||
case ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT, err_code %d", param->node_prov_enable_comp.err_code);
|
||
// send event to genie event loop
|
||
genie_event(GENIE_EVT_SDK_MESH_INIT, ¶m->node_prov_enable_comp.err_code);
|
||
|
||
if (param->node_prov_enable_comp.err_code == -EALREADY) {
|
||
// genie mesh init
|
||
genie_mesh_init();
|
||
}
|
||
break;
|
||
case ESP_BLE_MESH_NODE_PROV_DISABLE_COMP_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_DISABLE_COMP_EVT");
|
||
break;
|
||
case ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT, bearer %s",
|
||
param->node_prov_link_open.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||
|
||
// send event to genie event loop
|
||
genie_event(GENIE_EVT_SDK_MESH_PROV_START, NULL);
|
||
|
||
break;
|
||
case ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT, bearer %s",
|
||
param->node_prov_link_close.bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
|
||
break;
|
||
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT: // already have configuration when device restart, and provisioning completed.
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT");
|
||
ESP_LOG_BUFFER_HEX("NetKey: ", param->node_prov_complete.net_key, 16);
|
||
ESP_LOGI(TAG, "net_idx 0x%04x, NetKey: %s, Primary address: 0x%04x", param->node_prov_complete.net_idx,
|
||
util_hex2str(param->node_prov_complete.net_key, 16), param->node_prov_complete.addr);
|
||
|
||
prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr,
|
||
param->node_prov_complete.flags, param->node_prov_complete.iv_index);
|
||
|
||
user_prov_complete(param->node_prov_complete.net_idx, param->node_prov_complete.addr);
|
||
break;
|
||
case ESP_BLE_MESH_NODE_PROV_RESET_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_PROV_RESET_EVT");
|
||
|
||
// send event to genie event loop
|
||
genie_event(GENIE_EVT_SW_RESET, NULL);
|
||
|
||
user_prov_reset();
|
||
break;
|
||
case ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT, err_code %d", param->node_set_unprov_dev_name_comp.err_code);
|
||
break;
|
||
case ESP_BLE_MESH_PROVISIONER_STORE_NODE_COMP_DATA_COMP_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_STORE_NODE_COMP_DATA_COMP_EVT, err_code %d", param->provisioner_store_node_comp_data_comp.err_code);
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_SUBSCRIBE_GROUP_ADDR_COMP_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_SUBSCRIBE_GROUP_ADDR_COMP_EVT, err_code %d, element_addr 0x%04x, company_id 0x%04x, model_id 0x%04x, group_addr 0x%04x",
|
||
param->model_sub_group_addr_comp.err_code, param->model_sub_group_addr_comp.element_addr,
|
||
param->model_sub_group_addr_comp.company_id, param->model_sub_group_addr_comp.model_id,
|
||
param->model_sub_group_addr_comp.group_addr);
|
||
break;
|
||
case ESP_BLE_MESH_NODE_BIND_APP_KEY_TO_MODEL_COMP_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_NODE_BIND_APP_KEY_TO_MODEL_COMP_EVT, err_code %d, element_addr 0x%04x, company_id 0x%04x, model_id 0x%04x, app_idx 0x%04x",
|
||
param->node_bind_app_key_to_model_comp.err_code, param->node_bind_app_key_to_model_comp.element_addr,
|
||
param->node_bind_app_key_to_model_comp.company_id, param->node_bind_app_key_to_model_comp.model_id,
|
||
param->node_bind_app_key_to_model_comp.app_idx);
|
||
break;
|
||
default:
|
||
ESP_LOGI(TAG, "event %d", event);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void example_ble_mesh_config_server_cb(esp_ble_mesh_cfg_server_cb_event_t event,
|
||
esp_ble_mesh_cfg_server_cb_param_t *param)
|
||
{
|
||
if (event == ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT) {
|
||
switch (param->ctx.recv_op) {
|
||
case ESP_BLE_MESH_MODEL_OP_NET_KEY_ADD:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_NET_KEY_ADD");
|
||
ESP_LOGI(TAG, "net_idx 0x%04x, NetKey: %s",
|
||
param->value.state_change.netkey_add.net_idx,
|
||
util_hex2str(param->value.state_change.netkey_add.net_key, 16));
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_NET_KEY_UPDATE:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_NET_KEY_UPDATE");
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_NET_KEY_DELETE:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_NET_KEY_DELETE");
|
||
break;
|
||
|
||
case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD");
|
||
ESP_LOGI(TAG, "net_idx 0x%04x, app_idx 0x%04x, AppKey: %s",
|
||
param->value.state_change.appkey_add.net_idx, param->value.state_change.appkey_add.app_idx,
|
||
util_hex2str(param->value.state_change.appkey_add.app_key, 16));
|
||
|
||
// send event to genie event loop
|
||
genie_event(GENIE_EVT_SDK_APPKEY_ADD, ¶m->value.state_change.appkey_add.app_idx);
|
||
|
||
#if GENIE_VENDOR_MODEL_VERSION == 0
|
||
|
||
#elif GENIE_VENDOR_MODEL_VERSION == 1
|
||
// local bind AppKEY and Subcribe Group Address
|
||
local_operation(param->value.state_change.appkey_add.app_idx);
|
||
// genie mesh init
|
||
genie_mesh_init();
|
||
#endif
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_APP_KEY_UPDATE:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_APP_KEY_UPDATE");
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_APP_KEY_DELETE:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_APP_KEY_DELETE");
|
||
break;
|
||
|
||
case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND");
|
||
ESP_LOGI(TAG, "elem_addr 0x%04x, app_idx 0x%04x, cid 0x%04x, mod_id 0x%04x",
|
||
param->value.state_change.mod_app_bind.element_addr,
|
||
param->value.state_change.mod_app_bind.app_idx,
|
||
param->value.state_change.mod_app_bind.company_id,
|
||
param->value.state_change.mod_app_bind.model_id);
|
||
break;
|
||
|
||
case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD");
|
||
ESP_LOGI(TAG, "elem_addr 0x%04x, sub_addr 0x%04x, cid 0x%04x, mod_id 0x%04x",
|
||
param->value.state_change.mod_sub_add.element_addr,
|
||
param->value.state_change.mod_sub_add.sub_addr,
|
||
param->value.state_change.mod_sub_add.company_id,
|
||
param->value.state_change.mod_sub_add.model_id);
|
||
#if GENIE_VENDOR_MODEL_VERSION == 0
|
||
// genie mesh init
|
||
genie_mesh_init();
|
||
#elif GENIE_VENDOR_MODEL_VERSION == 1
|
||
|
||
#endif
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE");
|
||
break;
|
||
|
||
case ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_SET:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_HEARTBEAT_PUB_SET");
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_SET:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_HEARTBEAT_SUB_SET");
|
||
break;
|
||
default:
|
||
ESP_LOGW(TAG, "%s, event %d", __FUNCTION__, event);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event,
|
||
esp_ble_mesh_generic_server_cb_param_t *param)
|
||
{
|
||
ESP_LOGD(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x",
|
||
event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst);
|
||
|
||
switch (event) {
|
||
case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT");
|
||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||
|
||
param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
|
||
|
||
light_onoff_set(param->model, ¶m->ctx, param->value.state_change.onoff_set.onoff);
|
||
|
||
/* Update bound states second way */
|
||
// light_lightness_actual_set(param->ctx.recv_op, param->model,
|
||
// ¶m->ctx, param->value.state_change.onoff_set.onoff);
|
||
}
|
||
break;
|
||
case ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT");
|
||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET) {
|
||
esp_ble_mesh_gen_onoff_srv_t *srv = param->model->user_data;
|
||
ESP_LOGI(TAG, "onoff: 0x%02x", srv->state.onoff);
|
||
esp_ble_mesh_server_model_send_msg(param->model, ¶m->ctx,
|
||
ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, sizeof(srv->state.onoff), &srv->state.onoff);
|
||
}
|
||
break;
|
||
case ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT:
|
||
ESP_LOGI(TAG, "ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT");
|
||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||
|
||
param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {
|
||
ESP_LOGI(TAG, "onoff 0x%02x, tid 0x%02x", param->value.set.onoff.onoff, param->value.set.onoff.tid);
|
||
if (param->value.set.onoff.op_en) {
|
||
ESP_LOGI(TAG, "trans_time 0x%02x, delay 0x%02x",
|
||
param->value.set.onoff.trans_time, param->value.set.onoff.delay);
|
||
}
|
||
|
||
esp_ble_mesh_gen_onoff_srv_t *srv = param->model->user_data;
|
||
if (param->value.set.onoff.op_en == false) {
|
||
srv->state.onoff = param->value.set.onoff.onoff;
|
||
} else {
|
||
/* TODO: Delay and state transition */
|
||
srv->state.onoff = param->value.set.onoff.onoff;
|
||
}
|
||
g_indication_flag |= INDICATION_FLAG_ONOFF;
|
||
if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
|
||
esp_ble_mesh_server_model_send_msg(param->model, ¶m->ctx,
|
||
ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS, sizeof(srv->state.onoff), &srv->state.onoff);
|
||
}
|
||
|
||
light_onoff_set(param->model, ¶m->ctx, srv->state.onoff);
|
||
}
|
||
break;
|
||
default:
|
||
ESP_LOGW(TAG, "Unknown Generic Server event 0x%02x", event);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void example_ble_mesh_lighting_server_cb(esp_ble_mesh_lighting_server_cb_event_t event,
|
||
esp_ble_mesh_lighting_server_cb_param_t *param)
|
||
{
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
uint16_t lightness;
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
uint16_t temperature;
|
||
uint16_t delta_uv;
|
||
#endif
|
||
esp_ble_mesh_server_state_value_t state = {0};
|
||
|
||
ESP_LOGD(TAG, "event 0x%02x, opcode 0x%04x, src 0x%04x, dst 0x%04x",
|
||
event, param->ctx.recv_op, param->ctx.addr, param->ctx.recv_dst);
|
||
|
||
switch (event) {
|
||
case ESP_BLE_MESH_LIGHTING_SERVER_STATE_CHANGE_EVT:
|
||
switch (param->ctx.recv_op) {
|
||
#ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
|
||
/*!< Light Lightness Message Opcode */
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK: {
|
||
/* Light Lightness Server Model - Primary Element */
|
||
ESP_LOGI(TAG, "lightness actual %d", param->value.state_change.lightness_set.lightness);
|
||
/* Update bound states */
|
||
lightness = param->value.state_change.lightness_set.lightness;
|
||
state.light_lightness_linear.lightness = convert_lightness_actual_to_linear(lightness);
|
||
esp_ble_mesh_server_model_update_state(lightness_server.model, ESP_BLE_MESH_LIGHT_LIGHTNESS_LINEAR_STATE, &state);
|
||
state.gen_onoff.onoff = lightness ? LED_ON : LED_OFF;
|
||
esp_ble_mesh_server_model_update_state(onoff_server_0.model, ESP_BLE_MESH_GENERIC_ONOFF_STATE, &state);
|
||
|
||
/* Update bound states second way */
|
||
light_lightness_actual_set(param->ctx.recv_op, param->model,
|
||
¶m->ctx, lightness);
|
||
break;
|
||
}
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET_UNACK: {
|
||
/* Light Lightness Server Model - Primary Element */
|
||
ESP_LOGI(TAG, "lightness linear %d", param->value.state_change.lightness_linear_set.lightness);
|
||
/* Update bound states */
|
||
lightness = convert_lightness_linear_to_actual(param->value.state_change.lightness_linear_set.lightness);
|
||
state.light_lightness_actual.lightness = lightness;
|
||
esp_ble_mesh_server_model_update_state(lightness_server.model, ESP_BLE_MESH_LIGHT_LIGHTNESS_ACTUAL_STATE, &state);
|
||
state.gen_onoff.onoff = lightness ? LED_ON : LED_OFF;
|
||
esp_ble_mesh_server_model_update_state(onoff_server_0.model, ESP_BLE_MESH_GENERIC_ONOFF_STATE, &state);
|
||
|
||
/* Update bound states second way */
|
||
light_lightness_linear_set(param->ctx.recv_op, param->model,
|
||
¶m->ctx, lightness);
|
||
break;
|
||
}
|
||
/*!< Light Lightness Setup Message Opcode */
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK:
|
||
/* Light Lightness Setup Server Model - Primary Element */
|
||
ESP_LOGI(TAG, "lightness default %d", param->value.state_change.lightness_default_set.lightness);
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET_UNACK:
|
||
/* Light Lightness Setup Server Model - Primary Element */
|
||
ESP_LOGI(TAG, "lightness min %d, max %d",
|
||
param->value.state_change.lightness_range_set.range_min,
|
||
param->value.state_change.lightness_range_set.range_max);
|
||
break;
|
||
#endif
|
||
#ifdef CONFIG_MESH_MODEL_CTL_SRV
|
||
/*!< Light CTL Message Opcode */
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_SET_UNACK:
|
||
/* Light CTL Server Model - Primary Element */
|
||
ESP_LOGI(TAG, "lightness 0x%04x, temperature 0x%04x, delta uv 0x%04x",
|
||
param->value.state_change.ctl_set.lightness,
|
||
param->value.state_change.ctl_set.temperature,
|
||
param->value.state_change.ctl_set.delta_uv);
|
||
/* Update bound states */
|
||
lightness = param->value.state_change.ctl_set.lightness;
|
||
temperature = param->value.state_change.ctl_set.temperature;
|
||
delta_uv = param->value.state_change.ctl_set.delta_uv;
|
||
state.light_lightness_actual.lightness = lightness;
|
||
esp_ble_mesh_server_model_update_state(lightness_server.model, ESP_BLE_MESH_LIGHT_LIGHTNESS_ACTUAL_STATE, &state);
|
||
state.light_lightness_linear.lightness = convert_lightness_actual_to_linear(lightness);
|
||
esp_ble_mesh_server_model_update_state(lightness_server.model, ESP_BLE_MESH_LIGHT_LIGHTNESS_LINEAR_STATE, &state);
|
||
state.gen_onoff.onoff = lightness ? LED_ON : LED_OFF;
|
||
esp_ble_mesh_server_model_update_state(onoff_server_0.model, ESP_BLE_MESH_GENERIC_ONOFF_STATE, &state);
|
||
|
||
/* Update bound states second way */
|
||
light_ctl_set(param->ctx.recv_op, param->model,
|
||
¶m->ctx, lightness, temperature, delta_uv);
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET_UNACK:
|
||
/* Light CTL Temperature Server Model - Secondary Element */
|
||
ESP_LOGI(TAG, "temperature 0x%04x, delta uv 0x%04x",
|
||
param->value.state_change.ctl_temp_set.temperature,
|
||
param->value.state_change.ctl_temp_set.delta_uv);
|
||
break;
|
||
/*!< Light CTL Setup Message Opcode */
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET_UNACK:
|
||
/* Light CTL Setup Server Model - Primary Element */
|
||
ESP_LOGI(TAG, "lightness 0x%04x, temperature 0x%04x, delta uv 0x%04x",
|
||
param->value.state_change.ctl_default_set.lightness,
|
||
param->value.state_change.ctl_default_set.temperature,
|
||
param->value.state_change.ctl_default_set.delta_uv);
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET:
|
||
case ESP_BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK:
|
||
/* Light CTL Setup Server Model - Primary Element */
|
||
ESP_LOGI(TAG, "temperature min 0x%04x, max 0x%04x",
|
||
param->value.state_change.ctl_temp_range_set.range_min,
|
||
param->value.state_change.ctl_temp_range_set.range_max);
|
||
break;
|
||
#endif
|
||
}
|
||
break;
|
||
default:
|
||
ESP_LOGE(TAG, "Unknown Lighting Server event 0x%02x", event);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event,
|
||
esp_ble_mesh_model_cb_param_t *param)
|
||
{
|
||
ESP_LOGD(TAG, "event 0x%02x", event);
|
||
|
||
switch (event) {
|
||
case ESP_BLE_MESH_MODEL_OPERATION_EVT:
|
||
ESP_LOGD(TAG, "ESP_BLE_MESH_MODEL_OPERATION_EVT");
|
||
ESP_LOGD(TAG, "opcode: 0x%06x", param->model_operation.opcode);
|
||
genie_model_dispatch(param->model_operation.opcode, param->model_operation.model,
|
||
param->model_operation.ctx, param->model_operation.msg, param->model_operation.length);
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_SEND_COMP_EVT:
|
||
ESP_LOGD(TAG, "ESP_BLE_MESH_MODEL_SEND_COMP_EVT");
|
||
ESP_LOGD(TAG, "opcode: 0x%06x", param->model_send_comp.opcode);
|
||
if (param->model_send_comp.err_code) {
|
||
ESP_LOGE(TAG, "Failed to send message: 0x%06x, err: %d", param->model_send_comp.opcode, param->model_send_comp.err_code);
|
||
break;
|
||
}
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT:
|
||
ESP_LOGD(TAG, "ESP_BLE_MESH_MODEL_PUBLISH_COMP_EVT");
|
||
break;
|
||
case ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT:
|
||
ESP_LOGD(TAG, "ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT");
|
||
break;
|
||
case ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT:
|
||
ESP_LOGD(TAG, "ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT");
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT:
|
||
ESP_LOGD(TAG, "ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT");
|
||
break;
|
||
case ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_COMP_EVT:
|
||
ESP_LOGD(TAG, "ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_COMP_EVT");
|
||
ESP_LOGD(TAG, "result %d, model id 0x%04x, type 0x%02x",
|
||
param->server_model_update_state.err_code,
|
||
param->server_model_update_state.model->model_id,
|
||
param->server_model_update_state.type);
|
||
break;
|
||
case ESP_BLE_MESH_MODEL_EVT_MAX:
|
||
ESP_LOGW(TAG, "ESP_BLE_MESH_MODEL_EVT_MAX");
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static esp_err_t ble_mesh_init(void)
|
||
{
|
||
esp_err_t err;
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_register_config_server_callback(example_ble_mesh_config_server_cb));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_register_generic_server_callback(example_ble_mesh_generic_server_cb));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_register_lighting_server_callback(example_ble_mesh_lighting_server_cb));
|
||
ESP_ERROR_CHECK(esp_ble_mesh_register_custom_model_callback(example_ble_mesh_custom_model_cb));
|
||
|
||
err = esp_ble_mesh_init(&provision, &composition);
|
||
if (err) {
|
||
ESP_LOGE(TAG, "Initializing mesh failed (err %d)", err);
|
||
return err;
|
||
}
|
||
|
||
ESP_ERROR_CHECK(esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT));
|
||
|
||
if (esp_ble_mesh_node_is_provisioned()) {
|
||
ESP_LOGW(TAG, "node already provisioned");
|
||
} else {
|
||
ESP_LOGW(TAG, "node not provisioned");
|
||
light_driver_breath_start(0, 255, 0); /**< green blink */
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
void config_triples(void)
|
||
{
|
||
// AuthValue = SHA256(Product ID,MAC,Secret)
|
||
char *authvalue_string = NULL;
|
||
asprintf(&authvalue_string, "%08x,%s,%s", CONFIG_TRIPLES_PRODUCT_ID, CONFIG_TRIPLES_DEVICE_NAME, CONFIG_TRIPLES_DEVICE_SECRET);
|
||
ESP_LOGI(TAG, "authvalue_string: %s", authvalue_string);
|
||
|
||
uint8_t sha256_out[32] = {0};
|
||
mbedtls_sha256_ret((const unsigned char *)authvalue_string, strlen(authvalue_string), sha256_out, 0);
|
||
memcpy(static_val, sha256_out, 16);
|
||
provision.static_val = static_val;
|
||
|
||
uint8_t product_id[4];
|
||
mac_str2hex(authvalue_string, product_id);
|
||
swap_buf(dev_uuid + 3, product_id, 4);
|
||
|
||
uint8_t ali_mac_address[6];
|
||
mac_str2hex(CONFIG_TRIPLES_DEVICE_NAME, ali_mac_address);
|
||
swap_buf(dev_uuid + 7, ali_mac_address, 6);
|
||
ali_mac_address[5] -= 2;
|
||
esp_base_mac_addr_set(ali_mac_address);
|
||
|
||
free(authvalue_string);
|
||
}
|
||
|
||
void app_main(void)
|
||
{
|
||
esp_err_t err;
|
||
|
||
esp_log_level_set("genie_event", ESP_LOG_DEBUG);
|
||
ESP_LOGI(TAG, "Initializing...");
|
||
|
||
board_init();
|
||
|
||
err = nvs_flash_init();
|
||
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||
ESP_LOGI(TAG, "nvs_flash_erase...");
|
||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||
err = nvs_flash_init();
|
||
}
|
||
ESP_ERROR_CHECK(err);
|
||
|
||
/* Open nvs namespace for storing/restoring mesh example info */
|
||
err = ble_mesh_nvs_open(&NVS_HANDLE);
|
||
if (err) {
|
||
ESP_LOGE(TAG, "ble_mesh_nvs_open failed (err %d)", err);
|
||
return;
|
||
}
|
||
|
||
#ifdef CONFIG_GENIE_RESET_BY_REPEAT
|
||
genie_reset_by_repeat_init();
|
||
#endif
|
||
|
||
config_triples();
|
||
|
||
err = bluetooth_init();
|
||
if (err) {
|
||
ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err);
|
||
return;
|
||
}
|
||
|
||
/* Initialize the Bluetooth Mesh Subsystem */
|
||
err = ble_mesh_init();
|
||
if (err) {
|
||
ESP_LOGE(TAG, "Bluetooth mesh init failed (err %d)", err);
|
||
}
|
||
}
|