feat(matter): Adds Matter Enhanced Color Light Endpoint (CW/WW/RGB) (#10657)

* feat(matter): created enhanced color light new matter endpoint and example
This commit is contained in:
Rodrigo Garcia 2024-12-02 19:26:13 -03:00 committed by GitHub
parent c2ce738cae
commit 9d8df8b315
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 708 additions and 0 deletions

View file

@ -172,6 +172,7 @@ set(ARDUINO_LIBRARY_Matter_SRCS
libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp
libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp
libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp
libraries/Matter/src/Matter.cpp)
set(ARDUINO_LIBRARY_PPP_SRCS

View file

@ -0,0 +1,205 @@
// Copyright 2024 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.
// Matter Manager
#include <Matter.h>
#include <WiFi.h>
#include <Preferences.h>
// List of Matter Endpoints for this Node
// Color Light Endpoint
MatterEnhancedColorLight EnhancedColorLight;
// It will use HSV color to control all Matter Attribute Changes
HsvColor_t currentHSVColor = {0, 0, 0};
// it will keep last OnOff & HSV Color state stored, using Preferences
Preferences matterPref;
const char *onOffPrefKey = "OnOff";
const char *hsvColorPrefKey = "HSV";
// set your board RGB LED pin here
#ifdef RGB_BUILTIN
const uint8_t ledPin = RGB_BUILTIN;
#else
const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN
#warning "Do not forget to set the RGB LED pin"
#endif
// set your board USER BUTTON pin here
const uint8_t buttonPin = 0; // Set your pin here. Using BOOT Button. C6/C3 use GPIO9.
// WiFi is manually set and started
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
const char *password = "your-password"; // Change this to your WiFi password
// Set the RGB LED Light based on the current state of the Enhanced Color Light
bool setLightState(bool state, espHsvColor_t colorHSV, uint8_t brighteness, uint16_t temperature_Mireds) {
if (state) {
#ifdef RGB_BUILTIN
// currentHSVColor keeps final color result
espRgbColor_t rgbColor = espHsvColorToRgbColor(currentHSVColor);
// set the RGB LED
rgbLedWrite(ledPin, rgbColor.r, rgbColor.g, rgbColor.b);
#else
// No Color RGB LED, just use the HSV value (brightness) to control the LED
analogWrite(ledPin, colorHSV.v);
#endif
} else {
digitalWrite(ledPin, LOW);
}
// store last HSV Color and OnOff state for when the Light is restarted / power goes off
matterPref.putBool(onOffPrefKey, state);
matterPref.putUInt(hsvColorPrefKey, currentHSVColor.h << 16 | currentHSVColor.s << 8 | currentHSVColor.v);
// This callback must return the success state to Matter core
return true;
}
void setup() {
// Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch
pinMode(buttonPin, INPUT_PULLUP);
// Initialize the LED (light) GPIO and Matter End Point
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
while (!Serial) {
delay(100);
}
// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
// enable IPv6
WiFi.enableIPv6(true);
// Manually connect to WiFi
WiFi.begin(ssid, password);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\r\nWiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(500);
// Initialize Matter EndPoint
matterPref.begin("MatterPrefs", false);
// default OnOff state is ON if not stored before
bool lastOnOffState = matterPref.getBool(onOffPrefKey, true);
// default HSV color is (21, 216, 25) - Warm White Color at 10% intensity
uint32_t prefHsvColor = matterPref.getUInt(hsvColorPrefKey, 21 << 16 | 216 << 8 | 25);
currentHSVColor = {uint8_t(prefHsvColor >> 16), uint8_t(prefHsvColor >> 8), uint8_t(prefHsvColor)};
EnhancedColorLight.begin(lastOnOffState, currentHSVColor);
// set the callback function to handle the Light state change
EnhancedColorLight.onChange(setLightState);
// lambda functions are used to set the attribute change callbacks
EnhancedColorLight.onChangeOnOff([](bool state) {
Serial.printf("Light OnOff changed to %s\r\n", state ? "ON" : "OFF");
return true;
});
EnhancedColorLight.onChangeColorTemperature([](uint16_t colorTemperature) {
Serial.printf("Light Color Temperature changed to %d\r\n", colorTemperature);
// get correspondent Hue and Saturation of the color temperature
HsvColor_t hsvTemperature = espRgbColorToHsvColor(espCTToRgbColor(colorTemperature));
// keep previous the brightness and just change the Hue and Saturation
currentHSVColor.h = hsvTemperature.h;
currentHSVColor.s = hsvTemperature.s;
return true;
});
EnhancedColorLight.onChangeBrightness([](uint8_t brightness) {
Serial.printf("Light brightness changed to %d\r\n", brightness);
// change current brightness (HSV value)
currentHSVColor.v = brightness;
return true;
});
EnhancedColorLight.onChangeColorHSV([](HsvColor_t hsvColor) {
Serial.printf("Light HSV Color changed to (%d,%d,%d)\r\n", hsvColor.h, hsvColor.s, hsvColor.v);
// keep the current brightness and just change Hue and Saturation
currentHSVColor.h = hsvColor.h;
currentHSVColor.s = hsvColor.s;
return true;
});
// Matter beginning - Last step, after all EndPoints are initialized
Matter.begin();
// This may be a restart of a already commissioned Matter accessory
if (Matter.isDeviceCommissioned()) {
Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
Serial.printf(
"Initial state: %s | RGB Color: (%d,%d,%d) \r\n", EnhancedColorLight ? "ON" : "OFF", EnhancedColorLight.getColorRGB().r,
EnhancedColorLight.getColorRGB().g, EnhancedColorLight.getColorRGB().b
);
// configure the Light based on initial on-off state and its color
EnhancedColorLight.updateAccessory();
}
}
// Button control
uint32_t button_time_stamp = 0; // debouncing control
bool button_state = false; // false = released | true = pressed
const uint32_t debouceTime = 250; // button debouncing time (ms)
const uint32_t decommissioningTimeout = 10000; // keep the button pressed for 10s to decommission the light
void loop() {
// Check Matter Light Commissioning state, which may change during execution of loop()
if (!Matter.isDeviceCommissioned()) {
Serial.println("");
Serial.println("Matter Node is not commissioned yet.");
Serial.println("Initiate the device discovery in your Matter environment.");
Serial.println("Commission it to your Matter hub with the manual pairing code or QR code");
Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str());
Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str());
// waits for Matter Light Commissioning.
uint32_t timeCount = 0;
while (!Matter.isDeviceCommissioned()) {
delay(100);
if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec
Serial.println("Matter Node not commissioned yet. Waiting for commissioning.");
}
}
Serial.printf(
"Initial state: %s | RGB Color: (%d,%d,%d) \r\n", EnhancedColorLight ? "ON" : "OFF", EnhancedColorLight.getColorRGB().r,
EnhancedColorLight.getColorRGB().g, EnhancedColorLight.getColorRGB().b
);
// configure the Light based on initial on-off state and its color
EnhancedColorLight.updateAccessory();
Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
}
// A button is also used to control the light
// Check if the button has been pressed
if (digitalRead(buttonPin) == LOW && !button_state) {
// deals with button debouncing
button_time_stamp = millis(); // record the time while the button is pressed.
button_state = true; // pressed.
}
// Onboard User Button is used as a Light toggle switch or to decommission it
uint32_t time_diff = millis() - button_time_stamp;
if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) {
button_state = false; // released
// Toggle button is released - toggle the light
Serial.println("User button released. Toggling Light!");
EnhancedColorLight.toggle(); // Matter Controller also can see the change
// Factory reset is triggered if the button is pressed longer than 10 seconds
if (time_diff > decommissioningTimeout) {
Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
EnhancedColorLight = false; // turn the light off
Matter.decommission();
}
}
}

View file

@ -0,0 +1,7 @@
{
"fqbn_append": "PartitionScheme=huge_app",
"requires": [
"CONFIG_SOC_WIFI_SUPPORTED=y",
"CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y"
]
}

View file

@ -12,6 +12,7 @@ MatterOnOffLight KEYWORD1
MatterDimmableLight KEYWORD1
MatterColorTemperatureLight KEYWORD1
MatterColorLight KEYWORD1
MatterEnhancedColorLight KEYWORD1
MatterEndPoint KEYWORD1
#######################################

View file

@ -23,6 +23,7 @@
#include <MatterEndpoints/MatterDimmableLight.h>
#include <MatterEndpoints/MatterColorTemperatureLight.h>
#include <MatterEndpoints/MatterColorLight.h>
#include <MatterEndpoints/MatterEnhancedColorLight.h>
using namespace esp_matter;
@ -52,6 +53,7 @@ public:
friend class MatterDimmableLight;
friend class MatterColorTemperatureLight;
friend class MatterColorLight;
friend class MatterEnhancedColorLight;
protected:
static void _init();

View file

@ -57,6 +57,7 @@ public:
void onChangeOnOff(EndPointOnOffCB onChangeCB) {
_onChangeOnOffCB = onChangeCB;
}
// User Callback for whenever the Light brightness value [0..255] is changed by the Matter Controller
using EndPointBrightnessCB = std::function<bool(uint8_t)>;
void onChangeBrightness(EndPointBrightnessCB onChangeCB) {

View file

@ -0,0 +1,389 @@
// Copyright 2024 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 <sdkconfig.h>
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
#include <Matter.h>
#include <app/server/Server.h>
#include <MatterEndpoints/MatterEnhancedColorLight.h>
using namespace esp_matter;
using namespace esp_matter::endpoint;
using namespace chip::app::Clusters;
// endpoint for enhanced color light device
namespace esp_matter {
using namespace cluster;
namespace endpoint {
namespace enhanced_color_light {
typedef struct config {
cluster::descriptor::config_t descriptor;
cluster::identify::config_t identify;
cluster::groups::config_t groups;
cluster::scenes_management::config_t scenes_management;
cluster::on_off::config_t on_off;
cluster::level_control::config_t level_control;
cluster::color_control::config_t color_control;
} config_t;
uint32_t get_device_type_id() {
return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID;
}
uint8_t get_device_type_version() {
return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_VERSION;
}
esp_err_t add(endpoint_t *endpoint, config_t *config) {
if (!endpoint) {
log_e("Endpoint cannot be NULL");
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version());
if (err != ESP_OK) {
log_e("Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err);
return err;
}
descriptor::create(endpoint, &(config->descriptor), CLUSTER_FLAG_SERVER);
cluster_t *identify_cluster = identify::create(endpoint, &(config->identify), CLUSTER_FLAG_SERVER);
identify::command::create_trigger_effect(identify_cluster);
groups::create(endpoint, &(config->groups), CLUSTER_FLAG_SERVER);
cluster_t *scenes_cluster = scenes_management::create(endpoint, &(config->scenes_management), CLUSTER_FLAG_SERVER);
scenes_management::command::create_copy_scene(scenes_cluster);
scenes_management::command::create_copy_scene_response(scenes_cluster);
on_off::create(endpoint, &(config->on_off), CLUSTER_FLAG_SERVER, on_off::feature::lighting::get_id());
level_control::create(
endpoint, &(config->level_control), CLUSTER_FLAG_SERVER, level_control::feature::on_off::get_id() | level_control::feature::lighting::get_id()
);
color_control::create(
endpoint, &(config->color_control), CLUSTER_FLAG_SERVER,
color_control::feature::hue_saturation::get_id() | color_control::feature::color_temperature::get_id()
);
return ESP_OK;
}
endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) {
endpoint_t *endpoint = endpoint::create(node, flags, priv_data);
add(endpoint, config);
return endpoint;
}
} // namespace enhanced_color_light
} // namespace endpoint
} // namespace esp_matter
bool MatterEnhancedColorLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) {
bool ret = true;
if (!started) {
log_e("Matter Enhanced ColorLight device has not begun.");
return false;
}
log_d(
"Enhanced ColorAttr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u, type: %u", endpoint_id, cluster_id, attribute_id, val->val.u32,
val->type
);
if (endpoint_id == getEndPointId()) {
switch (cluster_id) {
case OnOff::Id:
if (attribute_id == OnOff::Attributes::OnOff::Id) {
log_d("Enhanced ColorLight On/Off State changed to %d", val->val.b);
if (_onChangeOnOffCB != NULL) {
ret &= _onChangeOnOffCB(val->val.b);
}
if (_onChangeCB != NULL) {
ret &= _onChangeCB(val->val.b, colorHSV, brightnessLevel, colorTemperatureLevel);
}
if (ret == true) {
onOffState = val->val.b;
}
}
break;
case LevelControl::Id:
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
log_d("Enhanced ColorLight Brightness changed to %d", val->val.u8);
if (_onChangeBrightnessCB != NULL) {
ret &= _onChangeBrightnessCB(val->val.u8);
}
if (_onChangeCB != NULL) {
ret &= _onChangeCB(onOffState, colorHSV, val->val.u8, colorTemperatureLevel);
}
if (ret == true) {
colorHSV.v = val->val.u8;
}
}
break;
case ColorControl::Id:
{
if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) {
log_d("Enhanced ColorLight Temperature changed to %d", val->val.u16);
if (_onChangeTemperatureCB != NULL) {
ret &= _onChangeTemperatureCB(val->val.u16);
}
if (_onChangeCB != NULL) {
ret &= _onChangeCB(onOffState, colorHSV, brightnessLevel, val->val.u16);
}
if (ret == true) {
colorTemperatureLevel = val->val.u16;
}
break;
}
if (attribute_id != ColorControl::Attributes::CurrentHue::Id && attribute_id != ColorControl::Attributes::CurrentSaturation::Id) {
log_i("Color Control Attribute ID [%x] not processed.", attribute_id);
break;
}
espHsvColor_t hsvColor = {colorHSV.h, colorHSV.s, colorHSV.v};
if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
log_d("Enhanced ColorLight Hue changed to %d", val->val.u8);
hsvColor.h = val->val.u8;
} else { // attribute_id == ColorControl::Attributes::CurrentSaturation::Id)
log_d("Enhanced ColorLight Saturation changed to %d", val->val.u8);
hsvColor.s = val->val.u8;
}
if (_onChangeColorCB != NULL) {
ret &= _onChangeColorCB(hsvColor);
}
if (_onChangeCB != NULL) {
ret &= _onChangeCB(onOffState, hsvColor, brightnessLevel, colorTemperatureLevel);
}
if (ret == true) {
colorHSV = {hsvColor.h, hsvColor.s, hsvColor.v};
}
break;
}
}
}
return ret;
}
MatterEnhancedColorLight::MatterEnhancedColorLight() {}
MatterEnhancedColorLight::~MatterEnhancedColorLight() {
end();
}
bool MatterEnhancedColorLight::begin(bool initialState, espHsvColor_t _colorHSV, uint8_t brightness, uint16_t ColorTemperature) {
ArduinoMatter::_init();
enhanced_color_light::config_t light_config;
light_config.on_off.on_off = initialState;
light_config.on_off.lighting.start_up_on_off = nullptr;
onOffState = initialState;
light_config.level_control.current_level = brightness;
light_config.level_control.lighting.start_up_current_level = nullptr;
light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;
light_config.color_control.color_temperature.color_temperature_mireds = ColorTemperature;
light_config.color_control.color_temperature.startup_color_temperature_mireds = nullptr;
colorTemperatureLevel = ColorTemperature;
light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation;
light_config.color_control.hue_saturation.current_hue = _colorHSV.h;
light_config.color_control.hue_saturation.current_saturation = _colorHSV.s;
colorHSV = {_colorHSV.h, _colorHSV.s, _colorHSV.v};
// endpoint handles can be used to add/modify clusters.
endpoint_t *endpoint = enhanced_color_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this);
if (endpoint == nullptr) {
log_e("Failed to create Enhanced ColorLight endpoint");
return false;
}
setEndPointId(endpoint::get_id(endpoint));
log_i("Enhanced ColorLight created with endpoint_id %d", getEndPointId());
/* Mark deferred persistence for some attributes that might be changed rapidly */
cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id);
attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id);
attribute::set_deferred_persistence(current_level_attribute);
started = true;
return true;
}
void MatterEnhancedColorLight::end() {
started = false;
}
bool MatterEnhancedColorLight::setOnOff(bool newState) {
if (!started) {
log_e("Matter Enhanced ColorLight device has not begun.");
return false;
}
// avoid processing the a "no-change"
if (onOffState == newState) {
return true;
}
onOffState = newState;
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
cluster_t *cluster = cluster::get(endpoint, OnOff::Id);
attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id);
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
attribute::get_val(attribute, &val);
if (val.val.b != onOffState) {
val.val.b = onOffState;
attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val);
}
return true;
}
void MatterEnhancedColorLight::updateAccessory() {
if (_onChangeCB != NULL) {
_onChangeCB(onOffState, colorHSV, brightnessLevel, colorTemperatureLevel);
}
}
bool MatterEnhancedColorLight::getOnOff() {
return onOffState;
}
bool MatterEnhancedColorLight::toggle() {
return setOnOff(!onOffState);
}
bool MatterEnhancedColorLight::setBrightness(uint8_t newBrightness) {
if (!started) {
log_w("Matter Enhanced ColorLight device has not begun.");
return false;
}
// avoid processing the a "no-change"
if (brightnessLevel == newBrightness) {
return true;
}
brightnessLevel = newBrightness;
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
cluster_t *cluster = cluster::get(endpoint, LevelControl::Id);
attribute_t *attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id);
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
attribute::get_val(attribute, &val);
if (val.val.u8 != brightnessLevel) {
val.val.u8 = brightnessLevel;
attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val);
}
return true;
}
uint8_t MatterEnhancedColorLight::getBrightness() {
return brightnessLevel;
}
bool MatterEnhancedColorLight::setColorTemperature(uint16_t newTemperature) {
if (!started) {
log_w("Matter Enhanced ColorLight device has not begun.");
return false;
}
// avoid processing the a "no-change"
if (colorTemperatureLevel == newTemperature) {
return true;
}
colorTemperatureLevel = newTemperature;
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
cluster_t *cluster = cluster::get(endpoint, ColorControl::Id);
attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::ColorTemperatureMireds::Id);
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
attribute::get_val(attribute, &val);
if (val.val.u16 != colorTemperatureLevel) {
val.val.u16 = colorTemperatureLevel;
attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id, &val);
}
return true;
}
uint16_t MatterEnhancedColorLight::getColorTemperature() {
return colorTemperatureLevel;
}
bool MatterEnhancedColorLight::setColorRGB(espRgbColor_t _rgbColor) {
return setColorHSV(espRgbColorToHsvColor(_rgbColor));
}
espRgbColor_t MatterEnhancedColorLight::getColorRGB() {
return espHsvColorToRgbColor(colorHSV);
}
bool MatterEnhancedColorLight::setColorHSV(espHsvColor_t _hsvColor) {
if (!started) {
log_w("Matter Enhanced ColorLight device has not begun.");
return false;
}
// avoid processing the a "no-change"
if (colorHSV.h == _hsvColor.h && colorHSV.s == _hsvColor.s && colorHSV.v == _hsvColor.v) {
return true;
}
colorHSV = {_hsvColor.h, _hsvColor.s, _hsvColor.v};
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
cluster_t *cluster = cluster::get(endpoint, ColorControl::Id);
// update hue
attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::CurrentHue::Id);
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
attribute::get_val(attribute, &val);
if (val.val.u8 != colorHSV.h) {
val.val.u8 = colorHSV.h;
attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id, &val);
}
// update saturation
attribute = attribute::get(cluster, ColorControl::Attributes::CurrentSaturation::Id);
val = esp_matter_invalid(NULL);
attribute::get_val(attribute, &val);
if (val.val.u8 != colorHSV.s) {
val.val.u8 = colorHSV.s;
attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id, &val);
}
// update value (brightness)
cluster = cluster::get(endpoint, LevelControl::Id);
attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id);
val = esp_matter_invalid(NULL);
attribute::get_val(attribute, &val);
if (val.val.u8 != colorHSV.v) {
val.val.u8 = colorHSV.v;
attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val);
}
return true;
}
espHsvColor_t MatterEnhancedColorLight::getColorHSV() {
return colorHSV;
}
MatterEnhancedColorLight::operator bool() {
return getOnOff();
}
void MatterEnhancedColorLight::operator=(bool newState) {
setOnOff(newState);
}
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

