Skip to content

Commit

Permalink
Added Color Temperature action, Enhanced Hue attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikita Solianik authored and tima-q committed Sep 26, 2022
1 parent 7189344 commit 71a3bc7
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 18 deletions.
6 changes: 6 additions & 0 deletions examples/lighting-app/lighting-common/include/ColorFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,11 @@ struct XyColor_t
uint16_t y;
};

struct CtColor_t
{
uint16_t ctMireds;
};

RgbColor_t XYToRgb(uint8_t Level, uint16_t currentX, uint16_t currentY);
RgbColor_t HsvToRgb(HsvColor_t hsv);
RgbColor_t CTToRgb(CtColor_t ct);
53 changes: 53 additions & 0 deletions examples/lighting-app/lighting-common/src/ColorFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,56 @@ RgbColor_t XYToRgb(uint8_t Level, uint16_t currentX, uint16_t currentY)

return rgb;
}

RgbColor_t CTToRgb(CtColor_t ct)
{
RgbColor_t rgb;
float r, g, b;

// Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html

// Convert Mireds to centiKelvins. k = 1,000,000/mired
float ctCentiKelvin = 10000 / ct.ctMireds;

// Red
if (ctCentiKelvin <= 66)
{
r = 255;
}
else
{
r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f);
}

// Green
if (ctCentiKelvin <= 66)
{
g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f;
}
else
{
g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f);
}

// Blue
if (ctCentiKelvin >= 66)
{
b = 255;
}
else
{
if (ctCentiKelvin <= 19)
{
b = 0;
}
else
{
b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307;
}
}
rgb.r = (uint8_t) clamp(r, 0, 255);
rgb.g = (uint8_t) clamp(g, 0, 255);
rgb.b = (uint8_t) clamp(b, 0, 255);

return rgb;
}
3 changes: 3 additions & 0 deletions examples/lighting-app/qpg/include/LightingManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class LightingManager
LEVEL_ACTION,
COLOR_ACTION_XY,
COLOR_ACTION_HSV,
COLOR_ACTION_CT,
INVALID_ACTION
} Action;

Expand All @@ -66,6 +67,7 @@ class LightingManager
XyColor_t mXY;
HsvColor_t mHSV;
RgbColor_t mRGB;
CtColor_t mCT;

LightingCallback_fn mActionInitiated_CB;
LightingCallback_fn mActionCompleted_CB;
Expand All @@ -74,6 +76,7 @@ class LightingManager
void SetLevel(uint8_t aLevel);
void SetColor(uint16_t x, uint16_t y);
void SetColor(uint8_t hue, uint8_t saturation);
void SetColorTemperature(CtColor_t ct);

void UpdateLight();

Expand Down
16 changes: 16 additions & 0 deletions examples/lighting-app/qpg/src/LightingManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint16_t
State_t new_state;
XyColor_t xy;
HsvColor_t hsv;
CtColor_t ct;

switch (aAction)
{
Expand All @@ -86,6 +87,10 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint16_t
hsv = *reinterpret_cast<HsvColor_t *>(value);
ChipLogProgress(NotSpecified, "LightMgr:COLOR: hsv:%u|%u->%u|%u", mHSV.h, mHSV.s, hsv.h, hsv.s);
break;
case COLOR_ACTION_CT:
ct.ctMireds = *reinterpret_cast<uint16_t *>(value);
ChipLogProgress(NotSpecified, "LightMgr:COLOR: ct:%u->%u", mCT.ctMireds, ct.ctMireds);
break;
default:
ChipLogProgress(NotSpecified, "LightMgr:Unknown");
break;
Expand Down Expand Up @@ -157,6 +162,10 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint16_t
{
SetColor(hsv.h, hsv.s);
}
else if (aAction == COLOR_ACTION_CT)
{
SetColorTemperature(ct);
}
else
{
Set(new_state == kState_On);
Expand Down Expand Up @@ -195,6 +204,13 @@ void LightingManager::SetColor(uint8_t hue, uint8_t saturation)
UpdateLight();
}

void LightingManager::SetColorTemperature(CtColor_t ct)
{
mCT = ct;
mRGB = CTToRgb(ct);
UpdateLight();
}

void LightingManager::Set(bool aOn)
{
if (aOn)
Expand Down
54 changes: 36 additions & 18 deletions examples/lighting-app/qpg/src/ZclCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,14 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
return;
}

if ((attributeId != ColorControl::Attributes::CurrentX::Id) && (attributeId != ColorControl::Attributes::CurrentY::Id) &&
(attributeId != ColorControl::Attributes::CurrentHue::Id) &&
(attributeId != ColorControl::Attributes::CurrentSaturation::Id))
{
ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId));
return;
}

