Skip to content

Commit 3055069

Browse files
tima-qNikita Solianik
authored andcommitted
Added Color Temperature action, Enhanced Hue attribute (#22870)
Co-authored-by: Nikita Solianik <nikita.solianik@qorvo.com>
1 parent 2f5db3c commit 3055069

File tree

5 files changed

+114
-18
lines changed

5 files changed

+114
-18
lines changed

examples/lighting-app/lighting-common/include/ColorFormat.h

+6
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,11 @@ struct XyColor_t
4040
uint16_t y;
4141
};
4242

43+
struct CtColor_t
44+
{
45+
uint16_t ctMireds;
46+
};
47+
4348
RgbColor_t XYToRgb(uint8_t Level, uint16_t currentX, uint16_t currentY);
4449
RgbColor_t HsvToRgb(HsvColor_t hsv);
50+
RgbColor_t CTToRgb(CtColor_t ct);

examples/lighting-app/lighting-common/src/ColorFormat.cpp

+53
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,56 @@ RgbColor_t XYToRgb(uint8_t Level, uint16_t currentX, uint16_t currentY)
130130

131131
return rgb;
132132
}
133+
134+
RgbColor_t CTToRgb(CtColor_t ct)
135+
{
136+
RgbColor_t rgb;
137+
float r, g, b;
138+
139+
// Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
140+
141+
// Convert Mireds to centiKelvins. k = 1,000,000/mired
142+
float ctCentiKelvin = 10000 / ct.ctMireds;
143+
144+
// Red
145+
if (ctCentiKelvin <= 66)
146+
{
147+
r = 255;
148+
}
149+
else
150+
{
151+
r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f);
152+
}
153+
154+
// Green
155+
if (ctCentiKelvin <= 66)
156+
{
157+
g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f;
158+
}
159+
else
160+
{
161+
g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f);
162+
}
163+
164+
// Blue
165+
if (ctCentiKelvin >= 66)
166+
{
167+
b = 255;
168+
}
169+
else
170+
{
171+
if (ctCentiKelvin <= 19)
172+
{
173+
b = 0;
174+
}
175+
else
176+
{
177+
b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307;
178+
}
179+
}
180+
rgb.r = (uint8_t) clamp(r, 0, 255);
181+
rgb.g = (uint8_t) clamp(g, 0, 255);
182+
rgb.b = (uint8_t) clamp(b, 0, 255);
183+
184+
return rgb;
185+
}

examples/lighting-app/qpg/include/LightingManager.h

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class LightingManager
4141
LEVEL_ACTION,
4242
COLOR_ACTION_XY,
4343
COLOR_ACTION_HSV,
44+
COLOR_ACTION_CT,
4445
INVALID_ACTION
4546
} Action;
4647

@@ -66,6 +67,7 @@ class LightingManager
6667
XyColor_t mXY;
6768
HsvColor_t mHSV;
6869
RgbColor_t mRGB;
70+
CtColor_t mCT;
6971

7072
LightingCallback_fn mActionInitiated_CB;
7173
LightingCallback_fn mActionCompleted_CB;
@@ -74,6 +76,7 @@ class LightingManager
7476
void SetLevel(uint8_t aLevel);
7577
void SetColor(uint16_t x, uint16_t y);
7678
void SetColor(uint8_t hue, uint8_t saturation);
79+
void SetColorTemperature(CtColor_t ct);
7780

7881
void UpdateLight();
7982

examples/lighting-app/qpg/src/LightingManager.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint16_t
6666
State_t new_state;
6767
XyColor_t xy;
6868
HsvColor_t hsv;
69+
CtColor_t ct;
6970

