I see your transformationPatternOut and I raise you a transformationPattern (in).
I loved that with your transformation I could use a single Color item and link it to OpenHAB Switch, Dimmer, and Color objects to control them with one bit of code, but it bugged me that updating the color of the device didn’t update the OpenHAB object. The next time I would pull up the ColorPicker, it would default back to white, not the current color.
So I decided to see if I could cobble up an incoming transformationPatter script.
My Thing definition (the important part is the colorHSB definition):
Thing topic testlightstrip {
Type switch : toggleonoff [ stateTopic="zigbee2mqtt/test_osram_flexstrip/state", commandTopic="zigbee2mqtt/test_osram_flexstrip/set/state", on="ON", off="OFF", transformationPatternOut="JS:HSBtoRGB.js"]
Type dimmer : dim [ stateTopic="zigbee2mqtt/test_osram_flexstrip/brightness", commandTopic="zigbee2mqtt/test_osram_flexstrip/set/brightness_percent", transformationPattern="JS:byte2percent.js" ] //, transformationPatternOut="JS:percent2byte.js"]
//Note: Color is still SET-only:
Type colorHSB : colorHSB [
commandTopic="zigbee2mqtt/test_osram_flexstrip/set", transformationPatternOut="JS:HSBtoRGB.js", onBrightness=100,
stateTopic="zigbee2mqtt/test_osram_flexstrip", transformationPattern="JS:xyz2hsb.js"
]
}
My Items:
Switch testlightstrip_sw "Test Lightstrip sw" (gTest) {channel="mqtt:topic:Mosq:testlightstrip:colorHSB"}
Dimmer testlightstrip_dim "Test Lightstrip dim" (gTest) {channel="mqtt:topic:Mosq:testlightstrip:colorHSB"}
Color testlightstrip_color "Test Lightstrip clr" (gTest) {channel="mqtt:topic:Mosq:testlightstrip:colorHSB"}
The xyz2hsb.js transformation script:
//Convert Zigbee2MQTT's xyZ format to OpenHAB's HSB/HSV format
(function(xyz) {
var debug=true;
if (debug) {
var logger = Java.type("org.slf4j.LoggerFactory").getLogger("xyz2hsb.js");
logger.warn("Input: "+xyz);
}
var json = JSON.parse(xyz);
var x = json.color.x;
var y = json.color.y;
var brightness = json.brightness;
if (debug) logger.warn("X:" + x + " Y:" + y + " B:"+ brightness);
//The following is based on https://github.com/Koenkk/zigbee2mqtt/issues/3497
if (brightness === undefined) brightness = 254; //Do I need this in this context??
var z = 1.0 - x - y;
var Y = (brightness / 254).toFixed(2);
var X = (Y / y) * x;
var Z = (Y / y) * z;
//Convert to RGB using Wide RGB D65 conversion
var r = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
var g = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
var b = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
//If red, green or blue is larger than 1.0 set it back to the maximum of 1.0
if (r > b && r > g && r > 1.0) {
g = g / r;
b = b / r;
r = 1.0;
} else if (g > b && g > r && g > 1.0) {
r = r / g;
b = b / g;
g = 1.0;
} else if (b > r && b > g && b > 1.0) {
r = r / b;
g = g / b;
b = 1.0;
}
//Reverse gamma correction
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
//Convert normalized decimal to decimal
r = Math.round(r * 255);
g = Math.round(g * 255);
b = Math.round(b * 255);
if (isNaN(r)) r = 0;
if (isNaN(g)) g = 0;
if (isNaN(b)) b = 0;
if (debug) logger.warn("RGB: "+r+","+g+","+b);
// We now have RGB!!! Now convert THAT to HSB for OpenHAB's pleasure:
//The following based on https://stackoverflow.com/questions/8022885/rgb-to-hsv-color-in-javascript
var rabs, gabs, babs, rr, gg, bb, h, s, v, diff;
rabs = r / 255;
gabs = g / 255;
babs = b / 255;
v = Math.max(rabs, gabs, babs),
diff = v - Math.min(rabs, gabs, babs);
if (diff == 0) {
h = s = 0;
} else {
s = diff / v;
rr = (v - rabs) / 6 / diff + 1 / 2;
gg = (v - gabs) / 6 / diff + 1 / 2;
bb = (v - babs) / 6 / diff + 1 / 2;
if (rabs === v) {
h = bb - gg;
} else if (gabs === v) {
h = (1 / 3) + rr - bb;
} else if (babs === v) {
h = (2 / 3) + gg - rr;
}
if (h < 0) {
h += 1;
}else if (h > 1) {
h -= 1;
}
}
// var hsb = Math.round(h*360) + "," + Math.round(s * 100) + "," + Math.round(v * 100);
var hsb = h*360.0 + "," + s * 100.0 + "," + v * 100.0;
if (debug) logger.warn("Returning HSB: "+hsb);
return(hsb);
})(input)
Debug output shows that the xyz2hsb.js properly converts the Zigbee2MQTT’s xyz color codes back to OpenHAB’s HSB format and when you open the ColorPicker again, it shows you the current value.
I hope that this provides some value to others who want to be able to use a Color object in both directions.