if (size == sizeof(uint16_t))
/* XY color space */
if (attributeId == ColorControl::Attributes::CurrentX::Id || attributeId == ColorControl::Attributes::CurrentY::Id)
{
if (size != sizeof(uint16_t))
{
ChipLogError(Zcl, "Wrong length for ColorControl value: %d", size);
return;
}
XyColor_t xy;
if (attributeId == ColorControl::Attributes::CurrentX::Id)
{
Expand All @@ -90,20 +88,37 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
EmberAfStatus status = ColorControl::Attributes::CurrentX::Get(endpoint, &xy.x);
assert(status == EMBER_ZCL_STATUS_SUCCESS);
}

ChipLogProgress(Zcl, "New XY color: %u|%u", xy.x, xy.y);
LightingMgr().InitiateAction(LightingManager::COLOR_ACTION_XY, 0, sizeof(xy), (uint8_t *) &xy);
}
else if (size == sizeof(uint8_t))
/* HSV color space */
else if (attributeId == ColorControl::Attributes::CurrentHue::Id ||
attributeId == ColorControl::Attributes::CurrentSaturation::Id ||
attributeId == ColorControl::Attributes::EnhancedCurrentHue::Id)
{
if (size != sizeof(uint8_t))
{
ChipLogError(Zcl, "Wrong length for ColorControl value: %d", size);
return;
}
HsvColor_t hsv;
if (attributeId == ColorControl::Attributes::CurrentHue::Id)
if (attributeId == ColorControl::Attributes::EnhancedCurrentHue::Id)
{
// We only support 8-bit hue. Assuming hue is linear, normalize 16-bit to 8-bit.
hsv.h = (uint8_t)((*reinterpret_cast<uint16_t *>(value)) >> 8);
// get saturation from cluster value storage
EmberAfStatus status = ColorControl::Attributes::CurrentSaturation::Get(endpoint, &hsv.s);
assert(status == EMBER_ZCL_STATUS_SUCCESS);
}
else if (attributeId == ColorControl::Attributes::CurrentHue::Id)
{
hsv.h = *value;
// get saturation from cluster value storage
EmberAfStatus status = ColorControl::Attributes::CurrentSaturation::Get(endpoint, &hsv.s);
assert(status == EMBER_ZCL_STATUS_SUCCESS);
}
if (attributeId == ColorControl::Attributes::CurrentSaturation::Id)
else if (attributeId == ColorControl::Attributes::CurrentSaturation::Id)
{
hsv.s = *value;
// get hue from cluster value storage
Expand All @@ -113,16 +128,19 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
ChipLogProgress(Zcl, "New HSV color: %u|%u", hsv.h, hsv.s);
LightingMgr().InitiateAction(LightingManager::COLOR_ACTION_HSV, 0, sizeof(hsv), (uint8_t *) &hsv);
}
else if (attributeId == ColorControl::Attributes::ColorTemperatureMireds::Id)
{
CtColor_t ct;
ct.ctMireds = *reinterpret_cast<uint16_t *>(value);
ChipLogProgress(Zcl, "New CT color: %u", ct.ctMireds);
LightingMgr().InitiateAction(LightingManager::COLOR_ACTION_CT, 0, sizeof(ct), (uint8_t *) &ct.ctMireds);
}
else
{
ChipLogError(Zcl, "Wrong length for ColorControl value: %d", size);
ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId));
return;
}
}
else
{
ChipLogProgress(Zcl, "Unknown cluster ID: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
return;
}
}

/** @brief OnOff Cluster Init
Expand Down

0 comments on commit 71a3bc7

Please sign in to comment.