7071
switch (aAction)
7172
{
@@ -86,6 +87,10 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint16_t
8687
hsv = *reinterpret_cast<HsvColor_t *>(value);
8788
ChipLogProgress(NotSpecified, "LightMgr:COLOR: hsv:%u|%u->%u|%u", mHSV.h, mHSV.s, hsv.h, hsv.s);
8889
break;
90+
case COLOR_ACTION_CT:
91+
ct.ctMireds = *reinterpret_cast<uint16_t *>(value);
92+
ChipLogProgress(NotSpecified, "LightMgr:COLOR: ct:%u->%u", mCT.ctMireds, ct.ctMireds);
93+
break;
8994
default:
9095
ChipLogProgress(NotSpecified, "LightMgr:Unknown");
9196
break;
@@ -157,6 +162,10 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint16_t
157162
{
158163
SetColor(hsv.h, hsv.s);
159164
}
165+
else if (aAction == COLOR_ACTION_CT)
166+
{
167+
SetColorTemperature(ct);
168+
}
160169
else
161170
{
162171
Set(new_state == kState_On);
@@ -195,6 +204,13 @@ void LightingManager::SetColor(uint8_t hue, uint8_t saturation)
195204
UpdateLight();
196205
}
197206

207+
void LightingManager::SetColorTemperature(CtColor_t ct)
208+
{
209+
mCT = ct;
210+
mRGB = CTToRgb(ct);
211+
UpdateLight();
212+
}
213+
198214
void LightingManager::Set(bool aOn)
199215
{
200216
if (aOn)

examples/lighting-app/qpg/src/ZclCallbacks.cpp

+36-18
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,14 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
6565
return;
6666
}
6767

68-
if ((attributeId != ColorControl::Attributes::CurrentX::Id) && (attributeId != ColorControl::Attributes::CurrentY::Id) &&
69-
(attributeId != ColorControl::Attributes::CurrentHue::Id) &&
70-
(attributeId != ColorControl::Attributes::CurrentSaturation::Id))
71-
{
72-
ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId));
73-
return;
74-
}
75-
76-
if (size == sizeof(uint16_t))
68+
/* XY color space */
69+
if (attributeId == ColorControl::Attributes::CurrentX::Id || attributeId == ColorControl::Attributes::CurrentY::Id)
7770
{
71+
if (size != sizeof(uint16_t))
72+
{
73+
ChipLogError(Zcl, "Wrong length for ColorControl value: %d", size);
74+
return;
75+
}
7876
XyColor_t xy;
7977
if (attributeId == ColorControl::Attributes::CurrentX::Id)
8078
{
@@ -90,20 +88,37 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
9088
EmberAfStatus status = ColorControl::Attributes::CurrentX::Get(endpoint, &xy.x);
9189
assert(status == EMBER_ZCL_STATUS_SUCCESS);
9290
}
91+
9392
ChipLogProgress(Zcl, "New XY color: %u|%u", xy.x, xy.y);
9493
LightingMgr().InitiateAction(LightingManager::COLOR_ACTION_XY, 0, sizeof(xy), (uint8_t *) &xy);
9594
}
96-
else if (size == sizeof(uint8_t))
95+
/* HSV color space */
96+
else if (attributeId == ColorControl::Attributes::CurrentHue::Id ||
97+
attributeId == ColorControl::Attributes::CurrentSaturation::Id ||
98+
attributeId == ColorControl::Attributes::EnhancedCurrentHue::Id)
9799
{
100+
if (size != sizeof(uint8_t))
101+
{
102+
ChipLogError(Zcl, "Wrong length for ColorControl value: %d", size);
103+
return;
104+
}
98105
HsvColor_t hsv;
99-
if (attributeId == ColorControl::Attributes::CurrentHue::Id)
106+
if (attributeId == ColorControl::Attributes::EnhancedCurrentHue::Id)
107+
{
108+
// We only support 8-bit hue. Assuming hue is linear, normalize 16-bit to 8-bit.
109+
hsv.h = (uint8_t)((*reinterpret_cast<uint16_t *>(value)) >> 8);
110+
// get saturation from cluster value storage
111+
EmberAfStatus status = ColorControl::Attributes::CurrentSaturation::Get(endpoint, &hsv.s);
112+
assert(status == EMBER_ZCL_STATUS_SUCCESS);
113+
}
114+
else if (attributeId == ColorControl::Attributes::CurrentHue::Id)
100115
{
101116
hsv.h = *value;
102117
// get saturation from cluster value storage
103118
EmberAfStatus status = ColorControl::Attributes::CurrentSaturation::Get(endpoint, &hsv.s);
104119
assert(status == EMBER_ZCL_STATUS_SUCCESS);
105120
}
106-
if (attributeId == ColorControl::Attributes::CurrentSaturation::Id)
121+
else if (attributeId == ColorControl::Attributes::CurrentSaturation::Id)
107122
{
108123
hsv.s = *value;
109124
// get hue from cluster value storage
@@ -113,16 +128,19 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
113128
ChipLogProgress(Zcl, "New HSV color: %u|%u", hsv.h, hsv.s);
114129
LightingMgr().InitiateAction(LightingManager::COLOR_ACTION_HSV, 0, sizeof(hsv), (uint8_t *) &hsv);
115130
}
131+
else if (attributeId == ColorControl::Attributes::ColorTemperatureMireds::Id)
132+
{
133+
CtColor_t ct;
134+
ct.ctMireds = *reinterpret_cast<uint16_t *>(value);
135+
ChipLogProgress(Zcl, "New CT color: %u", ct.ctMireds);
136+
LightingMgr().InitiateAction(LightingManager::COLOR_ACTION_CT, 0, sizeof(ct), (uint8_t *) &ct.ctMireds);
137+
}
116138
else
117139
{
118-
ChipLogError(Zcl, "Wrong length for ColorControl value: %d", size);
140+
ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId));
141+
return;
119142
}
120143
}
121-
else
122-
{
123-
ChipLogProgress(Zcl, "Unknown cluster ID: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
124-
return;
125-
}
126144
}
127145

128146
/** @brief OnOff Cluster Init

0 commit comments

Comments
 (0)