From 0a1281e383c27222f0d6ef5c6edb6be14b2db9f2 Mon Sep 17 00:00:00 2001
From: jkerdreux-imt <jerome.kerdreux@imt-atlantique.fr>
Date: Wed, 13 Nov 2024 01:37:09 +0100
Subject: [PATCH] Fix the unknown type

Cbor return an interface{} for everything, casting to uint64 or float64
is wrong due to the fact that xAAL schemas support both (even int is
possible). So recast everything to float64 and deal w/ that.

float64 mainly because colorful use float64 for everything, so as
brightness is Z in yxz format...
---
 utils.go | 38 ++++++++++++++++++++++++++++++++++++++
 xaal.go  | 39 ++++++++++++++++++++-------------------
 2 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/utils.go b/utils.go
index 95112e3..780b786 100644
--- a/utils.go
+++ b/utils.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"fmt"
 	"math"
 	"strconv"
 
@@ -73,3 +74,40 @@ func roundToDecimal(value float64, places int) float64 {
 	pow := math.Pow(10, float64(places))
 	return math.Round(value*pow) / pow
 }
+
+// convert Mired to Kelvin and Kelvin to Mired
+// Mired = 1,000,000 / Temperature in Kelvin
+func convertMired(value float64) float64 {
+	return 1e6 / float64(value)
+}
+
+func convertToFloat64(value interface{}) (float64, error) {
+	switch v := value.(type) {
+	case float32:
+		return float64(v), nil
+	case float64:
+		return v, nil
+	case int:
+		return float64(v), nil
+	case uint:
+		return float64(v), nil
+	case int8:
+		return float64(v), nil
+	case uint8:
+		return float64(v), nil
+	case int16:
+		return float64(v), nil
+	case uint16:
+		return float64(v), nil
+	case int32:
+		return float64(v), nil
+	case uint32:
+		return float64(v), nil
+	case int64:
+		return float64(v), nil
+	case uint64:
+		return float64(v), nil
+	default:
+		return 0.0, fmt.Errorf("Unable to converts %v (%T)", value, value)
+	}
+}
diff --git a/xaal.go b/xaal.go
index 0a8498f..08aff38 100644
--- a/xaal.go
+++ b/xaal.go
@@ -307,8 +307,7 @@ func (dev *Lamp) update(payload map[string]interface{}) {
 		// the color_temp is wrong when you change the mode w/ setMode
 		color_temp, exists := payload["color_temp"].(float64)
 		if exists {
-			// Mired = 1,000,000 / Temperature in Kelvin
-			color_temp = 1000000 / color_temp
+			color_temp = convertMired(color_temp)
 			dev.GetAttribute("white_temperature").SetValue(int(color_temp))
 		}
 	}
@@ -317,9 +316,9 @@ func (dev *Lamp) update(payload map[string]interface{}) {
 	if dev.getMode() == "color" {
 		color, exists := payload["color"].(map[string]interface{})
 		if exists {
-			x, _ := color["x"].(float64)
-			y, _ := color["y"].(float64)
-			brigthness, _ := payload["brightness"].(float64)
+			x, _ := convertToFloat64(color["x"])
+			y, _ := convertToFloat64(color["y"])
+			brigthness, _ := convertToFloat64(payload["brightness"])
 			value := xyToColor(x, y, brigthness)
 			slog.Debug("color", "color", value.Hex(), "x", x, "y", y, "tmp", brigthness)
 			hue, sat, val := value.Hsv()
@@ -347,19 +346,20 @@ func (dev *Lamp) toggle(xaal.MessageBody) *xaal.MessageBody {
 }
 
 func (dev *Lamp) setBrightness(body xaal.MessageBody) *xaal.MessageBody {
-	// TODO: I don't know why we receive a uint64 instead of a float64
-	value, exists := body["brightness"].(uint64)
+	value, exists := body["brightness"]
 	if exists {
-		dev.Z2MDevice.Set(fmt.Sprintf(`{"brightness": %d}`, value*255/100))
+		target, _ := convertToFloat64(value)
+		dev.Z2MDevice.Set(fmt.Sprintf(`{"brightness": %d}`, int(target*255/100)))
 	}
 	return nil
 }
 
 func (dev *Lamp) setWhiteTemperature(body xaal.MessageBody) *xaal.MessageBody {
-	value, exists := body["white_temperature"].(uint64)
+	value, exists := body["white_temperature"]
 	if exists {
-		value = 1000000 / value
-		dev.Z2MDevice.Set(fmt.Sprintf(`{"color_temp": %d}`, int(value)))
+		target, _ := convertToFloat64(value)
+		target = convertMired(target)
+		dev.Z2MDevice.Set(fmt.Sprintf(`{"color_temp": %d}`, int(target)))
 	}
 	return nil
 }
@@ -367,9 +367,9 @@ func (dev *Lamp) setWhiteTemperature(body xaal.MessageBody) *xaal.MessageBody {
 func (dev *Lamp) setHSV(body xaal.MessageBody) *xaal.MessageBody {
 	value, exist := body["hsv"].([]interface{})
 	if exist {
-		hue := float64(value[0].(uint64))
-		sat := value[1].(float64)
-		val := value[2].(float64)
+		hue, _ := convertToFloat64(value[0])
+		sat, _ := convertToFloat64(value[1])
+		val, _ := convertToFloat64(value[2])
 		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()))
@@ -383,21 +383,22 @@ func (dev *Lamp) setMode(body xaal.MessageBody) *xaal.MessageBody {
 		// for a unknown reason, we are unable to set the color_mode
 		// z2m doesn't give an error, but the color_mode doesn't change
 		// so we set old color or temperature
+		//
+		// dev.Z2MDevice.Set(`{"color_mode": "color_temp"}`)
+		// dev.Z2MDevice.Set(`{"color_mode": "xy"}`)
 		switch value {
 		case "color":
-			// dev.Z2MDevice.Set(`{"color_mode": "xy"}`)
 			hsv := dev.GetAttribute("hsv").Value.([]float64)
 			color := colorful.Hsv(hsv[0], hsv[1], hsv[2])
 			dev.Z2MDevice.Set(fmt.Sprintf(`{"color": { "hex": "%s" }}`, color.Hex()))
 		case "white":
-			// dev.Z2MDevice.Set(`{"color_mode": "color_temp"}`)
-			value := dev.GetAttribute("white_temperature").Value.(int)
+			value := dev.GetAttribute("white_temperature").Value.(float64)
 			// if booted in color mode, while_temperature is 0 => divide crash
 			if value == 0 {
 				value = 3000
 			}
-			value = 1000000 / value
-			dev.Z2MDevice.Set(fmt.Sprintf(`{"color_temp": %d}`, value))
+			value = convertMired(value)
+			dev.Z2MDevice.Set(fmt.Sprintf(`{"color_temp": %d}`, int(value)))
 		}
 	}
 	return nil
-- 
GitLab