@mwittig I have 3 Hue color bulbs and 1 philips white. I will try your plugin next weekend!
Philips HUE Plugin
@mwittig yeah. You’re right.
I think it would also be very useful to update the status of the light(s). The node-hue-api has therefore the lightStatus() function. For power and brightness this is hopefully no big deal. For color - as far as I understand - we have to convert the CIE1931 Color of the Philips hue bulb/lamp to RGB or HEX. It seems that the implemented color library doesn’t provide this. The only (short) way I found is to implement this code:
@mwittig the last update indeed solved the error I had, but I gained a new one.
Everytime at startup I get the following error:
error [pimatic-led-light]: write EPIPE
Also the color of the color picker changes with the brightness slider, which isn’t correct for the living color lights of Philips.
What happens now is when the color is red for example and the brightness at 100%, the color picker shows it as white, while the living color light itself is still red.
In the version before, this changing more to white changed the saturation of the living colors light.
Is it opssible to revert that?
While I am pretty new to programming I am not able to give you the assistance to change the hue.coffee for a proper pulling service.
So far I managed to log the status events and to convert the color CIE1931 to HEX.
Perhaps you could use the code snippet:
HueApi = require('node-hue-api').HueApi #Color Calculation by https://github.com/bjohnso5/hue-hacking.git XYPoint = (x, y) -> @x = x @y = y return Red = new XYPoint(0.675, 0.322) Lime = new XYPoint(0.4091, 0.518) Blue = new XYPoint(0.167, 0.04) componentToHex = (c) -> hex = c.toString(16) if hex.length == 1 then '0' + hex else hex rgbToHex = (r, g, b) -> componentToHex(r) + componentToHex(g) + componentToHex(b) crossProduct = (p1, p2) -> p1.x * p2.y - (p1.y * p2.x) checkPointInLampsReach = (p) -> v1 = new XYPoint(Lime.x - (Red.x), Lime.y - (Red.y)) v2 = new XYPoint(Blue.x - (Red.x), Blue.y - (Red.y)) q = new XYPoint(p.x - (Red.x), p.y - (Red.y)) s = crossProduct(q, v2) / crossProduct(v1, v2) t = crossProduct(v1, q) / crossProduct(v1, v2) s >= 0.0 and t >= 0.0 and s + t <= 1.0 getClosestPointToLine = (A, B, P) -> AP = new XYPoint(P.x - (A.x), P.y - (A.y)) AB = new XYPoint(B.x - (A.x), B.y - (A.y)) ab2 = AB.x * AB.x + AB.y * AB.y ap_ab = AP.x * AB.x + AP.y * AB.y t = ap_ab / ab2 if t < 0.0 t = 0.0 else if t > 1.0 t = 1.0 new XYPoint(A.x + AB.x * t, A.y + AB.y * t) getClosestPointToPoint = (xyPoint) -> # Color is unreproducible, find the closest point on each line in the CIE 1931 'triangle'. pAB = getClosestPointToLine(Red, Lime, xyPoint) pAC = getClosestPointToLine(Blue, Red, xyPoint) pBC = getClosestPointToLine(Lime, Blue, xyPoint) dAB = getDistanceBetweenTwoPoints(xyPoint, pAB) dAC = getDistanceBetweenTwoPoints(xyPoint, pAC) dBC = getDistanceBetweenTwoPoints(xyPoint, pBC) lowest = dAB closestPoint = pAB if dAC < lowest lowest = dAC closestPoint = pAC if dBC < lowest lowest = dBC closestPoint = pBC closestPoint getDistanceBetweenTwoPoints = (one, two) -> dx = one.x - (two.x) dy = one.y - (two.y) # vertical difference Math.sqrt dx * dx + dy * dy CIE1931ToHex = (x, y, bri) -> if bri == undefined bri = 1 rgb = getRGBFromXYAndBrightness(x, y, bri) rgbToHex rgb, rgb, rgb hexFullRed: 'FF0000' hexFullGreen: '00FF00' hexFullBlue: '0000FF' hexFullWhite: 'FFFFFF' getRGBFromXYAndBrightness = (x, y, bri) -> xyPoint = new XYPoint(x, y) if bri == undefined bri = 1 # Check if the xy value is within the color gamut of the lamp. # If not continue with step 2, otherwise step 3. # We do this to calculate the most accurate color the given light can actually do. if !checkPointInLampsReach(xyPoint) # Calculate the closest point on the color gamut triangle # and use that as xy value See step 6 of color to xy. xyPoint = getClosestPointToPoint(xyPoint) # Calculate XYZ values Convert using the following formulas: Y = bri X = Y / xyPoint.y * xyPoint.x Z = Y / xyPoint.y * (1 - (xyPoint.x) - (xyPoint.y)) # Convert to RGB using Wide RGB D65 conversion. rgb = [ X * 1.612 - (Y * 0.203) - (Z * 0.302) -X * 0.509 + Y * 1.412 + Z * 0.066 X * 0.026 - (Y * 0.072) + Z * 0.962 ] # Apply reverse gamma correction. rgb = rgb.map((x) -> if x <= 0.0031308 then 12.92 * x else (1.0 + 0.055) * x ** (1.0 / 2.4) - 0.055 ) # Bring all negative components to zero. rgb = rgb.map((x) -> Math.max 0, x ) # If one component is greater than 1, weight components by that value. max = Math.max(rgb, rgb, rgb) if max > 1 rgb = rgb.map((x) -> x / max ) rgb = rgb.map((x) -> Math.floor x * 255 ) rgb getStateHex = (status) -> status = JSON.parse(JSON.stringify(status, null, 2)) bri = status.state.bri x = status.state.xy y = status.state.xy console.log CIE1931ToHex(x, y, bri) #console.log getRGBFromXYAndBrightness(x, y, bri) getStateOn = (status) -> status = JSON.parse(JSON.stringify(status, null, 2)) StateOn = status.state.on console.log StateOn getStateBri = (status) -> status = JSON.parse(JSON.stringify(status, null, 2)) bri = Math.round(status.state.bri * 100 / 254) console.log bri # hue Control host = 'xx.xx.xx.xx' username = 'xxxxxxxxx' lightName = 1 api = new HueApi(host, username) api.lightStatus(lightName).then(getStateHex).done() api.lightStatus(lightName).then(getStateOn).done() api.lightStatus(lightName).then(getStateBri).done()
EDIT: I own only one Philips hue. There is an issue with the calculation of the color green - all other colors calculation work fine so far.
Is there a way to set the start state of de hue?
Because everytime i restart pimatic all my lights go on…
@Rob-Jager Well i have something similar for 1 hue light if i restart pimatic, 1 hue light is dimming to 10%, don’t know why. I don’t have a rule that sets this light to 10%. All the others don’t turn on (9 hue lights).
I have also created a very barbones hue plugin now which currently only turns lights on and off. I will take a look at these two other plugins and check if it makes sense to develop mine further or deprecate it.
Thanks! Looks really great, I will give it a try. Even rule actions, great.