Skip to content
Snippets Groups Projects
Commit 93caf40e authored by KERDREUX Jerome's avatar KERDREUX Jerome
Browse files

Add support for color

xy decoding is a pain to decode. Thanks to chatgpt, I was able to port
the JS code. The code seems to works fine now.

I need to fix a issue in the xAAL core due to compare of list..
parent 7009e224
Branches
No related tags found
No related merge requests found
package main
import "strconv"
import (
"math"
"strconv"
"github.com/lucasb-eyer/go-colorful"
)
func hexStringToInteger(hexString string) (uint64, error) {
// Drop the "0x" prefix if it exists
......@@ -15,3 +20,56 @@ func hexStringToInteger(hexString string) (uint64, error) {
}
return integerValue, nil
}
// xyToColor converts CIE XY color coordinates and brightness to an RGB color using the go-colorful library.
// https://github.com/Koenkk/zigbee2mqtt/issues/3497
func xyToColor(x, y, brightness float64) colorful.Color {
// Set maximum brightness if not provided (assuming brightness is in the range 0-254)
if brightness == 0 {
brightness = 254
}
// Calculate z, X, Y, and Z values for the XYZ color space
z := 1.0 - x - y
Y := brightness / 254.0 // Normalize brightness
X := (Y / y) * x
Z := (Y / y) * z
// Convert XYZ to RGB using Wide RGB D65 conversion
red := X*1.656492 - Y*0.354851 - Z*0.255038
green := -X*0.707196 + Y*1.655397 + Z*0.036152
blue := X*0.051713 - Y*0.121364 + Z*1.011530
// If any color component is larger than 1.0, scale it back to 1.0 and adjust others accordingly
if red > blue && red > green && red > 1.0 {
green = green / red
blue = blue / red
red = 1.0
} else if green > blue && green > red && green > 1.0 {
red = red / green
blue = blue / green
green = 1.0
} else if blue > red && blue > green && blue > 1.0 {
red = red / blue
green = green / blue
blue = 1.0
}
// Apply reverse gamma correction to each component
applyGamma := func(value float64) float64 {
if value <= 0.0031308 {
return 12.92 * value
}
return (1.0+0.055)*math.Pow(value, 1.0/2.4) - 0.055
}
red = applyGamma(red)
green = applyGamma(green)
blue = applyGamma(blue)
return colorful.Color{R: red, G: green, B: blue}
}
func roundToDecimal(value float64, places int) float64 {
pow := math.Pow(10, float64(places))
return math.Round(value*pow) / pow
}
......@@ -6,6 +6,7 @@ import (
"math"
"github.com/davecgh/go-spew/spew"
"github.com/lucasb-eyer/go-colorful"
"gitlab.imt-atlantique.fr/xaal/code/go/core/schemas"
"gitlab.imt-atlantique.fr/xaal/code/go/core/uuid"
"gitlab.imt-atlantique.fr/xaal/code/go/core/xaal"
......@@ -252,7 +253,7 @@ func NewLamp(addr uuid.UUID, zDev *Z2MDevice, expose *Expose) XAALDeviceInterfac
}
if expose.GetFeature("color_xy") != nil {
dev.DevType = "lamp.color"
dev.AddAttribute("hsv", nil)
dev.AddAttribute("hsv", []float64{0, 0, 0})
dev.AddAttribute("mode", nil)
dev.UnsupportedAttributes = []string{"scene"}
dev.AddMethod("set_hsv", dev.setHSV)
......@@ -281,6 +282,23 @@ func (dev *Lamp) update(payload map[string]interface{}) {
brightness = brightness / 255 * 100
dev.GetAttribute("brightness").SetValue(int(brightness))
}
// color
color, exists := payload["color"].(map[string]interface{})
if exists {
x, _ := color["x"].(float64)
y, _ := color["y"].(float64)
brigthness, _ := payload["brightness"].(float64)
value := xyToColor(x, y, brigthness)
slog.Warn("color", "color", value.Hex(), "x", x, "y", y, "tmp", brigthness)
hue, sat, val := value.Hsv()
hue = roundToDecimal(hue, 1)
sat = roundToDecimal(sat, 2)
val = roundToDecimal(val, 2)
slog.Warn("color", "hue", hue, "sat", sat, "val", val)
dev.GetAttribute("hsv").SetValue([]float64{hue, sat, val})
return
}
// color_temp
color_temp, exists := payload["color_temp"].(float64)
if exists {
......@@ -324,7 +342,15 @@ func (dev *Lamp) setWhiteTemperature(body xaal.MessageBody) *xaal.MessageBody {
}
func (dev *Lamp) setHSV(body xaal.MessageBody) *xaal.MessageBody {
spew.Dump(body)
value, exist := body["hsv"].([]interface{})
if exist {
hue := float64(value[0].(uint64))
sat := value[1].(float64)
val := value[2].(float64)
color := colorful.Hsv(hue, sat, val)
slog.Debug("setHSV", "color", color.Hex(), "hue", hue, "sat", sat, "val", val)
dev.Z2MDevice.Set(fmt.Sprintf(`{"color": { "hex": "%s" }}`, color.Hex()))
}
return nil
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment