Skip to content

Commit 6cbdbec

Browse files
authored
feat(matter): adds matter extended color light code file
1 parent 157d0a0 commit 6cbdbec

File tree

1 file changed

+384
-0
lines changed

1 file changed

+384
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <sdkconfig.h>
16+
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
17+
18+
#include <Matter.h>
19+
#include <app/server/Server.h>
20+
#include <MatterEndpoints/MatterEnhancedColorLight.h>
21+
22+
using namespace esp_matter;
23+
using namespace esp_matter::endpoint;
24+
using namespace chip::app::Clusters;
25+
26+
// endpoint for enhanced color light device
27+
namespace esp_matter {
28+
using namespace cluster;
29+
namespace endpoint {
30+
namespace enhanced_color_light {
31+
typedef struct config {
32+
cluster::descriptor::config_t descriptor;
33+
cluster::identify::config_t identify;
34+
cluster::groups::config_t groups;
35+
cluster::scenes_management::config_t scenes_management;
36+
cluster::on_off::config_t on_off;
37+
cluster::level_control::config_t level_control;
38+
cluster::color_control::config_t color_control;
39+
} config_t;
40+
41+
uint32_t get_device_type_id() {
42+
return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID;
43+
}
44+
45+
uint8_t get_device_type_version() {
46+
return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_VERSION;
47+
}
48+
49+
esp_err_t add(endpoint_t *endpoint, config_t *config) {
50+
if (!endpoint) {
51+
log_e("Endpoint cannot be NULL");
52+
return ESP_ERR_INVALID_ARG;
53+
}
54+
esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version());
55+
if (err != ESP_OK) {
56+
log_e("Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err);
57+
return err;
58+
}
59+
60+
descriptor::create(endpoint, &(config->descriptor), CLUSTER_FLAG_SERVER);
61+
cluster_t *identify_cluster = identify::create(endpoint, &(config->identify), CLUSTER_FLAG_SERVER);
62+
identify::command::create_trigger_effect(identify_cluster);
63+
groups::create(endpoint, &(config->groups), CLUSTER_FLAG_SERVER);
64+
cluster_t *scenes_cluster = scenes_management::create(endpoint, &(config->scenes_management), CLUSTER_FLAG_SERVER);
65+
scenes_management::command::create_copy_scene(scenes_cluster);
66+
scenes_management::command::create_copy_scene_response(scenes_cluster);
67+
68+
on_off::create(endpoint, &(config->on_off), CLUSTER_FLAG_SERVER, on_off::feature::lighting::get_id());
69+
level_control::create(endpoint, &(config->level_control), CLUSTER_FLAG_SERVER,
70+
level_control::feature::on_off::get_id() | level_control::feature::lighting::get_id());
71+
color_control::create(endpoint, &(config->color_control), CLUSTER_FLAG_SERVER,
72+
color_control::feature::hue_saturation::get_id() | color_control::feature::color_temperature::get_id());
73+
return ESP_OK;
74+
}
75+
76+
endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) {
77+
endpoint_t *endpoint = endpoint::create(node, flags, priv_data);
78+
add(endpoint, config);
79+
return endpoint;
80+
}
81+
} /* enhanced_color_light */
82+
} /* endpoint */
83+
} /* esp_matter */
84+
85+
86+
bool MatterEnhancedColorLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) {
87+
bool ret = true;
88+
if (!started) {
89+
log_e("Matter Enhanced ColorLight device has not begun.");
90+
return false;
91+
}
92+
93+
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);
94+
95+
if (endpoint_id == getEndPointId()) {
96+
switch (cluster_id) {
97+
case OnOff::Id:
98+
if (attribute_id == OnOff::Attributes::OnOff::Id) {
99+
log_d("Enhanced ColorLight On/Off State changed to %d", val->val.b);
100+
if (_onChangeOnOffCB != NULL) {
101+
ret &= _onChangeOnOffCB(val->val.b);
102+
}
103+
if (_onChangeCB != NULL) {
104+
ret &= _onChangeCB(val->val.b, colorHSV, brightnessLevel, colorTemperatureLevel);
105+
}
106+
if (ret == true) {
107+
onOffState = val->val.b;
108+
}
109+
}
110+
break;
111+
case LevelControl::Id:
112+
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
113+
log_d("Enhanced ColorLight Brightness changed to %d", val->val.u8);
114+
if (_onChangeBrightnessCB != NULL) {
115+
ret &= _onChangeBrightnessCB(val->val.u8);
116+
}
117+
if (_onChangeCB != NULL) {
118+
ret &= _onChangeCB(onOffState, colorHSV, val->val.u8, colorTemperatureLevel);
119+
}
120+
if (ret == true) {
121+
colorHSV.v = val->val.u8;
122+
}
123+
}
124+
break;
125+
case ColorControl::Id:
126+
{
127+
if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) {
128+
log_d("Enhanced ColorLight Temperature changed to %d", val->val.u16);
129+
if (_onChangeTemperatureCB != NULL) {
130+
ret &= _onChangeTemperatureCB(val->val.u16);
131+
}
132+
if (_onChangeCB != NULL) {
133+
ret &= _onChangeCB(onOffState, colorHSV, brightnessLevel, val->val.u16);
134+
}
135+
if (ret == true) {
136+
colorTemperatureLevel = val->val.u16;
137+
}
138+
break;
139+
}
140+
if (attribute_id != ColorControl::Attributes::CurrentHue::Id && attribute_id != ColorControl::Attributes::CurrentSaturation::Id) {
141+
log_i("Color Control Attribute ID [%x] not processed.", attribute_id);
142+
break;
143+
}
144+
espHsvColor_t hsvColor = {colorHSV.h, colorHSV.s, colorHSV.v};
145+
if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
146+
log_d("Enhanced ColorLight Hue changed to %d", val->val.u8);
147+
hsvColor.h = val->val.u8;
148+
} else { // attribute_id == ColorControl::Attributes::CurrentSaturation::Id)
149+
log_d("Enhanced ColorLight Saturation changed to %d", val->val.u8);
150+
hsvColor.s = val->val.u8;
151+
}
152+
if (_onChangeColorCB != NULL) {
153+
ret &= _onChangeColorCB(hsvColor);
154+
}
155+
if (_onChangeCB != NULL) {
156+
ret &= _onChangeCB(onOffState, hsvColor, brightnessLevel, colorTemperatureLevel);
157+
}
158+
if (ret == true) {
159+
colorHSV = {hsvColor.h, hsvColor.s, hsvColor.v};
160+
}
161+
break;
162+
}
163+
}
164+
}
165+
return ret;
166+
}
167+
168+
MatterEnhancedColorLight::MatterEnhancedColorLight() {}
169+
170+
MatterEnhancedColorLight::~MatterEnhancedColorLight() {
171+
end();
172+
}
173+
174+
bool MatterEnhancedColorLight::begin(bool initialState, espHsvColor_t _colorHSV, uint8_t brightness, uint16_t ColorTemperature) {
175+
ArduinoMatter::_init();
176+
enhanced_color_light::config_t light_config;
177+
178+
light_config.on_off.on_off = initialState;
179+
light_config.on_off.lighting.start_up_on_off = nullptr;
180+
onOffState = initialState;
181+
182+
light_config.level_control.current_level = brightness;
183+
light_config.level_control.lighting.start_up_current_level = nullptr;
184+
185+
light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;
186+
light_config.color_control.color_temperature.color_temperature_mireds = ColorTemperature;
187+
light_config.color_control.color_temperature.startup_color_temperature_mireds = nullptr;
188+
colorTemperatureLevel = ColorTemperature;
189+
190+
light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation;
191+
light_config.color_control.hue_saturation.current_hue = _colorHSV.h;
192+
light_config.color_control.hue_saturation.current_saturation = _colorHSV.s;
193+
colorHSV = {_colorHSV.h, _colorHSV.s, _colorHSV.v};
194+
195+
// endpoint handles can be used to add/modify clusters.
196+
endpoint_t *endpoint = enhanced_color_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this);
197+
if (endpoint == nullptr) {
198+
log_e("Failed to create Enhanced ColorLight endpoint");
199+
return false;
200+
}
201+
202+
setEndPointId(endpoint::get_id(endpoint));
203+
log_i("Enhanced ColorLight created with endpoint_id %d", getEndPointId());
204+
205+
/* Mark deferred persistence for some attributes that might be changed rapidly */
206+
cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id);
207+
attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id);
208+
attribute::set_deferred_persistence(current_level_attribute);
209+
210+
started = true;
211+
return true;
212+
}
213+
214+
void MatterEnhancedColorLight::end() {
215+
started = false;
216+
}
217+
218+
bool MatterEnhancedColorLight::setOnOff(bool newState) {
219+
if (!started) {
220+
log_e("Matter Enhanced ColorLight device has not begun.");
221+
return false;
222+
}
223+
224+
// avoid processing the a "no-change"
225+
if (onOffState == newState) {
226+
return true;
227+
}
228+
229+
onOffState = newState;
230+
231+
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
232+
cluster_t *cluster = cluster::get(endpoint, OnOff::Id);
233+
attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id);
234+
235+
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
236+
attribute::get_val(attribute, &val);
237+
238+
if (val.val.b != onOffState) {
239+
val.val.b = onOffState;
240+
attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val);
241+
}
242+
return true;
243+
}
244+
245+
void MatterEnhancedColorLight::updateAccessory() {
246+
if (_onChangeCB != NULL) {
247+
_onChangeCB(onOffState, colorHSV, brightnessLevel, colorTemperatureLevel);
248+
}
249+
}
250+
251+
bool MatterEnhancedColorLight::getOnOff() {
252+
return onOffState;
253+
}
254+
255+
bool MatterEnhancedColorLight::toggle() {
256+
return setOnOff(!onOffState);
257+
}
258+
259+
bool MatterEnhancedColorLight::setBrightness(uint8_t newBrightness) {
260+
if (!started) {
261+
log_w("Matter Enhanced ColorLight device has not begun.");
262+
return false;
263+
}
264+
265+
// avoid processing the a "no-change"
266+
if (brightnessLevel == newBrightness) {
267+
return true;
268+
}
269+
270+
brightnessLevel = newBrightness;
271+
272+
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
273+
cluster_t *cluster = cluster::get(endpoint, LevelControl::Id);
274+
attribute_t *attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id);
275+
276+
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
277+
attribute::get_val(attribute, &val);
278+
279+
if (val.val.u8 != brightnessLevel) {
280+
val.val.u8 = brightnessLevel;
281+
attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val);
282+
}
283+
return true;
284+
}
285+
286+
uint8_t MatterEnhancedColorLight::getBrightness() {
287+
return brightnessLevel;
288+
}
289+
290+
bool MatterEnhancedColorLight::setColorTemperature(uint16_t newTemperature) {
291+
if (!started) {
292+
log_w("Matter Enhanced ColorLight device has not begun.");
293+
return false;
294+
}
295+
296+
// avoid processing the a "no-change"
297+
if (colorTemperatureLevel == newTemperature) {
298+
return true;
299+
}
300+
301+
colorTemperatureLevel = newTemperature;
302+
303+
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
304+
cluster_t *cluster = cluster::get(endpoint, ColorControl::Id);
305+
attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::ColorTemperatureMireds::Id);
306+
307+
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
308+
attribute::get_val(attribute, &val);
309+
310+
if (val.val.u16 != colorTemperatureLevel) {
311+
val.val.u16 = colorTemperatureLevel;
312+
attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id, &val);
313+
}
314+
return true;
315+
}
316+
317+
uint16_t MatterEnhancedColorLight::getColorTemperature() {
318+
return colorTemperatureLevel;
319+
}
320+
321+
bool MatterEnhancedColorLight::setColorRGB(espRgbColor_t _rgbColor) {
322+
return setColorHSV(espRgbColorToHsvColor(_rgbColor));
323+
}
324+
325+
espRgbColor_t MatterEnhancedColorLight::getColorRGB() {
326+
return espHsvColorToRgbColor(colorHSV);
327+
}
328+
329+
bool MatterEnhancedColorLight::setColorHSV(espHsvColor_t _hsvColor) {
330+
331+
if (!started) {
332+
log_w("Matter Enhanced ColorLight device has not begun.");
333+
return false;
334+
}
335+
336+
// avoid processing the a "no-change"
337+
if (colorHSV.h == _hsvColor.h && colorHSV.s == _hsvColor.s && colorHSV.v == _hsvColor.v) {
338+
return true;
339+
}
340+
341+
colorHSV = { _hsvColor.h, _hsvColor.s, _hsvColor.v };
342+
343+
endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
344+
cluster_t *cluster = cluster::get(endpoint, ColorControl::Id);
345+
// update hue
346+
attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::CurrentHue::Id);
347+
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
348+
attribute::get_val(attribute, &val);
349+
if (val.val.u8 != colorHSV.h) {
350+
val.val.u8 = colorHSV.h;
351+
attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id, &val);
352+
}
353+
// update saturation
354+
attribute = attribute::get(cluster, ColorControl::Attributes::CurrentSaturation::Id);
355+
val = esp_matter_invalid(NULL);
356+
attribute::get_val(attribute, &val);
357+
if (val.val.u8 != colorHSV.s) {
358+
val.val.u8 = colorHSV.s;
359+
attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id, &val);
360+
}
361+
// update value (brightness)
362+
cluster = cluster::get(endpoint, LevelControl::Id);
363+
attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id);
364+
val = esp_matter_invalid(NULL);
365+
attribute::get_val(attribute, &val);
366+
if (val.val.u8 != colorHSV.v) {
367+
val.val.u8 = colorHSV.v;
368+
attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val);
369+
}
370+
return true;
371+
}
372+
373+
espHsvColor_t MatterEnhancedColorLight::getColorHSV() {
374+
return colorHSV;
375+
}
376+
377+
MatterEnhancedColorLight::operator bool() {
378+
return getOnOff();
379+
}
380+
381+
void MatterEnhancedColorLight::operator=(bool newState) {
382+
setOnOff(newState);
383+
}
384+
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

0 commit comments

Comments
 (0)