View file

@ -0,0 +1,102 @@
// Copyright 2024 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.
#pragma once
#include <sdkconfig.h>
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
#include <Matter.h>
#include <MatterEndPoint.h>
class MatterEnhancedColorLight : public MatterEndPoint {
public:
static const uint8_t MAX_BRIGHTNESS = 255;
static const uint16_t MAX_COLOR_TEMPERATURE = 500;
static const uint16_t MIN_COLOR_TEMPERATURE = 100;
MatterEnhancedColorLight();
~MatterEnhancedColorLight();
// default initial state is off, brightness = 25 (10%), HSV(21, 216, 25), color temperature is 454 (Warm White)
virtual bool begin(bool initialState = false, espHsvColor_t colorHSV = {21, 216, 25}, uint8_t newBrightness = 25, uint16_t colorTemperature = 454);
// this will just stop processing Light Matter events
void end();
bool setOnOff(bool newState); // returns true if successful
bool getOnOff(); // returns current light state
bool toggle(); // returns true if successful
bool setColorTemperature(uint16_t newTemperature); // returns true if successful
uint16_t getColorTemperature(); // returns current temperature
bool setBrightness(uint8_t newBrightness); // returns true if successful
uint8_t getBrightness(); // returns current brightness
bool setColorRGB(espRgbColor_t rgbColor); // returns true if successful
espRgbColor_t getColorRGB(); // returns current RGB Color
bool setColorHSV(espHsvColor_t hsvColor); // returns true if successful
espHsvColor_t getColorHSV(); // returns current HSV Color
// used to update the state of the light using the current Matter Light internal state
// It is necessary to set a user callback function using onChange() to handle the physical light state
void updateAccessory();
operator bool(); // returns current on/off light state
void operator=(bool state); // turns light on or off
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
// User Callback for whenever the Light On/Off state is changed by the Matter Controller
using EndPointOnOffCB = std::function<bool(bool)>;
void onChangeOnOff(EndPointOnOffCB onChangeCB) {
_onChangeOnOffCB = onChangeCB;
}
// User Callback for whenever the Light brightness value [0..255] is changed by the Matter Controller
using EndPointBrightnessCB = std::function<bool(uint8_t)>;
void onChangeBrightness(EndPointBrightnessCB onChangeCB) {
_onChangeBrightnessCB = onChangeCB;
}
// User Callback for whenever the HSV Color value is changed by the Matter Controller
using EndPointRGBColorCB = std::function<bool(espHsvColor_t)>;
void onChangeColorHSV(EndPointRGBColorCB onChangeCB) {
_onChangeColorCB = onChangeCB;
}
// User Callbqck for whenever the Light temperature value is changed by the Matter Controller
using EndPointTemperatureCB = std::function<bool(uint16_t)>;
void onChangeColorTemperature(EndPointTemperatureCB onChangeCB) {
_onChangeTemperatureCB = onChangeCB;
}
// User Callback for whenever any parameter is changed by the Matter Controller
using EndPointCB = std::function<bool(bool, espHsvColor_t, uint8_t, uint16_t)>;
void onChange(EndPointCB onChangeCB) {
_onChangeCB = onChangeCB;
}
protected:
bool started = false;
bool onOffState = false; // default initial state is off, but it can be changed by begin(bool)
uint8_t brightnessLevel = 0; // default initial brightness is 0, but it can be changed by begin(bool, uint8_t)
espHsvColor_t colorHSV = {0}; // default initial color HSV is black, but it can be changed by begin(bool, uint8_t, espHsvColor_t)
uint16_t colorTemperatureLevel = 0; // default initial color temperature is 0, but it can be changed by begin(bool, uint8_t, espHsvColor_t, uint16_t)
EndPointOnOffCB _onChangeOnOffCB = NULL;
EndPointBrightnessCB _onChangeBrightnessCB = NULL;
EndPointRGBColorCB _onChangeColorCB = NULL;
EndPointTemperatureCB _onChangeTemperatureCB = NULL;
EndPointCB _onChangeCB = NULL;
};
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */