Skip to content

Commit 414e4f3

Browse files
authored
feat(Matter): add new MatterColorLight endpoint (espressif#10654)
* feat(matter): adds Matter Color Light endpoint
1 parent 0f3191e commit 414e4f3

15 files changed

+978
-282
lines changed

CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ endif()
2525
set(CORE_SRCS
2626
cores/esp32/base64.cpp
2727
cores/esp32/cbuf.cpp
28+
cores/esp32/ColorFormat.c
2829
cores/esp32/chip-debug-report.cpp
2930
cores/esp32/esp32-hal-adc.c
3031
cores/esp32/esp32-hal-bt.c
@@ -170,7 +171,7 @@ set(ARDUINO_LIBRARY_Matter_SRCS
170171
libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp
171172
libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp
172173
libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp
173-
libraries/Matter/src/MatterUtil/ColorFormat.cpp
174+
libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
174175
libraries/Matter/src/Matter.cpp)
175176

176177
set(ARDUINO_LIBRARY_PPP_SRCS

cores/esp32/ColorFormat.c

+279
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/*
2+
*
3+
* Copyright (c) 2021 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include "ColorFormat.h"
20+
21+
#include <math.h>
22+
23+
// define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards
24+
#define clamp(a, min, max) ((a) < (min) ? (min) : ((a) > (max) ? (max) : (a)))
25+
26+
const espHsvColor_t HSV_BLACK = {0, 0, 0};
27+
const espHsvColor_t HSV_WHITE = {0, 0, 254};
28+
const espHsvColor_t HSV_RED = {0, 254, 254};
29+
const espHsvColor_t HSV_YELLOW = {42, 254, 254};
30+
const espHsvColor_t HSV_GREEN = {84, 254, 254};
31+
const espHsvColor_t HSV_CYAN = {127, 254, 254};
32+
const espHsvColor_t HSV_BLUE = {169, 254, 254};
33+
const espHsvColor_t HSV_MAGENTA = {211, 254, 254};
34+
35+
const espRgbColor_t RGB_BLACK = {0, 0, 0};
36+
const espRgbColor_t RGB_WHITE = {255, 255, 255};
37+
const espRgbColor_t RGB_RED = {255, 0, 0};
38+
const espRgbColor_t RGB_YELLOW = {255, 255, 0};
39+
const espRgbColor_t RGB_GREEN = {0, 255, 0};
40+
const espRgbColor_t RGB_CYAN = {0, 255, 255};
41+
const espRgbColor_t RGB_BLUE = {0, 0, 255};
42+
const espRgbColor_t RGB_MAGENTA = {255, 0, 255};
43+
44+
// main color temperature values
45+
const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE = {142};
46+
const espCtColor_t DAYLIGHT_WHITE_COLOR_TEMPERATURE = {181};
47+
const espCtColor_t WHITE_COLOR_TEMPERATURE = {250};
48+
const espCtColor_t SOFT_WHITE_COLOR_TEMPERATURE = {370};
49+
const espCtColor_t WARM_WHITE_COLOR_TEMPERATURE = {454};
50+
51+
espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v) {
52+
espHsvColor_t hsv = {h, s, v};
53+
return espHsvColorToRgbColor(hsv);
54+
}
55+
56+
espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv) {
57+
espRgbColor_t rgb;
58+
59+
uint8_t region, p, q, t;
60+
uint32_t h, s, v, remainder;
61+
62+
if (hsv.s == 0) {
63+
rgb.r = rgb.g = rgb.b = hsv.v;
64+
} else {
65+
h = hsv.h;
66+
s = hsv.s;
67+
v = hsv.v;
68+
69+
region = h / 43;
70+
remainder = (h - (region * 43)) * 6;
71+
p = (v * (255 - s)) >> 8;
72+
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
73+
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
74+
switch (region) {
75+
case 0: rgb.r = v, rgb.g = t, rgb.b = p; break;
76+
case 1: rgb.r = q, rgb.g = v, rgb.b = p; break;
77+
case 2: rgb.r = p, rgb.g = v, rgb.b = t; break;
78+
case 3: rgb.r = p, rgb.g = q, rgb.b = v; break;
79+
case 4: rgb.r = t, rgb.g = p, rgb.b = v; break;
80+
case 5:
81+
default: rgb.r = v, rgb.g = p, rgb.b = q; break;
82+
}
83+
}
84+
return rgb;
85+
}
86+
87+
espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b) {
88+
espRgbColor_t rgb = {r, g, b};
89+
return espRgbColorToHsvColor(rgb);
90+
}
91+
92+
espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb) {
93+
espHsvColor_t hsv;
94+
uint8_t rgbMin, rgbMax;
95+
96+
rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
97+
rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
98+
99+
hsv.v = rgbMax;
100+
if (hsv.v == 0) {
101+
hsv.h = 0;
102+
hsv.s = 0;
103+
return hsv;
104+
}
105+
106+
hsv.s = 255 * (rgbMax - rgbMin) / hsv.v;
107+
if (hsv.s == 0) {
108+
hsv.h = 0;
109+
return hsv;
110+
}
111+
if (rgbMax == rgb.r) {
112+
hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
113+
} else if (rgbMax == rgb.g) {
114+
hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
115+
} else {
116+
hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);
117+
}
118+
return hsv;
119+
}
120+
121+
espRgbColor_t espXYColorToRgbColor(uint8_t Level, espXyColor_t xy) {
122+
return espXYToRgbColor(Level, xy.x, xy.y);
123+
}
124+
125+
espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y) {
126+
// convert xyY color space to RGB
127+
128+
// https://www.easyrgb.com/en/math.php
129+
// https://en.wikipedia.org/wiki/SRGB
130+
// refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
131+
132+
// The current_X/current_Y attribute contains the current value of the normalized chromaticity value of x/y.
133+
// The value of x/y shall be related to the current_X/current_Y attribute by the relationship
134+
// x = current_X/65536
135+
// y = current_Y/65536
136+
// z = 1-x-y
137+
138+
espRgbColor_t rgb;
139+
140+
float x, y, z;
141+
float X, Y, Z;
142+
float r, g, b;
143+
144+
x = ((float)current_X) / 65535.0f;
145+
y = ((float)current_Y) / 65535.0f;
146+
147+
z = 1.0f - x - y;
148+
149+
// Calculate XYZ values
150+
151+
// Y - given brightness in 0 - 1 range
152+
Y = ((float)Level) / 254.0f;
153+
X = (Y / y) * x;
154+
Z = (Y / y) * z;
155+
156+
// X, Y and Z input refer to a D65/2° standard illuminant.
157+
// sR, sG and sB (standard RGB) output range = 0 ÷ 255
158+
// convert XYZ to RGB - CIE XYZ to sRGB
159+
X = X / 100.0f;
160+
Y = Y / 100.0f;
161+
Z = Z / 100.0f;
162+
163+
r = (X * 3.2406f) - (Y * 1.5372f) - (Z * 0.4986f);
164+
g = -(X * 0.9689f) + (Y * 1.8758f) + (Z * 0.0415f);
165+
b = (X * 0.0557f) - (Y * 0.2040f) + (Z * 1.0570f);
166+
167+
// apply gamma 2.2 correction
168+
r = (r <= 0.0031308f ? 12.92f * r : (1.055f) * pow(r, (1.0f / 2.4f)) - 0.055f);
169+
g = (g <= 0.0031308f ? 12.92f * g : (1.055f) * pow(g, (1.0f / 2.4f)) - 0.055f);
170+
b = (b <= 0.0031308f ? 12.92f * b : (1.055f) * pow(b, (1.0f / 2.4f)) - 0.055f);
171+
172+
// Round off
173+
r = clamp(r, 0, 1);
174+
g = clamp(g, 0, 1);
175+
b = clamp(b, 0, 1);
176+
177+
// these rgb values are in the range of 0 to 1, convert to limit of HW specific LED
178+
rgb.r = (uint8_t)(r * 255);
179+
rgb.g = (uint8_t)(g * 255);
180+
rgb.b = (uint8_t)(b * 255);
181+
182+
return rgb;
183+
}
184+
185+
espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b) {
186+
espRgbColor_t rgb = {r, g, b};
187+
return espRgbColorToXYColor(rgb);
188+
}
189+
190+
espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb) {
191+
// convert RGB to xy color space
192+
193+
// https://www.easyrgb.com/en/math.php
194+
// https://en.wikipedia.org/wiki/SRGB
195+
// refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
196+
197+
espXyColor_t xy;
198+
199+
float r, g, b;
200+
float X, Y, Z;
201+
float x, y;
202+
203+
r = ((float)rgb.r) / 255.0f;
204+
g = ((float)rgb.g) / 255.0f;
205+
b = ((float)rgb.b) / 255.0f;
206+
207+
// convert RGB to XYZ - sRGB to CIE XYZ
208+
r = (r <= 0.04045f ? r / 12.92f : pow((r + 0.055f) / 1.055f, 2.4f));
209+
g = (g <= 0.04045f ? g / 12.92f : pow((g + 0.055f) / 1.055f, 2.4f));
210+
b = (b <= 0.04045f ? b / 12.92f : pow((b + 0.055f) / 1.055f, 2.4f));
211+
212+
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
213+
X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
214+
Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
215+
Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f;
216+
217+
// sR, sG and sB (standard RGB) input range = 0 ÷ 255
218+
// X, Y and Z output refer to a D65/2° standard illuminant.
219+
X = r * 0.4124564f + g * 0.3575761f + b * 0.1804375f;
220+
Y = r * 0.2126729f + g * 0.7151522f + b * 0.0721750f;
221+
Z = r * 0.0193339f + g * 0.1191920f + b * 0.9503041f;
222+
223+
// Calculate xy values
224+
x = X / (X + Y + Z);
225+
y = Y / (X + Y + Z);
226+
227+
// convert to 0-65535 range
228+
xy.x = (uint16_t)(x * 65535);
229+
xy.y = (uint16_t)(y * 65535);
230+
return xy;
231+
}
232+
233+
espRgbColor_t espCTToRgbColor(uint16_t ct) {
234+
espCtColor_t ctColor = {ct};
235+
return espCTColorToRgbColor(ctColor);
236+
}
237+
238+
espRgbColor_t espCTColorToRgbColor(espCtColor_t ct) {
239+
espRgbColor_t rgb = {0, 0, 0};
240+
float r, g, b;
241+
242+
if (ct.ctMireds == 0) {
243+
return rgb;
244+
}
245+
// Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
246+
247+
// Convert Mireds to centiKelvins. k = 1,000,000/mired
248+
float ctCentiKelvin = 10000 / ct.ctMireds;
249+
250+
// Red
251+
if (ctCentiKelvin <= 66) {
252+
r = 255;
253+
} else {
254+
r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f);
255+
}
256+
257+
// Green
258+
if (ctCentiKelvin <= 66) {
259+
g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f;
260+
} else {
261+
g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f);
262+
}
263+
264+
// Blue
265+
if (ctCentiKelvin >= 66) {
266+
b = 255;
267+
} else {
268+
if (ctCentiKelvin <= 19) {
269+
b = 0;
270+
} else {
271+
b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307;
272+
}
273+
}
274+
rgb.r = (uint8_t)clamp(r, 0, 255);
275+
rgb.g = (uint8_t)clamp(g, 0, 255);
276+
rgb.b = (uint8_t)clamp(b, 0, 255);
277+
278+
return rgb;
279+
}

cores/esp32/ColorFormat.h

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
*
3+
* Copyright (c) 2021 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
#include <stdint.h>
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
struct RgbColor_t {
27+
uint8_t r;
28+
uint8_t g;
29+
uint8_t b;
30+
};
31+
32+
struct HsvColor_t {
33+
uint16_t h;
34+
uint8_t s;
35+
uint8_t v;
36+
};
37+
38+
struct XyColor_t {
39+
uint16_t x;
40+
uint16_t y;
41+
};
42+
43+
struct CtColor_t {
44+
uint16_t ctMireds;
45+
};
46+
47+
typedef struct RgbColor_t espRgbColor_t;
48+
typedef struct HsvColor_t espHsvColor_t;
49+
typedef struct XyColor_t espXyColor_t;
50+
typedef struct CtColor_t espCtColor_t;
51+
52+
espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y);
53+
espRgbColor_t espXYColorToRgb(uint8_t Level, espXyColor_t xy);
54+
espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb);
55+
espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b);
56+
espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv);
57+
espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v);
58+
espRgbColor_t espCTColorToRgbColor(espCtColor_t ct);
59+
espRgbColor_t espCTToRgbColor(uint16_t ct);
60+
espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb);
61+
espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b);
62+
63+
extern const espHsvColor_t HSV_BLACK, HSV_WHITE, HSV_RED, HSV_YELLOW, HSV_GREEN, HSV_CYAN, HSV_BLUE, HSV_MAGENTA;
64+
extern const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE, DAYLIGHT_WHITE_COLOR_TEMPERATURE, WHITE_COLOR_TEMPERATURE, SOFT_WHITE_COLOR_TEMPERATURE,
65+
WARM_WHITE_COLOR_TEMPERATURE;
66+
extern const espRgbColor_t RGB_BLACK, RGB_WHITE, RGB_RED, RGB_YELLOW, RGB_GREEN, RGB_CYAN, RGB_BLUE, RGB_MAGENTA;
67+
68+
#ifdef __cplusplus
69+
}
70+
#endif

0 commit comments

Comments
 (0)