Posts: 10
Threads: 2
Joined: Jan 2018
Reputation:
0
Hello everyone,
I am trying to read the color status of a Philips RGB lamp with the Zigbee gateway.
Looking at the link: https://kb.logicmachine.net/libraries/zigbee/
I have been able to get the On/Off status, color temperature, but I am not able to read the RGB status.I don't understand that about xy and then being able to convert it to 3 bytes to use it on KNX screens.
Can anybody help me?
Thank you so much in advance,
Posts: 7729
Threads: 42
Joined: Jun 2015
Reputation:
446
Posts: 111
Threads: 14
Joined: Nov 2019
Reputation:
6
Code: RGB = event.getvalue()
 Norm of RGB values
R = bit.rshift(bit.band(RGB, 0xFF0000), 16)
G = bit.rshift(bit.band(RGB, 0x00FF00), 8)
B = bit.band(RGB, 0x0000FF)
Red = R / 255
Green = G / 255
Blue = B / 255
 Gamma correction
if Red > 0.04045 then
Red = ((Red + 0.055) / (1 + 0.055))^2.4
else
Red = Red / 12.92
end
if Green > 0.04045 then
Green = ((Green + 0.055) / (1 + 0.055))^2.4
else
Green = Green / 12.92
end
if Blue > 0.04045 then
Blue = ((Blue + 0.055) / (1 + 0.055))^2.4
else
Blue = Red / 12.92
end
 Coversion RGB > XY
X = Red * 0.649926 + Green * 0.103455 + Blue * 0.197109
Y = Red * 0.234327 + Green * 0.743075 + Blue * 0.022598
Z = Green * 0.053077 + Blue * 1.035763
x = X / (X+Y+Z)
y = Y / (X+Y+Z)
 Coversion XY > CCT
n = (x  0.3320) / (0.1858  y)
cct = math.floor((449 * ((x  0.332) / (y  0.1858))^3) + (3525 * ((x  0.332) / (y  0.1858))^2)  (6823.3 * ((x  0.332) / (y  0.1858))) + (5520.33))
log(cct)
Posts: 26
Threads: 2
Joined: Aug 2024
Reputation:
0
23.09.2024, 13:51
(This post was last modified: 23.09.2024, 13:52 by stianj.)
(21.03.2024, 09:13)admin Wrote: Try using xy_to_rgb from user.hue v2.lua: https://forum.logicmachine.net/showthrea...50#pid6250
I'm trying to use xy_to_rgb from user.hue v2.lua. But I can't be doing it right. I have copied the function into common functions. Then I have in the event script:
Code: xy = zb.cmdsync('getxy', addr)
rgb = xy_to_rgb(xy['x'],xy['y'])
log(rgb)
But I get the excact same rgb value wether I have red or blue light. (255,0,0) or (0,0,255) gives the same rgb value. But the lamp is red or blue correctly. For colours without blue the result makes sense I think, but it seems like blue and red is mixed up somehow.
Value of variable rgb is 16711680 for both (255,0,0) and (0,0,255)...
I can see that the x and y values differ (45913,19614) for red and (8880,2613) for blue  so the result shouldn't be equal...
Any hints?
Posts: 26
Threads: 2
Joined: Aug 2024
Reputation:
0
Well, looking more into this I now understand that the xy coordinates should be less than 1  and that's the main problem. Don't know where these numbers come from, or what I can do with them... Help!
Posts: 7729
Threads: 42
Joined: Jun 2015
Reputation:
446
Use this conversion function:
Code: function xytorgb(x, y, level)
local function revgamma(v)
if v <= 0.0031308 then
return v * 12.92
else
return (1 + 0.055) * math.pow(v, (1 / 2.4))  0.055
end
end
local function clampconvert(v, max)
v = math.max(0, v * 255 / max)
v = math.min(255, v)
return math.round(v)
end
local x = x / 0xFFFE
local y = y / 0xFFFE
local z = 1  x  y
local Y = math.min(254, level) / 254
local X = (Y / y) * x
local Z = (Y / y) * z
local r = revgamma(3.2404542 * X  1.5371385 * Y  0.4985314 * Z)
local g = revgamma(0.9692660 * X + 1.8760108 * Y + 0.0415560 * Z)
local b = revgamma(0.0556434 * X  0.2040259 * Y + 1.0572252 * Z)
local max = math.max(r, g, b)
r = clampconvert(r, max)
g = clampconvert(g, max)
b = clampconvert(b, max)
return r * 0x10000 + g * 0x100 + b
end
x = 45913
y = 19614
level = 254
rgb = xytorgb(x, y, level)
log(rgb)
You also need to pass the light level (0..254) for the conversion to work.
Posts: 26
Threads: 2
Joined: Aug 2024
Reputation:
0
Thank you so much! This works nicely!
Can I ask why getxy() returns not xy?
But I think I have uncovered a bug in the Mosaic RGBW dimmer (6 byte DALI) widget. It seems it expects 0255 values, but according to this:
https://support.knx.org/hc/enus/article...2631105682
(and my Gira devices...) the 6 byte DPT 251.600 should have 0100 as value for the different colours. Unlike 232.600 which is 0255... Yay for consistency from KNX...
Unless I'm mistaken (which I very much could be...) it would be awesome if this could be fixed in the next FW release
Posts: 7729
Threads: 42
Joined: Jun 2015
Reputation:
446
The actual range is 0..255 which is treated as 0..100%. Notice the resolution is ~0.4% (100/255).
Posts: 26
Threads: 2
Joined: Aug 2024
Reputation:
0
25.09.2024, 07:31
(This post was last modified: 25.09.2024, 07:41 by stianj.)
Might be... But Gira sends (and expects) 0100. But that might be their bug, I don't have anything else to compare with.
(But why is the DPT 232.600 showing expected value to be 0255, while DPT 251.600 shows 0100 in the specifications?)
Seems atleast a MDT Dali controller does the same: https://community.openhab.org/t/rgbwcol...600/150055
Posts: 26
Threads: 2
Joined: Aug 2024
Reputation:
0
I still think I'm right about the 6 bit DALI RGBW DPT...
But anyways, your xytorgb() works very good. I have not been comparing input and output, because that doesn't really matter, but I just noticed that for different green colours, I usually get the same feedback anyways...
rgb(0 149 48) gives me x=11049, y=44152
rgb(0 255 0) gives me x=11299, y=48940
But running both these coordinates through xytorgb() gives me 0,255,0 as feedback...
As I wrote, I understand that it's impossible to match input and feedback 100%, but I feel this should have been better..?
What do you think?
Posts: 4583
Threads: 24
Joined: Aug 2017
Reputation:
206
MDT is brand labeling this from IPAS and they have new firmware which is fixing this bug. Check if MDT already released latest version.
Same works correct on SE (also IPAS branded) version.

Ctrl+F5
Posts: 7729
Threads: 42
Joined: Jun 2015
Reputation:
446
Try this updated conversion function:
Code: function xytorgb(x, y, level)
local function revgamma(v)
if v <= 0.0031308 then
return v * 12.92
else
return (1 + 0.055) * math.pow(v, (1 / 2.4))  0.055
end
end
local function round(v)
if v <= 0 then
return 0
else
return math.round(v * level)
end
end
x = x / 0xFFFE
y = y / 0xFFFE
local z = 1.0  x  y
local Y = level
local X = (Y / y) * x
local Z = (Y / y) * z
local r = X * 1.656492  Y * 0.354851  Z * 0.255038
local g = X * 0.707196 + Y * 1.655397 + Z * 0.036152
local b = X * 0.051713  Y * 0.121364 + Z * 1.01153
if r > b and r > g and r > 1 then
g = g / r
b = b / r
r = 1
elseif g > b and g > r and g > 1 then
r = r / g
b = b / g
g = 1
elseif b > r and b > g and b > 1 then
r = r / b
g = g / b
b = 1
end
r = round(revgamma(r))
g = round(revgamma(g))
b = round(revgamma(b))
return r * 0x10000 + g * 0x100 + b
end
Posts: 26
Threads: 2
Joined: Aug 2024
Reputation:
0
22.10.2024, 16:20
(This post was last modified: 22.10.2024, 18:53 by stianj.)
This one is perfect, thank you so much!
I didn't notice that I had getlevel before setrgb, so things didn't really make sense. But eventually I saw my mistake and now it's 100%!
Thank you!
