diff --git a/examples/light_network_prov/main/app_driver.cpp b/examples/light_network_prov/main/app_driver.cpp index d77e9c313..1cbc88303 100644 --- a/examples/light_network_prov/main/app_driver.cpp +++ b/examples/light_network_prov/main/app_driver.cpp @@ -23,68 +23,64 @@ static const char *TAG = "app_driver"; extern uint16_t light_endpoint_id; /* Do any conversions/remapping for the actual value here */ -static esp_err_t app_driver_light_set_power(led_indicator_handle_t handle, esp_matter_attr_val_t *val) +esp_err_t app_driver_light_set_power(led_indicator_handle_t handle, bool val) { #if CONFIG_BSP_LEDS_NUM > 0 esp_err_t err = ESP_OK; - if (val->val.b) { + if (val) { err = led_indicator_start(handle, BSP_LED_ON); } else { err = led_indicator_start(handle, BSP_LED_OFF); } return err; #else - ESP_LOGI(TAG, "LED set power: %d", val->val.b); + ESP_LOGI(TAG, "LED set power: %d", val); return ESP_OK; #endif } -static esp_err_t app_driver_light_set_brightness(led_indicator_handle_t handle, esp_matter_attr_val_t *val) +esp_err_t app_driver_light_set_brightness(led_indicator_handle_t handle, int val) { - int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); #if CONFIG_BSP_LEDS_NUM > 0 - return led_indicator_set_brightness(handle, value); + return led_indicator_set_brightness(handle, val); #else - ESP_LOGI(TAG, "LED set brightness: %d", value); + ESP_LOGI(TAG, "LED set brightness: %d", val); return ESP_OK; #endif } -static esp_err_t app_driver_light_set_hue(led_indicator_handle_t handle, esp_matter_attr_val_t *val) +esp_err_t app_driver_light_set_hue(led_indicator_handle_t handle, int val) { - int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE); #if CONFIG_BSP_LEDS_NUM > 0 led_indicator_ihsv_t hsv; hsv.value = led_indicator_get_hsv(handle); - hsv.h = value; + hsv.h = val; return led_indicator_set_hsv(handle, hsv.value); #else - ESP_LOGI(TAG, "LED set hue: %d", value); + ESP_LOGI(TAG, "LED set hue: %d", val); return ESP_OK; #endif } -static esp_err_t app_driver_light_set_saturation(led_indicator_handle_t handle, esp_matter_attr_val_t *val) +esp_err_t app_driver_light_set_saturation(led_indicator_handle_t handle, int val) { - int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION); #if CONFIG_BSP_LEDS_NUM > 0 led_indicator_ihsv_t hsv; hsv.value = led_indicator_get_hsv(handle); - hsv.s = value; + hsv.s = val; return led_indicator_set_hsv(handle, hsv.value); #else - ESP_LOGI(TAG, "LED set saturation: %d", value); + ESP_LOGI(TAG, "LED set saturation: %d", val); return ESP_OK; #endif } -static esp_err_t app_driver_light_set_temperature(led_indicator_handle_t handle, esp_matter_attr_val_t *val) +esp_err_t app_driver_light_set_temperature(led_indicator_handle_t handle, int val) { - uint32_t value = REMAP_TO_RANGE_INVERSE(val->val.u16, STANDARD_TEMPERATURE_FACTOR); #if CONFIG_BSP_LEDS_NUM > 0 - return led_indicator_set_color_temperature(handle, value); + return led_indicator_set_color_temperature(handle, val); #else - ESP_LOGI(TAG, "LED set temperature: %ld", value); + ESP_LOGI(TAG, "LED set temperature: %ld", val); return ESP_OK; #endif } @@ -112,19 +108,19 @@ esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_ led_indicator_handle_t handle = (led_indicator_handle_t)driver_handle; if (cluster_id == OnOff::Id) { if (attribute_id == OnOff::Attributes::OnOff::Id) { - err = app_driver_light_set_power(handle, val); + err = app_driver_light_set_power(handle, val->val.b); } } else if (cluster_id == LevelControl::Id) { if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { - err = app_driver_light_set_brightness(handle, val); + err = app_driver_light_set_brightness(handle, val->val.u8); } } else if (cluster_id == ColorControl::Id) { if (attribute_id == ColorControl::Attributes::CurrentHue::Id) { - err = app_driver_light_set_hue(handle, val); + err = app_driver_light_set_hue(handle, val->val.u16); } else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) { - err = app_driver_light_set_saturation(handle, val); + err = app_driver_light_set_saturation(handle, val->val.u16); } else if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) { - err = app_driver_light_set_temperature(handle, val); + err = app_driver_light_set_temperature(handle, val->val.u16); } } } @@ -142,7 +138,7 @@ esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id) /* Setting brightness */ attribute = attribute::get(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id); attribute::get_val(attribute, &val); - err |= app_driver_light_set_brightness(handle, &val); + err |= app_driver_light_set_brightness(handle, val.val.u8); /* Setting color */ attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorMode::Id); @@ -151,16 +147,16 @@ esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id) /* Setting hue */ attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id); attribute::get_val(attribute, &val); - err |= app_driver_light_set_hue(handle, &val); + err |= app_driver_light_set_hue(handle, val.val.u16); /* Setting saturation */ attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id); attribute::get_val(attribute, &val); - err |= app_driver_light_set_saturation(handle, &val); + err |= app_driver_light_set_saturation(handle, val.val.u16); } else if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kColorTemperature) { /* Setting temperature */ attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id); attribute::get_val(attribute, &val); - err |= app_driver_light_set_temperature(handle, &val); + err |= app_driver_light_set_temperature(handle, val.val.u16); } else { ESP_LOGE(TAG, "Color mode not supported"); } @@ -168,7 +164,7 @@ esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id) /* Setting power */ attribute = attribute::get(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id); attribute::get_val(attribute, &val); - err |= app_driver_light_set_power(handle, &val); + err |= app_driver_light_set_power(handle, val.val.b); return err; } diff --git a/examples/light_network_prov/main/app_main.cpp b/examples/light_network_prov/main/app_main.cpp index fc222d3d4..923c69184 100644 --- a/examples/light_network_prov/main/app_main.cpp +++ b/examples/light_network_prov/main/app_main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,9 @@ #include "app-common/zap-generated/ids/Attributes.h" #include "app-common/zap-generated/ids/Clusters.h" #include "network_provisioning/manager.h" +#include "platform/CHIPDeviceEvent.h" #include "platform/PlatformManager.h" +#include "support/CodeUtils.h" #if CHIP_DEVICE_CONFIG_ENABLE_THREAD #include #include @@ -62,6 +65,7 @@ static const uint16_t s_decryption_key_len = decryption_key_end - decryption_key #endif // CONFIG_ENABLE_ENCRYPTED_OTA static esp_rmaker_device_t *light_device; +static bool rmaker_init_done = false; static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) { @@ -117,6 +121,16 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) break; } + case chip::DeviceLayer::DeviceEventType::kThreadConnectivityChange: { + // When Thread is attached with network provisioning, try to start DNS-SD server to advertise Matter + // commissionable service + if (event->ThreadConnectivityChange.Result == chip::DeviceLayer::kConnectivity_Established) { + chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t){ chip::app::DnssdServer::Instance().StartServer(); }, + reinterpret_cast(nullptr)); + } + break; + } + case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved: ESP_LOGI(TAG, "Fabric will be removed"); break; @@ -143,6 +157,75 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) } } +static esp_err_t app_matter_report_power(bool val) +{ + esp_matter_attr_val_t value = esp_matter_bool(val); + return attribute::report(light_endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &value); +} + +static esp_err_t app_matter_report_hue(int val) +{ + esp_matter_attr_val_t value = esp_matter_uint8(REMAP_TO_RANGE(val, STANDARD_HUE, MATTER_HUE)); + return attribute::report(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id, &value); +} + +static esp_err_t app_matter_report_saturation(int val) +{ + esp_matter_attr_val_t value = esp_matter_uint8(REMAP_TO_RANGE(val, STANDARD_SATURATION, MATTER_SATURATION)); + return attribute::report(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id, &value); +} + +static esp_err_t app_matter_report_brightness(int val) +{ + esp_matter_attr_val_t value = esp_matter_nullable_uint8(REMAP_TO_RANGE(val, STANDARD_BRIGHTNESS, MATTER_BRIGHTNESS)); + return attribute::report(light_endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &value); +} + +static const char *app_matter_get_rmaker_param_name_from_id(uint32_t cluster_id, uint32_t attribute_id) +{ + if (cluster_id == OnOff::Id) { + if (attribute_id == OnOff::Attributes::OnOff::Id) { + return ESP_RMAKER_DEF_POWER_NAME; + } + } else if (cluster_id == LevelControl::Id) { + if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { + return ESP_RMAKER_DEF_BRIGHTNESS_NAME; + } + } else if (cluster_id == ColorControl::Id) { + if (attribute_id == ColorControl::Attributes::CurrentHue::Id) { + return ESP_RMAKER_DEF_HUE_NAME; + } else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) { + return ESP_RMAKER_DEF_SATURATION_NAME; + } + } + return NULL; +} + +static esp_rmaker_param_val_t app_matter_get_rmaker_val(esp_matter_attr_val_t *val, uint32_t cluster_id, + uint32_t attribute_id) +{ + /* Attributes which need to be remapped */ + if (cluster_id == LevelControl::Id) { + if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { + int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); + return esp_rmaker_int(value); + } + } else if (cluster_id == ColorControl::Id) { + if (attribute_id == ColorControl::Attributes::CurrentHue::Id) { + int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE); + return esp_rmaker_int(value); + } else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) { + int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION); + return esp_rmaker_int(value); + } + } else if (cluster_id == OnOff::Id) { + if (attribute_id == OnOff::Attributes::OnOff::Id) { + return esp_rmaker_bool(val->val.b); + } + } + return esp_rmaker_int(0); +} + static esp_err_t bulk_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[], uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx) { @@ -159,28 +242,20 @@ static esp_err_t bulk_write_cb(const esp_rmaker_device_t *device, const esp_rmak const char *param_name = esp_rmaker_param_get_name(param); if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) { ESP_LOGI(TAG, "Received value = %s for %s - %s", val.val.b ? "true" : "false", device_name, param_name); - matter_val.type = ESP_MATTER_VAL_TYPE_BOOLEAN; - matter_val.val.b = val.val.b; - app_driver_attribute_update(light_handle, light_endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, - &matter_val); + app_driver_light_set_power(light_handle, val.val.b); + app_matter_report_power(val.val.b); } else if (strcmp(param_name, ESP_RMAKER_DEF_BRIGHTNESS_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); - matter_val.type = ESP_MATTER_VAL_TYPE_UINT8; - matter_val.val.u8 = (uint8_t)(val.val.i * 254 / 100); - app_driver_attribute_update(light_handle, light_endpoint_id, LevelControl::Id, - LevelControl::Attributes::CurrentLevel::Id, &matter_val); + app_driver_light_set_brightness(light_handle, val.val.i); + app_matter_report_brightness(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_HUE_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); - matter_val.type = ESP_MATTER_VAL_TYPE_UINT16; - matter_val.val.u16 = (uint16_t)(val.val.i * 254 / 360); - app_driver_attribute_update(light_handle, light_endpoint_id, ColorControl::Id, - ColorControl::Attributes::CurrentHue::Id, &matter_val); + app_driver_light_set_hue(light_handle, val.val.i); + app_matter_report_hue(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_SATURATION_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); - matter_val.type = ESP_MATTER_VAL_TYPE_UINT16; - matter_val.val.u16 = (uint16_t)(val.val.i * 254 / 100); - app_driver_attribute_update(light_handle, light_endpoint_id, ColorControl::Id, - ColorControl::Attributes::CurrentSaturation::Id, &matter_val); + app_driver_light_set_saturation(light_handle, val.val.i); + app_matter_report_saturation(val.val.i); } else { ESP_LOGI(TAG, "Updating for %s", param_name); } @@ -210,6 +285,30 @@ static esp_err_t app_attribute_update_cb(attribute::callback_type_t type, uint16 /* Driver update */ app_driver_handle_t driver_handle = (app_driver_handle_t)priv_data; err = app_driver_attribute_update(driver_handle, endpoint_id, cluster_id, attribute_id, val); + } else if (type == POST_UPDATE) { + if (!rmaker_init_done) { + ESP_LOGI(TAG, "RainMaker init not done. Not processing attribute update"); + return ESP_OK; + } + + /* RainMaker update */ + const char *device_name = "Light"; + const char *param_name = app_matter_get_rmaker_param_name_from_id(cluster_id, attribute_id); + if (!param_name) { + ESP_LOGD(TAG, "param name not handled"); + return ESP_FAIL; + } + + const esp_rmaker_node_t *node = esp_rmaker_get_node(); + esp_rmaker_device_t *device = esp_rmaker_node_get_device_by_name(node, device_name); + esp_rmaker_param_t *param = esp_rmaker_device_get_param_by_name(device, param_name); + if (!param) { + ESP_LOGE(TAG, "Param %s not found", param_name); + return ESP_FAIL; + } + + esp_rmaker_param_val_t rmaker_val = app_matter_get_rmaker_val(val, cluster_id, attribute_id); + return esp_rmaker_param_update_and_report(param, rmaker_val); } return err; @@ -316,10 +415,15 @@ extern "C" void app_main() .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), }; set_openthread_platform_config(&ot_config); - // This will not really initiaize Thread stack as the thread stack has been initialzed in app_network. + // This will not really initialize Thread stack as the thread stack has been initialized in app_network. // We call this function to pass the OpenThread instance to GenericThreadStackManagerImpl_OpenThread // so that it can be used for SRP service registration and network commissioning driver. chip::DeviceLayer::ThreadStackMgr().InitThreadStack(); + // Then try to start DNS-SD advertisement if Thread is provisioned. + if (chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned()) { + chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t){ chip::app::DnssdServer::Instance().StartServer(); }, + reinterpret_cast(nullptr)); + } #endif /* Starting driver with default values */ @@ -338,6 +442,7 @@ extern "C" void app_main() if (is_network_provisioned && esp_rmaker_user_node_mapping_get_state() == ESP_RMAKER_USER_MAPPING_DONE) { chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t) { chip::DeviceLayer::Internal::BLEMgr().Shutdown(); }); } + rmaker_init_done = true; #if CONFIG_ENABLE_CHIP_SHELL esp_matter::console::diagnostics_register_commands(); diff --git a/examples/light_network_prov/main/app_priv.h b/examples/light_network_prov/main/app_priv.h index 7844ce5bc..64cf9a2c5 100644 --- a/examples/light_network_prov/main/app_priv.h +++ b/examples/light_network_prov/main/app_priv.h @@ -8,6 +8,7 @@ #pragma once +#include "led_indicator.h" #include #include @@ -16,9 +17,9 @@ #endif /** Standard max values (used for remapping attributes) */ -#define STANDARD_BRIGHTNESS 255 +#define STANDARD_BRIGHTNESS 100 #define STANDARD_HUE 360 -#define STANDARD_SATURATION 255 +#define STANDARD_SATURATION 100 #define STANDARD_TEMPERATURE_FACTOR 1000000 /** Matter max values (used for remapping attributes) */ @@ -80,6 +81,16 @@ esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_ */ esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id); +esp_err_t app_driver_light_set_power(led_indicator_handle_t handle, bool val); + +esp_err_t app_driver_light_set_brightness(led_indicator_handle_t handle, int val); + +esp_err_t app_driver_light_set_hue(led_indicator_handle_t handle, int val); + +esp_err_t app_driver_light_set_saturation(led_indicator_handle_t handle, int val); + +esp_err_t app_driver_light_set_temperature(led_indicator_handle_t handle, int val); + #if CHIP_DEVICE_CONFIG_ENABLE_THREAD #define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ { \