diff --git a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp index aea1fcbc7b4cac..1f314ba868c910 100644 --- a/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/all-clusters-app/esp32/main/DeviceCallbacks.cpp @@ -73,7 +73,7 @@ void DeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_ break; } - ESP_LOGI(TAG, "Current free heap: %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); + ESP_LOGI(TAG, "Current free heap: %zu\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); } void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, uint8_t mask, @@ -92,12 +92,16 @@ void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, Cluster OnIdentifyPostAttributeChangeCallback(endpointId, attributeId, value); break; + case ZCL_LEVEL_CONTROL_CLUSTER_ID: + OnLevelControlAttributeChangeCallback(endpointId, attributeId, value); + break; + default: ESP_LOGI(TAG, "Unhandled cluster ID: %d", clusterId); break; } - ESP_LOGI(TAG, "Current free heap: %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); + ESP_LOGI(TAG, "Current free heap: %zu\n", heap_caps_get_free_size(MALLOC_CAP_8BIT)); } void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) @@ -138,7 +142,22 @@ void DeviceCallbacks::OnOnOffPostAttributeChangeCallback(EndpointId endpointId, VerifyOrExit(endpointId == 1 || endpointId == 2, ESP_LOGE(TAG, "Unexpected EndPoint ID: `0x%02x'", endpointId)); // At this point we can assume that value points to a bool value. - endpointId == 1 ? statusLED1.Set(*value) : statusLED2.Set(*value); + mEndpointOnOffState[endpointId - 1] = *value; + +exit: + return; +} + +void DeviceCallbacks::OnLevelControlAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + bool onOffState = mEndpointOnOffState[endpointId - 1]; + uint8_t brightness = onOffState ? *value : 0; + + VerifyOrExit(attributeId == ZCL_CURRENT_LEVEL_ATTRIBUTE_ID, ESP_LOGI(TAG, "Unhandled Attribute ID: '0x%04x", attributeId)); + VerifyOrExit(endpointId == 1 || endpointId == 2, ESP_LOGE(TAG, "Unexpected EndPoint ID: `0x%02x'", endpointId)); + + // At this point we can assume that value points to a bool value. + endpointId == 1 ? statusLED1.SetBrightness(brightness) : statusLED2.SetBrightness(brightness); exit: return; diff --git a/examples/all-clusters-app/esp32/main/LEDWidget.cpp b/examples/all-clusters-app/esp32/main/LEDWidget.cpp index d6f71eda3735e1..c6a5a8c5986510 100644 --- a/examples/all-clusters-app/esp32/main/LEDWidget.cpp +++ b/examples/all-clusters-app/esp32/main/LEDWidget.cpp @@ -27,10 +27,11 @@ #include "ScreenManager.h" -#include "driver/gpio.h" +#include "driver/ledc.h" #include "esp_log.h" #include "esp_system.h" #include "esp_timer.h" +#include "hal/ledc_types.h" void LEDWidget::Init(gpio_num_t gpioNum) { @@ -46,7 +47,25 @@ void LEDWidget::Init(gpio_num_t gpioNum) if (gpioNum < GPIO_NUM_MAX) { - gpio_set_direction(gpioNum, GPIO_MODE_OUTPUT); + ledc_timer_config_t ledc_timer = { + .speed_mode = LEDC_LOW_SPEED_MODE, // timer mode + .duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty + .timer_num = LEDC_TIMER_1, // timer index + .freq_hz = 5000, // frequency of PWM signal + .clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock + }; + ledc_timer_config(&ledc_timer); + ledc_channel_config_t ledc_channel = { + .gpio_num = gpioNum, + .speed_mode = LEDC_LOW_SPEED_MODE, + .channel = LEDC_CHANNEL_0, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = LEDC_TIMER_1, + .duty = 0, + .hpoint = 0, + }; + ledc_channel_config(&ledc_channel); + mDefaultOnBrightness = UINT8_MAX; } } @@ -56,6 +75,25 @@ void LEDWidget::Set(bool state) DoSet(state); } +void LEDWidget::SetBrightness(uint8_t brightness) +{ + if (mGPIONum < GPIO_NUM_MAX) + { + ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, brightness); + ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); + } + if (brightness > 0) + { + mDefaultOnBrightness = brightness; + } +#if CONFIG_HAVE_DISPLAY + if (mVLED1 != -1) + { + ScreenManager::SetVLED(mVLED1, mState); + } +#endif // CONFIG_HAVE_DISPLAY +} + void LEDWidget::Blink(uint32_t changeRateMS) { Blink(changeRateMS, changeRateMS); @@ -119,7 +157,8 @@ void LEDWidget::DoSet(bool state) mState = state; if (mGPIONum < GPIO_NUM_MAX) { - gpio_set_level(mGPIONum, (state) ? 1 : 0); + ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, state ? mDefaultOnBrightness : 0); + ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); } if (stateChange) { diff --git a/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h b/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h index 0be901539a58fd..e68b61a018d077 100644 --- a/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h +++ b/examples/all-clusters-app/esp32/main/include/DeviceCallbacks.h @@ -41,5 +41,8 @@ class DeviceCallbacks : public chip::DeviceManager::CHIPDeviceManagerCallbacks void OnInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); void OnSessionEstablished(const chip::DeviceLayer::ChipDeviceEvent * event); void OnOnOffPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); + void OnLevelControlAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); void OnIdentifyPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); + + bool mEndpointOnOffState[2]; }; diff --git a/examples/all-clusters-app/esp32/main/include/LEDWidget.h b/examples/all-clusters-app/esp32/main/include/LEDWidget.h index 340914c60eee5c..a3f6f6c9c4ed08 100644 --- a/examples/all-clusters-app/esp32/main/include/LEDWidget.h +++ b/examples/all-clusters-app/esp32/main/include/LEDWidget.h @@ -31,11 +31,21 @@ class LEDWidget { public: void Init(gpio_num_t gpioNum); + void Set(bool state); + + void SetStateMask(bool state); + + void SetBrightness(uint8_t brightness); + void Blink(uint32_t changeRateMS); + void Blink(uint32_t onTimeMS, uint32_t offTimeMS); + void BlinkOnError(); + void Animate(); + #if CONFIG_HAVE_DISPLAY void SetVLED(int id1, int id2); #endif @@ -44,6 +54,7 @@ class LEDWidget int64_t mLastChangeTimeUS; uint32_t mBlinkOnTimeMS; uint32_t mBlinkOffTimeMS; + uint8_t mDefaultOnBrightness; gpio_num_t mGPIONum; int mVLED1; int mVLED2; diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index 4bcfb74491f916..123a744ec0fe55 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -49,6 +50,8 @@ #include #include #include +#include +#include #include #include #include @@ -363,6 +366,16 @@ class CustomScreen : public Screen #endif // CONFIG_DEVICE_TYPE_M5STACK +void SetupInitialLevelControlValues(chip::EndpointId endpointId) +{ + uint8_t level = UINT8_MAX; + + emberAfWriteAttribute(endpointId, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_CURRENT_LEVEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &level, + ZCL_DATA8_ATTRIBUTE_TYPE); + emberAfWriteAttribute(endpointId, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_ON_LEVEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &level, + ZCL_DATA8_ATTRIBUTE_TYPE); +} + void SetupPretendDevices() { AddDevice("Watch"); @@ -380,9 +393,13 @@ void SetupPretendDevices() AddEndpoint("1"); AddCluster("OnOff"); AddAttribute("OnOff", "Off"); + AddCluster("Level Control"); + AddAttribute("Current Level", "255"); AddEndpoint("2"); AddCluster("OnOff"); AddAttribute("OnOff", "Off"); + AddCluster("Level Control"); + AddAttribute("Current Level", "255"); AddDevice("Thermometer"); AddEndpoint("External"); @@ -614,6 +631,8 @@ extern "C" void app_main() #endif SetupPretendDevices(); + SetupInitialLevelControlValues(/* endpointId = */ 1); + SetupInitialLevelControlValues(/* endpointId = */ 2); std::string qrCodeText = createSetupPayload(); ESP_LOGI(TAG, "QR CODE Text: '%s'", qrCodeText.c_str());