So I have got an RGBW Light and I don't know how I could perfectly represent this in HomeKit:
I have 3 incoming nodes:
On: true/false')Brightness, Hue, Saturation.Take a look at this openhab comment
It is the "original" function that I used as a building block for most of my other functions. It's not perfect - but it's for a HSV (hue, saturation, value/brightness) so it could be helpful here. Plus it's openhab!
You may want to modify the function to have separate outputs - one for the hue and saturation - the other for the brightness.
About RGBW.
Please read this .
It's about converting rgb to rgbw.
Okay thanks!
This looks great! I will try to implement this in JavaScript and if it works, I will share that node here...
Untested but could get you thinking:
This should create a function with 3 outputs. The first will be sending 1 or 0 to your openhab switch. The second will be sending a hue and saturation to your color channel, and the third output should send a white number to your white channel in openhab.

var h = context.get('h')||0;
var s = context.get('s')||0;
var b = context.get('b')||0;
var onoff={}; //create on/off message
var huesat={}; //create hue/saturation message
var bright={}; //create brightness message
onoff.payload=1; //assume onoff default on
if(msg.payload.On === false){
onoff.payload=0; //set onoff to off
return [onoff,null,null]; //send 0 to onoff output
}
if(msg.payload.Hue){
h = msg.payload.Hue;
context.set('h',h)
}
if(msg.payload.Saturation){
s = msg.payload.Saturation;
context.set('s',s)
}
if(msg.payload.Brightness){
b = msg.payload.Brightness;
context.set('b',b)
}
huesat.payload=h+","s;
bright.payload=b;
if (msg.hap.context !== undefined )
{
return [onoff,huesat,bright];
}
Thanks I’ll try it. But I also have to send a brightness to the color channel as well.
Regarding rgbw try this code:
let Ri = 254;
let Gi = 0;
let Bi = 80;
if (Ri === 0) {
Ri = 1;
}
if (Gi === 0) {
Gi = 1;
}
if (Bi === 0) {
Bi = 1;
}
let M = Math.max(Ri,Gi,Bi);
let m = Math.min(Ri,Gi,Bi);
let Wo = m / M < 0.5 ? m * M / (M - m) : M;
let Q = 255;
let K = (Wo + M) / m;
let Ro = Math.floor( [ ( K * Ri ) - Wo ] / Q );
let Go = Math.floor( [ ( K * Gi ) - Wo ] / Q );
let Bo = Math.floor( [ ( K * Bi ) - Wo ] / Q );
console.log("Input RGB: [" + Ri + "," + Gi + "," + Bi + "]");
console.log("Output RGBW: [" + Ro + "," + Go + "," + Bo + "," + Wo+ "]");
Output is:
Input RGB: [254,1,80]
Output RGBW: [254,0,79,1.0039525691699605]
Ah sure no problem.
change this line:
huesat.payload=h+","s;
to:
huesat.payload=h+","+s+","+b;
@radokristof - are the values that openhab color channel sends/needs HSV or RGB?
HSB
This looks really complicated to implement. I get the color as a HSB and the seperate White in percent (0-100). I need to convert HSB to RGB (and in parralel the percentage to 0-255 value) then add this White to the RGB (need to recalculate all of them) to get RGBW and then back to HSB.
I couldn't find a method to calculate this from HSB right away...
@radokristof I will look how to change HSB to RGB.
By the way look at #29
Maybe we should add all Characteristic values on node output?
Not in payload but in other object (msg.characteristics?)
yes, it would be great. It doesn't really matter if it is in the payload or in an other object, because I have to process everything manually. But it would be better, if we seperate which values are really changed, and which are just sent back...
Changed values would be send in msg.payload.
Current values would be sent in msg.WE_NEED_SOME_NAME_FOR_THAT
msg.values
msg.attributes
something like this I suppose
About rgbw to hsb look here
Thanks. But the problem is that I also have to “insert” the white channel into these. These are just purely converting colors from one space to another.
Something like this?
HSB -> RGB -> Add white channel so it will be RGBW -> HSB
Here we go. First you need plugin called color-convert
Code below sort of represent what you need.
Its your input (hsv or hsb it doesnt matter I thing)
const Hi = 304;
const Si = 24;
const Vi = 67;
I did test it for some values:
hsv input [ 304, 24, 67 ]
rgb [ 171, 130, 168 ]
rgbw [ 41, 0, 38, 130 ]
rgb [ 171, 130, 168 ]
hsv output [ 304, 24, 67 ]
I am not sure how much data we lose on rgbw > rgb > hsv
var convert = require('color-convert');
let rgbRgbw = function(Ri, Gi, Bi) {
//Get the maximum between R, G, and B
let tM = Math.max(Ri, Math.min(Gi, Bi));
//If the maximum value is 0, immediately return pure black.
if(tM == 0)
return [0,0,0,0];
//This section serves to figure out what the color with 100% hue is
var multiplier = 255 / tM;
var hR = Ri * multiplier;
var hG = Gi * multiplier;
var hB = Bi * multiplier;
//This calculates the Whiteness (not strictly speaking Luminance) of the color
var M = Math.max(hR, Math.max(hG, hB));
var m = Math.min(hR, Math.min(hG, hB));
var Luminance = ((M + m) / 2 - 127.5) * (255.0/127.5) / multiplier;
//Calculate the output values
var Wo = Luminance;
var Bo = Bi - Luminance;
var Ro = Ri - Luminance;
var Go = Gi - Luminance;
//Trim them so that they are all between 0 and 255
if (Wo < 0) Wo = 0;
if (Bo < 0) Bo = 0;
if (Ro < 0) Ro = 0;
if (Go < 0) Go = 0;
if (Wo > 255) Wo = 255;
if (Bo > 255) Bo = 255;
if (Ro > 255) Ro = 255;
if (Go > 255) Go = 255;
return [Ro, Go, Bo, Wo];
}
let rgbwRgb = function(Ri, Gi, Bi, Wi) {
//I am pretty sure we lost some data here... But how much?
const Ro = (Ri + Wi);
const Go = (Gi + Wi);
const Bo = (Bi + Wi);
return [Ro, Go, Bo];
}
const Hi = 304;
const Si = 24;
const Vi = 67;
const hsv = [Hi, Si, Vi];
console.log(hsv);
const hsvToRgb = convert.hsv.rgb(Hi, Si, Vi);
console.log(hsvToRgb);
const rgbToRgbw = rgbRgbw(hsvToRgb[0], hsvToRgb[1], hsvToRgb[2]);
console.log(rgbToRgbw);
const rgbwToRgb = rgbwRgb(rgbToRgbw[0], rgbToRgbw[1], rgbToRgbw[2], rgbToRgbw[3]);
console.log(rgbwToRgb);
const rgbToHsv = convert.rgb.hsv(rgbwToRgb[0], rgbwToRgb[1], rgbwToRgb[2]);
console.log(rgbToHsv);
Thanks. This is something similar I have tried. But I still don’t know how to inject the white (this also just convert from one to another. When you convert it to rgb I have to inject the white channel - or just have the rgb and add the channel to it a fourth parameter?).
This code snippet should work in Node-RED? Can I include external libraries right in the function node?
Sorry I don't have much experience with Node-RED and Javascript...
Actually I am not sure. You should try it and see :)
If not working then we will think how to solve it.
Wiadomość napisana przez Kristof Rado notifications@github.com w dniu 08.03.2019, o godz. 19:26:
This code snippet should work in Node-RED? Can I include external libraries right in the function node?
Sorry I don't have much experience with Node-RED and Javascript...—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
Thanks for your help :) I think I have to seperate them, because one function node can only run one function. But this might work...
Ok, so I had to download a different node which supports npm libraries.
I have created my nodes, there is a few, but I don't know which part of it makes Node-RED really slow, and for example now, it can't even start....
I found node for color conversion - HERE
Install it and add function for RGB <> RGBW
This is cool! Thank you very much. I will try this out later this week
How the things are going?
I'm working on it, but this still looks not an easy job... I don't really know much about color spaces.
[{"id":"795ba8b9.c81338","type":"function","z":"5b421c97.903ae4","name":"Translate for HomeKit","func":"var input = msg.payload;\n\nvar h = input[0];\nvar s = input[1];\nvar b = input[2];\n\nflow.set(\"TopLEDKitchenHue\", h);\nflow.set(\"TopLEDKitchenSat\", s);\nflow.set(\"TopLEDKitchenBright\", b);\n\nmsg.payload = {\n \"hue\": h,\n \"saturation\": s,\n \"brightness\": b\n};\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":300,"wires":[["cc7a358d.7d59f8"]]},{"id":"cc7a358d.7d59f8","type":"color-convert","z":"5b421c97.903ae4","input":"hsl","output":"rgb","outputType":"array","x":490,"y":300,"wires":[["c36f61d7.1025e"]]},{"id":"adc44f57.08f82","type":"openhab-v2-in","z":"5b421c97.903ae4","name":"","controller":"427d851b.f7e23c","item":"wifiled2_color","ohCompatibleTimestamp":false,"eventTypes":["ItemStateChangedEvent"],"outputAtStartup":true,"storeStateInFlow":false,"x":90,"y":260,"wires":[["795ba8b9.c81338"],[]]},{"id":"c36f61d7.1025e","type":"function","z":"5b421c97.903ae4","name":"Converting","func":"var input = msg.payload;\n\nvar r = input[0];\nvar g = input[1];\nvar b = input[2];\n\nflow.set(\"TopLEDKitchenRed\", r);\nflow.set(\"TopLEDKitchenGreen\", g);\nflow.set(\"TopLEDKitchenBlue\", b);\n\nmsg.payload = {\n \"Red\": r,\n \"Green\": g,\n \"Blue\": b\n};\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":240,"wires":[["d9436198.82cd2"]]},{"id":"d9436198.82cd2","type":"function","z":"5b421c97.903ae4","name":"Converting and combining","func":"var r;\nvar g;\nvar b;\nvar w;\n\nif(msg.payload.White) {\n w = msg.payload.White;\n}\nelse {\n w = flow.get(\"TopLEDKitchenWhite\");\n}\nif(msg.payload.Red || msg.payload.Green || msg.payload.Blue) {\n r = msg.payload.Red;\n g = msg.payload.Green;\n b = msg.payload.Blue;\n}\nelse {\n r = flow.get(\"TopLEDKitchenRed\");\n g = flow.get(\"TopLEDKitchenGreen\");\n b = flow.get(\"TopLEDKitchenBlue\");\n}\n\nvar Ro = r + w;\nvar Go = g + w;\nvar Bo = b + w;\n\nif(Ro < 0) {\n Ro = 0;\n}\nif(Ro > 255) {\n Ro = 255;\n}\n\nif(Go < 0) {\n Go = 0;\n}\nif(Go > 255) {\n Go = 255;\n}\n\nif(Go < 0) {\n Go = 0;\n}\nif(Go > 255) {\n Go = 255;\n}\n\nmsg.payload = {\n \"red\": Ro,\n \"green\": Go,\n \"blue\": Bo\n};\nreturn msg;","outputs":1,"noerr":0,"x":570,"y":220,"wires":[["38c4c414.feca0c"]]},{"id":"38c4c414.feca0c","type":"color-convert","z":"5b421c97.903ae4","input":"rgb","output":"hsv","outputType":"array","x":770,"y":240,"wires":[["d221c88f.057828"]]},{"id":"d221c88f.057828","type":"function","z":"5b421c97.903ae4","name":"Translate for HomeKit","func":"var input = msg.payload;\nmsg.payload = {\n \"Hue\": input[0],\n \"Saturation\": input[1],\n \"Brightness\": input[2],\n};\nreturn msg;","outputs":1,"noerr":0,"x":680,"y":160,"wires":[["1b717000.fbd3b"]]},{"id":"8f75139f.9678c","type":"function","z":"5b421c97.903ae4","name":"White to color","func":"var input = msg.payload;\n\nvar output = (input / 100) * 255;\n\nflow.set(\"TopLEDKitchenWhite\", output);\nmsg.payload = {\n \"White\": output\n};\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":180,"wires":[["d9436198.82cd2"]]},{"id":"7b615245.ae9f0c","type":"openhab-v2-in","z":"5b421c97.903ae4","name":"","controller":"427d851b.f7e23c","item":"wifiled2_white","ohCompatibleTimestamp":false,"eventTypes":["ItemStateChangedEvent"],"outputAtStartup":true,"storeStateInFlow":false,"x":130,"y":180,"wires":[["8f75139f.9678c"],[]]},{"id":"e9164915.e3c6e8","type":"openhab-v2-in","z":"5b421c97.903ae4","name":"","controller":"427d851b.f7e23c","item":"wifiled2_power","ohCompatibleTimestamp":false,"eventTypes":["ItemStateChangedEvent"],"outputAtStartup":true,"storeStateInFlow":false,"x":140,"y":120,"wires":[["73acd4c0.c35c8c"],[]]},{"id":"73acd4c0.c35c8c","type":"function","z":"5b421c97.903ae4","name":"openHab to HomeKit","func":"if(msg.payload == \"ON\") {\n msg.payload = {\n \"On\" : true\n };\n}\nelse {\n msg.payload = {\n \"On\" : false\n };\n}\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":120,"wires":[["1b717000.fbd3b"]]},{"id":"1b717000.fbd3b","type":"homekit-service","z":"5b421c97.903ae4","bridge":"db6c4c1.9b703b","name":"Felső LED","serviceName":"Lightbulb","topic":"","manufacturer":"MagicHome","model":"WifiLED","serialNo":"111","characteristicProperties":"{\n \"Brightness\" : true,\n \"Hue\" : true,\n \"Saturation\" : true\n}","x":710,"y":100,"wires":[["5536716a.e1e5f","4d7fdb28.baab14"]]},{"id":"4d7fdb28.baab14","type":"function","z":"5b421c97.903ae4","name":"Translate for convert","func":"if(msg.hap.context !== undefined) {\n var h;\n var s;\n var b;\n \n if(msg.payload.Hue) {\n h = msg.payload.Hue;\n }\n else {\n h = flow.get(\"TopLEDKitchenHue\");\n }\n \n if(msg.payload.Saturation) {\n s = msg.payload.Saturation;\n }\n else {\n s = flow.get(\"TopLEDKitchenSat\");\n }\n \n if(msg.payload.Brightness) {\n b = msg.payload.Brightness;\n }\n else {\n b = flow.get(\"TopLEDKitchenBright\");\n }\n \n msg.payload = {\n \"hue\": h,\n \"saturation\": s,\n \"brightness\": b\n };\n return msg;\n}\n","outputs":1,"noerr":0,"x":1060,"y":280,"wires":[["43b56266.83655c"]]},{"id":"5536716a.e1e5f","type":"function","z":"5b421c97.903ae4","name":"HomeKit to openHab","func":"if(msg.hap.context !== undefined) {\n if(msg.payload.hasOwnProperty(\"On\")) {\n if(msg.payload.On === true) {\n msg.payload = \"ON\";\n }\n else {\n msg.payload = \"OFF\";\n }\n return msg;\n }\n}","outputs":1,"noerr":0,"x":1080,"y":120,"wires":[["aa632592.3ab648"]]},{"id":"aa632592.3ab648","type":"openhab-v2-out","z":"5b421c97.903ae4","name":"","controller":"427d851b.f7e23c","item":"wifiled2_power","topic":"ItemCommand","topicType":"oh_cmd","payload":"payload","payloadType":"msg","storeStateInFlow":false,"x":1300,"y":120,"wires":[]},{"id":"43b56266.83655c","type":"color-convert","z":"5b421c97.903ae4","input":"hsv","output":"rgb","outputType":"array","x":1270,"y":280,"wires":[["defc8643.b3e518"]]},{"id":"defc8643.b3e518","type":"function","z":"5b421c97.903ae4","name":"RGB to RGBW","func":"var input = msg.payload;\n\nvar r = input[0];\nvar g = input[1];\nvar b = input[2];\n\nvar rOut;\nvar gOut;\nvar bOut;\nvar wOut;\n\nvar tM = Math.max(r, Math.max(g, b));\n\n// Black\nif(tM === 0) {\n rOut = 0;\n gOut = 0;\n bOut = 0;\n wOut = 0;\n}\n\nvar multiplier = 255.0 / tM;\nvar hR = r * multiplier;\nvar hG = g * multiplier;\nvar hB = b * multiplier;\n\nvar M = Math.max(hR, Math.max(hG, hB));\nvar m = Math.min(hR, Math.min(hG, hB));\nvar luminance = ((M + m) / 2.0 - 127.5) * (255.0 / 127.5) / multiplier;\n\nwOut = Math.round(luminance);\nrOut = Math.round(r - luminance);\ngOut = Math.round(g - luminance);\nbOut = Math.round(b - luminance);\n\nmsg.payload = {\n \"Red\": rOut,\n \"Green\": gOut,\n \"Blue\": bOut,\n \"White\": wOut\n};\n\nreturn msg;","outputs":1,"noerr":0,"x":1480,"y":280,"wires":[["26e038c.47f87c8","f1e5ba2.53cc848"]]},{"id":"f1e5ba2.53cc848","type":"function","z":"5b421c97.903ae4","name":"Color to convert","func":"var r = msg.payload.Red;\nvar g = msg.payload.Green;\nvar b = msg.payload.Blue;\n\nmsg.payload = {\n \"red\": r,\n \"green\": g,\n \"blue\": b\n};\nreturn msg;","outputs":1,"noerr":0,"x":1520,"y":200,"wires":[["d4bf7629.25c848"]]},{"id":"26e038c.47f87c8","type":"function","z":"5b421c97.903ae4","name":"Color to White","func":"var input;\nif(msg.payload.White) {\n input = msg.payload.White;\n}\n\nvar output = (255 / input ) * 100;\n\nreturn output;","outputs":1,"noerr":0,"x":1640,"y":360,"wires":[["4a4eaaf4.7794a4"]]},{"id":"4a4eaaf4.7794a4","type":"openhab-v2-out","z":"5b421c97.903ae4","name":"","controller":"427d851b.f7e23c","item":"wifiled2_white","topic":"ItemCommand","topicType":"oh_cmd","payload":"payload","payloadType":"msg","storeStateInFlow":false,"x":1780,"y":280,"wires":[]},{"id":"b36a16ce.7577a8","type":"openhab-v2-out","z":"5b421c97.903ae4","name":"","controller":"427d851b.f7e23c","item":"wifiled2_color","topic":"ItemCommand","topicType":"oh_cmd","payload":"payload","payloadType":"msg","storeStateInFlow":false,"x":1880,"y":200,"wires":[]},{"id":"d4bf7629.25c848","type":"color-convert","z":"5b421c97.903ae4","input":"rgb","output":"hsv","outputType":"array","x":1670,"y":140,"wires":[["b36a16ce.7577a8"]]},{"id":"427d851b.f7e23c","type":"openhab-v2-controller","z":"","name":"openhab2","protocol":"http","host":"localhost","port":"8080","path":"","username":"","password":"","allowRawEvents":true},{"id":"db6c4c1.9b703b","type":"homekit-bridge","z":"","bridgeName":"openHAB - RED","pinCode":"111-22-333","port":"","manufacturer":"Node-RED","model":"v2.0","serialNo":"Default Serial Number"}]
This is where I am. I don't think you can simplify this... maybe I will leave out the White channel and just send the RGB...
Well issue is complicated. I know a little about color spaces but not enough to handle rgbw <> hsv
However now I have started over from a scratch (I got confused about why I did some parts...) and tried to set it up just as a RGB light and leave out the white channel now. However this is not working properly for me as well...
@crxporter Did you ever tried controlling an RGB light from HomeKit?
@radokristof I have not - but I will try it tonight. I have an mqtt rgb light strip that I always just use as white, I'll throw together an RGB light in homekit to try it out then share my results here.
Thanks. I used flow.set, flow.get to 'persist' the values - because as you know HomeKit only sends the changed values on the output, but I don't know why it didn't work properly. - For example if I change the Brightness with the slider (which should change the Brightness value in HSB) somehow crashes Node-RED and restarts :)
I think I got it.
You'll need to have installed the color convert node as noted above.
This flow will take RGB input (replace at the "simulate" function) in the form of msg.payload=[r,g,b] and output to the final debug node in the form of msg.payload=[r,g,b].
The magic happens in the color convert nodes and in the function nodes. All values are persisted using the flow.set. This example works right in homekit - meaning homekit shows the correct colors and brightnesses based on what the simulator function is sending.
Take a look!
Flow code:
[{"id":"6c90892b.b229a","type":"inject","z":"8ab94716.868738","name":"","topic":"","payload":"Red","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":1020,"wires":[["faed9f12.16cd1"]]},{"id":"faed9f12.16cd1","type":"function","z":"8ab94716.868738","name":"Simulate","func":"if(msg.payload == \"Off\"){\n return[{\"payload\":[0,0,0]}]\n}\nif(msg.payload == \"Red\"){\n return[{\"payload\":[255,0,0]}]\n}\nif(msg.payload == \"Green\"){\n return[{\"payload\":[0,255,0]}]\n}\nif(msg.payload == \"Blue\"){\n return[{\"payload\":[0,0,255]}]\n}\nif(msg.payload == \"White\"){\n return[{\"payload\":[255,255,255]}]\n}\n","outputs":1,"noerr":0,"x":240,"y":1040,"wires":[["df96d518.9356e8"]]},{"id":"df96d518.9356e8","type":"color-convert","z":"8ab94716.868738","input":"rgb","output":"hsv","outputType":"array","x":390,"y":1040,"wires":[["e9ba32f3.ba157"]]},{"id":"76ba113d.5f2f78","type":"inject","z":"8ab94716.868738","name":"Off","topic":"","payload":"Off","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":980,"wires":[["faed9f12.16cd1"]]},{"id":"3d806d56.009ff2","type":"inject","z":"8ab94716.868738","name":"","topic":"","payload":"Green","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":1060,"wires":[["faed9f12.16cd1"]]},{"id":"7226341b.12915c","type":"inject","z":"8ab94716.868738","name":"","topic":"","payload":"Blue","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":1100,"wires":[["faed9f12.16cd1"]]},{"id":"448b762c.ea0d08","type":"inject","z":"8ab94716.868738","name":"","topic":"","payload":"White","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":1140,"wires":[["faed9f12.16cd1"]]},{"id":"e9ba32f3.ba157","type":"function","z":"8ab94716.868738","name":"Input","func":"var outmsg={};\nvar Hue = flow.get('Hue')||0;\nvar Saturation = flow.get('Saturation')||0;\nvar Brightness = flow.get('Brightness')||100;\n\nif(msg.payload[0]===0 && msg.payload[1]===0 && msg.payload[2]===0){\n outmsg.payload={\"On\":false};\n} else{\n Hue = msg.payload[0];\n flow.set('Hue',Hue);\n Saturation = msg.payload[1];\n flow.set('Saturation',Saturation);\n Brightness = msg.payload[2];\n flow.set('Brightness',Brightness);\n outmsg.payload={\n \"On\":true,\n \"Hue\":Hue,\n \"Saturation\":Saturation,\n \"Brightness\":Brightness\n }\n}\nreturn [outmsg];\n","outputs":1,"noerr":0,"x":550,"y":1040,"wires":[["42123222.b7e504"]]},{"id":"42123222.b7e504","type":"homekit-service","z":"8ab94716.868738","isParent":true,"bridge":"63a21f39.7ace9","parentService":"","name":"HSV light","serviceName":"Lightbulb","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n \"Brightness\":true,\n \"Hue\":true,\n \"Saturation\":true\n}","x":700,"y":1040,"wires":[["3d71759d.d3f53a","8c376820.c4396"]]},{"id":"3d71759d.d3f53a","type":"function","z":"8ab94716.868738","name":"Output","func":"var Hue = flow.get('Hue')||0;\nvar Saturation = flow.get('Saturation')||0;\nvar Brightness = flow.get('Brightness')||100;\n\nif(msg.payload.Hue){\n Hue = msg.payload.Hue;\n flow.set('Hue',Hue);\n}\nif(msg.payload.Saturation){\n Saturation = msg.payload.Saturation;\n flow.set('Saturation',Saturation);\n}\nif(msg.payload.Brightness){\n Brightness = msg.payload.Brightness;\n flow.set('Brightness',Brightness);\n}\nif (msg.hap.context !== undefined) {\n if(msg.payload.On === true){\n return [{\"payload\":[Hue,Saturation,Brightness]}]\n }\n if(msg.payload.On === false){\n return [{\"payload\":[0,0,0]}]\n }\n else{\n return [{\"payload\":[Hue,Saturation,Brightness]}]\n }\n}","outputs":1,"noerr":0,"x":870,"y":1040,"wires":[["378a5cc2.a2fb14"]]},{"id":"8c376820.c4396","type":"debug","z":"8ab94716.868738","name":"HomeKit output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":900,"y":1100,"wires":[]},{"id":"378a5cc2.a2fb14","type":"color-convert","z":"8ab94716.868738","input":"hsv","output":"rgb","outputType":"array","x":1030,"y":1040,"wires":[["a2de29b9.6cf5a8"]]},{"id":"a2de29b9.6cf5a8","type":"debug","z":"8ab94716.868738","name":"RGB output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1210,"y":1040,"wires":[]},{"id":"63a21f39.7ace9","type":"homekit-bridge","z":"","bridgeName":"Dev2","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true}]
@radokristof did you see this example? Did it get you any closer?
Now in wiki page
Wow I got sucked in tonight. Here we go.
I've made a flow that will:
1-take input in the form of [red,green,blue,white]
2-convert it to RGB
3-convert to HSV
4-send to homekit
5-receive from homekit
6-convert to rgb
7-convert to original form of [red,green,blue,white]
@radokristof are your lights RGBW? I saw in one of your functions that your inputs may actually be HSV plus a white. This seems odd to me, what hardware device are you using here?
I modified the functions provide up above by @Shaquu to work inside the function nodes. He comments that there may be some data loss, I tested with several examples and the colors might not be EXACT between the conversions but any RGB or RGBW I sent through the system came out exactly the same on the other side.

[{"id":"5c0e039.596defc","type":"function","z":"8ab94716.868738","name":"RGB to RGBW","func":"var Ri = msg.payload[0];\nvar Gi = msg.payload[1];\nvar Bi = msg.payload[2];\n\n //Get the maximum between R, G, and B\n let tM = Math.max(Ri, Math.max(Gi, Bi));\n\n //If the maximum value is 0, immediately return pure black.\n if(tM === 0)\n return [{\"payload\":[0,0,0,0]}];\n\n //This section serves to figure out what the color with 100% hue is\n var multiplier = 255 / tM;\n var hR = Ri * multiplier;\n var hG = Gi * multiplier;\n var hB = Bi * multiplier; \n\n //This calculates the Whiteness (not strictly speaking Luminance) of the color\n var M = Math.max(hR, Math.max(hG, hB));\n var m = Math.min(hR, Math.min(hG, hB));\n var Luminance = ((M + m) / 2 - 127.5) * (255.0/127.5) / multiplier;\n\n //Calculate the output values\n var Wo = Luminance;\n var Bo = Bi - Luminance;\n var Ro = Ri - Luminance;\n var Go = Gi - Luminance;\n\n //Trim them so that they are all between 0 and 255\n if (Wo < 0) Wo = 0;\n if (Bo < 0) Bo = 0;\n if (Ro < 0) Ro = 0;\n if (Go < 0) Go = 0;\n if (Wo > 255) Wo = 255;\n if (Bo > 255) Bo = 255;\n if (Ro > 255) Ro = 255;\n if (Go > 255) Go = 255;\n return [{\"payload\":[Ro, Go, Bo, Wo]}];\n","outputs":1,"noerr":0,"x":1400,"y":1640,"wires":[[]]},{"id":"511fa668.6280a","type":"color-convert","z":"8ab94716.868738","input":"hsv","output":"rgb","outputType":"array","x":1210,"y":1640,"wires":[["5c0e039.596defc"]]},{"id":"4bcb69da.54835","type":"function","z":"8ab94716.868738","name":"Output","func":"var Hue = flow.get('Hue')||0;\nvar Saturation = flow.get('Saturation')||0;\nvar Brightness = flow.get('Brightness')||100;\n\nif(msg.payload.Hue){\n Hue = msg.payload.Hue;\n flow.set('Hue',Hue);\n}\nif(msg.payload.Saturation){\n Saturation = msg.payload.Saturation;\n flow.set('Saturation',Saturation);\n}\nif(msg.payload.Brightness){\n Brightness = msg.payload.Brightness;\n flow.set('Brightness',Brightness);\n}\nif (msg.hap.context !== undefined) {\n if(msg.payload.On === true){\n return [{\"payload\":[Hue,Saturation,Brightness]}]\n }\n if(msg.payload.On === false){\n return [{\"payload\":[0,0,0]}]\n }\n else{\n return [{\"payload\":[Hue,Saturation,Brightness]}]\n }\n}","outputs":1,"noerr":0,"x":1050,"y":1640,"wires":[["511fa668.6280a"]]},{"id":"42123222.b7e504","type":"homekit-service","z":"8ab94716.868738","isParent":true,"bridge":"63a21f39.7ace9","parentService":"","name":"HSV light","serviceName":"Lightbulb","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n \"Brightness\":true,\n \"Hue\":true,\n \"Saturation\":true\n}","x":880,"y":1640,"wires":[["4bcb69da.54835"]]},{"id":"8d74448a.453288","type":"function","z":"8ab94716.868738","name":"Format","func":"var outmsg={};\nvar Hue = flow.get('Hue')||0;\nvar Saturation = flow.get('Saturation')||0;\nvar Brightness = flow.get('Brightness')||100;\n\nif(msg.payload[0]===0 && msg.payload[1]===0 && msg.payload[2]===0){\n outmsg.payload={\"On\":false};\n} else{\n Hue = msg.payload[0];\n flow.set('Hue',Hue);\n Saturation = msg.payload[1];\n flow.set('Saturation',Saturation);\n Brightness = msg.payload[2];\n flow.set('Brightness',Brightness);\n outmsg.payload={\n \"On\":true,\n \"Hue\":Hue,\n \"Saturation\":Saturation,\n \"Brightness\":Brightness\n }\n}\nreturn [outmsg];\n","outputs":1,"noerr":0,"x":700,"y":1640,"wires":[["42123222.b7e504"]]},{"id":"48309579.c4869c","type":"color-convert","z":"8ab94716.868738","input":"rgb","output":"hsv","outputType":"array","x":530,"y":1640,"wires":[["8d74448a.453288"]]},{"id":"9765eddf.4a7448","type":"function","z":"8ab94716.868738","name":"RGBW to RGB","func":"var Ri = msg.payload[0];\nvar Gi = msg.payload[1];\nvar Bi = msg.payload[2];\nvar Wi = msg.payload[3];\n\n //I am pretty sure we lost some data here... But how much?\n const Ro = (Ri + Wi);\n const Go = (Gi + Wi);\n const Bo = (Bi + Wi);\n\n return [{\"payload\":[Ro, Go, Bo]}];\n","outputs":1,"noerr":0,"x":340,"y":1640,"wires":[["48309579.c4869c"]]},{"id":"63a21f39.7ace9","type":"homekit-bridge","z":"","bridgeName":"Dev2","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number"}]
Hopefully you can make some progress with some of this.
If I've missed completely on all of it, take me back to square one, I need to know what your hardware devices are and how they're connected to openhab...
@crxporter Thanks for your help, I didn't had time to look at it.
Yes I also had to go back to the basics... I'm using an RGBW LED Strip Controller (MagicHome) which can be controlled with the WifiLED binding. Unfortunately the design of this binding is not the best... I have a Color channel which is HSV and a White channel with Percentage (I don't know who designed it).
That's why my first thought was to convert everything to RGB and RGBW to get some consistency in it (I don't know how I could mix a White channel into HSV and on the other side get back that White component).
Looking at the binding, it looks like it's not exactly RGBW - It looks like you could send a command to the color item of RGB=[255,255,255] or HSV=[0,0,100] AND a command of 100% brightness to the white dimmer item. In RGBW color space each of those would be [0,0,0,255] meaning you've got white at full bright - which both rgb 255,255,255 and hsv 0,0,100 are "white".
That would be a command of RGBW=[255,255,255,255] ... which isn't a valid value in RGB color space. That would mean your red, green, blue, and white LEDs in the strip are all running full power... If this is possible with your strip then you kind of do have 2 items here - a color strip (the RGB part) and a white strip (the dimmer part)
First question: does your strip controller have 4 or 5 connections? I'm pretty sure you have red, green, blue, white, and power - but there is a version of these without the white. (the red, green, blue, and white connectors are actually grounding each of these channels using PWM)
The MagicHome controller is based off an ESP8266 (my favorite!) or sometimes ESP8285. With that information - you have many options.
You can of course use the binding you are already using, it seems like you're pretty close on that one. You could take my functions up above and add an input/output for the white channel. You could run it in homekit as a double-item which would use the RGB channels as one color bulb item and the white channel as another, this would make it possible to send all possible values into your openhab system - treating them separately in homekit just as they are in openhab.
Another option is using tasmota on the board(s). Here is a good write up about using these boards with that firmware (runs over mqtt)
According to the aliexpress (not always accurate) description of magic home, it supports 16 million colors - which is the normal color space for RGB (and RGBW). This suggests to me that it's not actually supported to send full bright to all four channels.
If I were doing this, I would probably move over to tasmota and set up my openhab/nodered to send and receive the hex color values like #RRGGBBWW
If you don't want to do that then we can adjust the functions to work properly with your current setup. The RGBW->RGB function will need to persist the incoming values in a flow context. The RGB->RGBW function will need 2 outputs, one going to the color item and the other going to the white channel.
That conversion would look something like this (partly tested - W channel is still out on a scale of 0-255):

Flow:
[{"id":"20580380.a90d8c","type":"function","z":"8ab94716.868738","name":"RGB to RGBW","func":"var Ri = msg.payload[0];\nvar Gi = msg.payload[1];\nvar Bi = msg.payload[2];\n\n //Get the maximum between R, G, and B\n let tM = Math.max(Ri, Math.max(Gi, Bi));\n\n //If the maximum value is 0, immediately return pure black.\n if(tM === 0)\n return [{\"payload\":[0,0,0]},{\"payload\":0}];\n\n //This section serves to figure out what the color with 100% hue is\n var multiplier = 255 / tM;\n var hR = Ri * multiplier;\n var hG = Gi * multiplier;\n var hB = Bi * multiplier; \n\n //This calculates the Whiteness (not strictly speaking Luminance) of the color\n var M = Math.max(hR, Math.max(hG, hB));\n var m = Math.min(hR, Math.min(hG, hB));\n var Luminance = ((M + m) / 2 - 127.5) * (255.0/127.5) / multiplier;\n\n //Calculate the output values\n var Wo = Luminance;\n var Bo = Bi - Luminance;\n var Ro = Ri - Luminance;\n var Go = Gi - Luminance;\n\n //Trim them so that they are all between 0 and 255\n if (Wo < 0) Wo = 0;\n if (Bo < 0) Bo = 0;\n if (Ro < 0) Ro = 0;\n if (Go < 0) Go = 0;\n if (Wo > 255) Wo = 255;\n if (Bo > 255) Bo = 255;\n if (Ro > 255) Ro = 255;\n if (Go > 255) Go = 255;\n return [{\"payload\":[Ro,Go,Bo]},{\"payload\":Wo}];\n","outputs":2,"noerr":0,"x":1160,"y":1800,"wires":[["1d7a54a8.ff40e3"],["fad386b.97b2e78"]]},{"id":"1d7a54a8.ff40e3","type":"debug","z":"8ab94716.868738","name":"RGB output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1350,"y":1780,"wires":[]},{"id":"5ba06b37.962d6c","type":"debug","z":"8ab94716.868738","name":"W output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1460,"y":1820,"wires":[]},{"id":"bbaf6c6d.159cd","type":"function","z":"8ab94716.868738","name":"RGBW to RGB","func":"var Ri = context.get('Ri')||0;\nvar Gi = context.get('Gi')||0;\nvar Bi = context.get('Bi')||0;\nvar Wi = context.get('Wi')||0;\n\nif(msg.rgb){\n Ri = msg.rgb[0];\n Gi = msg.rgb[1];\n Bi = msg.rgb[2];\n context.set('Ri',Ri);\n context.set('Gi',Gi);\n context.set('Bi',Bi);\n}\nif(msg.white!==undefined){\n Wi = msg.white;\n context.set('Wi',Wi);\n}\n\n //I am pretty sure we lost some data here... But how much?\n const Ro = (Ri + Wi);\n const Go = (Gi + Wi);\n const Bo = (Bi + Wi);\n\n return [{\"payload\":[Ro, Go, Bo]}];\n","outputs":1,"noerr":0,"x":940,"y":1800,"wires":[[]]},{"id":"2a06adc0.1179ba","type":"change","z":"8ab94716.868738","name":"RGB channel in","rules":[{"t":"move","p":"payload","pt":"msg","to":"rgb","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":1780,"wires":[["bbaf6c6d.159cd"]]},{"id":"ce2ec9d9.0331b8","type":"change","z":"8ab94716.868738","name":"W channel in","rules":[{"t":"move","p":"payload","pt":"msg","to":"white","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":1820,"wires":[["65787b06.b9f264"]]},{"id":"fad386b.97b2e78","type":"range","z":"8ab94716.868738","minin":"0","maxin":"255","minout":"0","maxout":"100","action":"scale","round":true,"property":"payload","name":"Scale","x":1330,"y":1820,"wires":[["5ba06b37.962d6c"]]},{"id":"65787b06.b9f264","type":"range","z":"8ab94716.868738","minin":"0","maxin":"100","minout":"0","maxout":"255","action":"scale","round":true,"property":"white","name":"Scale","x":770,"y":1820,"wires":[["bbaf6c6d.159cd"]]}]
I put this together then I remembered you may be getting HSV values out of openhab. I don't always love openhab... The problem is you can't have HSV color space AND the W color space. It doesn't work. HSV is all of the colors, including white. White in HSV is [0,0,100] 50% dim white is [0,0,50] (the H and S can actually be any number).
I see why you've been struggling with this.
You inspired me to finally take a few minutes to adapt my lights to a color bulb in homekit.
Yes it has a fully seperate White channel (4 independent channels). Firstly I think now I will just try to get the HSV working (it should be easy but something didn't really worked out before)...
@radokristof how is this going? Have you had any breakthroughs lately?
I'm bored in a hotel tonight going through everything - seeing if we have some issues that are ready to be closed...
@radokristof how is it going here?
Bump, @radokristof how is the situation here?
If you still have a problem maybe we can try to start from the begining?
Simply describe what is your input and what is your output.
Yes I didn't had time to work with this.
I will try to explain where I always got stuck.
I have an HSV input (which I could easily send it to HomeKit). Plus I have a White channel (in percent to I have to first calculate this to some more meaningful unit), but these can be done.
Where I stuck is to send command from HomeKit. I can't back the 'white' part from the output. And it is not enough to just say set white to 37% I also need to distract this from the original value, in order to have a good output, with correct colors.
And your output is RGBW, correct?
From what I understand - there are 4 separate LED channels available on the lights:
1- Red
2- Green
3- Blue
4- White
Each of the 4 can be driven at 100%. Most node-red plugins are written to run r, g, b only and if the light is supposed to be white it sends 255, 255, 255 BUT these lights can run 255, 255, 255, 255...
So really you can technically have 200% brightness...
I believe I put a script up there somewhere that would take the hsv colors and output to rgbw. What it did was take the minimum between r, g, and b - subtract that value from each r, g, b - and send it to w.
Example: send 40, 57, 90 into the script and get out 0, 17, 50, 40
This was a thought I had on a way to settle the 4 separate channels. But no way to send 200% brightness on that. I believe this method is how "typical" rgbw lights work...
Red Green and Blue are all together, sent by 1 openHAB node (represented on 8 bit - 255 max value) and another node is sending the White as percents.
I will have a look at your RGBW code again. But I always stuck at some point, resulting in that the lamp would not want to turn on at all. I will try again!
Yes and one other thing:
I need to store for these calculations (and mostly because of HomeKit) the states of each channel, I did it with a flow.set, flow.get. But this is cumbersome and make it hard to maintain if I have more than a few lights. Is there a solution for this to 'hide' the saving? Like creating a subflow, will it save the states to different objects?
When you save values in flow then save them under common key (not r,g,b directly but under some parent key).
If I am right then saving red in key LightOne.r, green in LightOne.g and blue in LightOne.b should create:
LightOne: {
r: 123,
g: 233,
b: 122
}
Then when you add new light you can change LightOne to LightTwo etc.
@Shaquu thanks this makes it much cleaner. But I'm thinking that it is not possible to make a general script (like you would make a Java class) and have more instance of that class? That way, there will be no lightOne, lightTwo, etc... It is possible in Node-RED and more particular, in Javascript?
You can make multiple instances in JS but you still have to distinguish them somehow for example with a key :)
Maybe add topic to Service so it will be passed forward and use it as a key? Or just node.name?
You have some values you could use to distinguish multiple Services:
const msg = {payload: {}, hap: info, name: node.name, topic: topic};
topic? node.name? info?
Ok, I have started it again from a scratch, looking at the examples as well.
What I did now is eliminated the White channel at first, see if I can get it working with just the HSV colors.
It is working!
I was wrong with the colors. OpenHAB everywhere describes that the Color channel returns RGB but it seems that this returns HSV. So this can be easily done. Now I don't know how I could add the white to the input (first I convert it from percent and then? Just adding it to the Brightness channel won't work...). Also how I could distract the white from the output?
And I realised that I don't really know how these 'compact' color selectors work in native, like for example in a Philips Hue lamp. I mean how I can achieve the brightest color if I want, with still providing correct output...
To add white to HSV you would have to convert HSV to RGBW and add white to W value.
And RGBW back to HSV to send it to HomeKit right?
Sent from my iPhone
On 2019. Jun 23., at 18:50, Shaq notifications@github.com wrote:
To add white to HSV you would have to convert HSV to RGBW and add white to W value.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
I think yes.
@Shaquu thanks I will try it again with the color convert nodes.
So what situation do we have here?
Not perfect, but I made it work. I will post some tutorials soon on this.
I'm closing this.
I dare you too post tutorials! :)
The part below should change, otherwise when colors are blue(0,0,255) or green(0,255,0) it will always return black(0,0,0)