IKEA Tradfi Lampen mit Farbwahl werden nicht nach Alexa übernommen

Hallo,

ich habe da ein kleines Problem ( oder vielleicht mache ich einen Denkfehler )

Ich habe mehrere IKEA Tradfi Lampe mit Farbwahlmöglichkeit ( Weisston ).
Diese sind über die Tradfi-Bridge in und dem Tradfi Modul in IPS angelegt

Im Alexa Modul habe ich nun alle Lampen ebenfalls eingerichtet, über den Punkt "Lampen (Experte).

Alle Lampen mit Schalt- und Helligkeitsvariable werden einwandfrei nach Alexa übernommen und erscheinen auch in der Alexa App.

Nur bei den Lampen, die eine zusätzliche Farbvariable haben, passiert nichts, die erscheinen nicht in Alexa.
Es ist auch egal, ob ich für die Farbvariable „Ambiente“ oder „Farbe“-Variable in IPS nehme.
Lasse ich diese weg, geht es wunderbar.

Ist da ein Problem bekannt oder gibt es bereits eine Lösung dafür ?

Danke im Voraus

Hallo Tuxtom007,

ist das über mein Modul eingebunden?

Joachim

Steht der Status der Geräte in der Alexa-Instanz auf OK? Wenn ja, dann sollten die Geräte gefunden werden, ansonsten müsstest du den dort dargestellten Fehler ausbessern.

Hallo Joachim, ja die Lampen sind mit deinem Modul eingebunden

Nee, jett wo du es schreibst.

Ich hänge mal einen Screenshot an.
Die im Status OK werden auch eingelesen in Alexa

Hallo Tuxtom007,

das mit der Farbe ist bei der IKEA-Leuchte etwas anders als vielleicht bei anderen Leuchten, da sie nur bestimmte Farben als Hex akzeptiert, weswegen ich kein „normales“ HexColor verwenden konnte.
Hier ist erklärt, das die IKEA-Leuchte xy-Werte benötigt, bisher war es mir aber nicht gelungen diese Werte aus dem IPS-HexColor zu transformieren (was nicht heißt das es funktionieren könnte!).

Von daher wird das so erst einmal nicht funktionieren…

Joachim

Wie eingeschränkt ist der Farbraum der Lampen denn? Prinzipiell könnte man im Modul ja das ~HexColor-Profil verwenden und müsste dann intern rumrechnen. Wird auf eine Farbe geschaltet, könntest du die nächstmögliche Farbe bestimmen und darauf schalten.

Ansonsten sind die Meldungen ja glaube ich selbsterklärend: Action required erfordert eine Variablenaktion. Die gewählte Variable ist nicht schaltbar. Und ~HexColor profile required ist das von Joachim beschriebene Problem.

Vorerst müsstest du die Farbvariablen wohl leider rausnehmen, dann sollte alles andere funktionieren.

Hallo Dr.Niels,

genau das ist die Herausforderung: Die IPS-HexColor-Werte in den xyY-Wertebereich (siehe Link im oberen Posting) der IKEA-Lampen (und zurück) zu transformieren. Ich habe dazu im Internet leider keine funktionierende Funktion gefunden.
Wenn diese Funktion vorhanden ist, wäre das kein Problem…[emoji6]

Joachim

Hallo Joachim,

schau doch mal bei Kai ins HUE Modul :
IPS-PhilipsHUE/ColorHelper.php at master · Schnittcher/IPS-PhilipsHUE · GitHub

Ev. hilft dir das ?

Hallo Thomas,

auf den ersten Blick ist das leider nicht passend. Wie hier erläutert, wird ein „xyY color space“ genutzt, die Funktion von Kai arbeitet offenbar mit drei Werten (xyz). Vielleicht kann das Z-Parameter zu null gesetzt werden, habe dazu aber nichts gefunden.
Vielleicht ist ja ein Farbspezialist unter uns der uns aufklären kann?

Joachim

Ich nutze dann aber nur x und y.
Der letzte Wert ist nur die Helligkeit wenn ich das noch richtig im Kopf habe.

Grüße,
Kai

Hallo Kai,

sind die xY-Werte zwischen 0 und 65535?

Joachim

Nein, ich brauche aber gerade auch genau diesen Wertebereich und versuche mich daran.

Edit: Hast du eine Webseite, bei der du genau die Farbwerte eingeben kannst und dir dazu der RGB Wert angezeigt wird?
Finde dazu irgendwie nichts.

Grüße,
Kai

Versuch es mal damit:



function RGBToCIE($red, $green, $blue, $opt = false)
    {
        $red = ($red > 0.04045) ? pow(($red + 0.055) / (1.0 + 0.055), 2.4) : ($red / 12.92);
        $green = ($green > 0.04045) ? pow(($green + 0.055) / (1.0 + 0.055), 2.4) : ($green / 12.92);
        $blue = ($blue > 0.04045) ? pow(($blue + 0.055) / (1.0 + 0.055), 2.4) : ($blue / 12.92);

        $X = $red * 0.664511 + $green * 0.154324 + $blue * 0.162028;
        $Y = $red * 0.283881 + $green * 0.668433 + $blue * 0.047685;
        $Z = $red * 0.000088 + $green * 0.072310 + $blue * 0.986039;
        //$this->SendDebug('RGBToCIE', 'X: ' . $X . ' Y: ' . $Y . ' Z: ' . $Z, 0);

        if ($opt) {
            $cie['x'] = round(($X / ($X + $Y + $Z) * 65536), 0);
            $cie['y'] = round(($Y / ($X + $Y + $Z) * 65536), 0);
        } else {
            $cie['x'] = round(($X / ($X + $Y + $Z)), 4);
            $cie['y'] = round(($Y / ($X + $Y + $Z)), 4);
        }

        return $cie;
    }


function CIEToRGB($x, $y, $brightness = 255, $opt = false)
    {

        if ($opt) {
            $x = $x / 65536;
            $y = $y / 65536;
        }
        
        $z = 1.0 - $x - $y;
        $Y = $brightness / 255;
        $X = ($Y / $y) * $x;
        $Z = ($Y / $y) * $z;

        $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 ($red > $blue && $red > $green && $red > 1.0) {
            $green = $green / $red;
            $blue = $blue / $red;
            $red = 1.0;
        } elseif ($green > $blue && $green > $red && $green > 1.0) {
            $red = $red / $green;
            $blue = $blue / $green;
            $green = 1.0;
        } elseif ($blue > $red && $blue > $green && $blue > 1.0) {
            $red = $red / $blue;
            $green = $green / $blue;
            $blue = 1.0;
        }
        $red = $red <= 0.0031308 ? 12.92 * $red : (1.0 + 0.055) * $red ** (1.0 / 2.4) - 0.055;
        $green = $green <= 0.0031308 ? 12.92 * $green : (1.0 + 0.055) * $green ** (1.0 / 2.4) - 0.055;
        $blue = $blue <= 0.0031308 ? 12.92 * $blue : (1.0 + 0.055) * $blue ** (1.0 / 2.4) - 0.055;

        $red = ceil($red * 255);
        $green = ceil($green * 255);
        $blue = ceil($blue * 255);

        $color = sprintf('#%02x%02x%02x', $red, $green, $blue);

        return $color;
    }

function HexToRGB($value)
    {
        $RGB = [];
        $RGB[0] = (($value >> 16) & 0xFF);
        $RGB[1] = (($value >> 8) & 0xFF);
        $RGB[2] = ($value & 0xFF);
        //$this->SendDebug('HexToRGB', 'R: ' . $RGB[0] . ' G: ' . $RGB[1] . ' B: ' . $RGB[2], 0);
        return $RGB;
    }

Mit HexToRGB kannst du Hex in RGB umrechnen.
Wenn du von HEX in RGB umgerechnet hast kannst du mit der Funktion RGBToCIE in X und Y umrechnen.
Der Parameter $opt = false gibt an, x und y im Wertebereich zwischen 0 und 65535 liegen

Mit CIEToRGB kannst du RGB zu x und y umrechnen.
Dazu musst du x, y, Helligkeit angeben.
Mit dem Parameter $opt = true gibst du wieder an, dass x und y im Wertebreich zwischen 0 und 65535 liegen.

Ich würde mich über eine Rückmeldung freuen ob es klappt.

Grüße,
Kai

Hallo Kai,

konnte es noch nicht vollumfänglich prüfen, aber ein Problem ist schwarz (0,0,0), da gibt es ein Division by Zero Error. Ich weiß jetzt nicht, wie man das am Besten prüft. Möglicherweise tritt der Fehler immer dann auf, wenn einer der drei Werte 0 ist.

Ansonsten bist Du auf dem richtigen Weg, habe nur mal einen Blauton probiert und das funktionierte.

Ist also noch etwas zu machen, sollte man aber hinbekommen.
Übrigens hatten wir wohl beide die gleiche Quelle, mein Code ist nahezu identisch aufgebaut, nur hatte ich die Skalierung anders gemacht (und damit gescheitert)…

Melde mich wenn ich da weiter bin…

Joachim

…nach meinen Tests tritt der Fehler nur bei Schwarz (0,0,0) auf…

Ansonsten sehen der gesendete Wert und das Ergebnis sehr ähnlich aus.

Joachim

Ich glaube ich werde mal ein für ColorHelper Trait erstellen.
Kann man dann als Submodule einbinden.

Grüße,
Kai

Hallo,

da euch für die Ausführungen.

Die Lampen bei mir sind keine RGB-Lampen, sondern welche mit mehreren Weiss-Tönen. Das ist daher nicht so wirklich tragisch, wenn es nicht funktioniert. Schalten und Dimmen ist wichtiger.

Ich werde die Farbvariablen überall rauswerfen.

WEnn ich was testen soll, sagt Bescheid

Hab den Fehler mal abgefangen :

function RGBToCIE($red, $green, $blue, $opt = false)
    {
     if( $red == 0 || $green == 0 || $blue == 0) { 
        $cie['x'] = 0;
        $cie['y'] = 0;
     }
     else{
        $red = ($red > 0.04045) ? pow(($red + 0.055) / (1.0 + 0.055), 2.4) : ($red / 12.92);
        $green = ($green > 0.04045) ? pow(($green + 0.055) / (1.0 + 0.055), 2.4) : ($green / 12.92);
        $blue = ($blue > 0.04045) ? pow(($blue + 0.055) / (1.0 + 0.055), 2.4) : ($blue / 12.92);

        $X = $red * 0.664511 + $green * 0.154324 + $blue * 0.162028;
        $Y = $red * 0.283881 + $green * 0.668433 + $blue * 0.047685;
        $Z = $red * 0.000088 + $green * 0.072310 + $blue * 0.986039;
        //$this->SendDebug('RGBToCIE', 'X: ' . $X . ' Y: ' . $Y . ' Z: ' . $Z, 0);

        if ($opt) {
            $cie['x'] = round(($X / ($X + $Y + $Z) * 65536), 0);
            $cie['y'] = round(($Y / ($X + $Y + $Z) * 65536), 0);
        } else {
            $cie['x'] = round(($X / ($X + $Y + $Z)), 4);
            $cie['y'] = round(($Y / ($X + $Y + $Z)), 4);
        }
     }
        return $cie;
    }       

Hallo Kai und Thomas,

die beiden Funktionen auf meine Bedürfnisse angepasst sehen jetzt so aus:

private function HexToCIE($HexColor)
	{
		$red = (($HexColor >> 16) & 0xFF);
		$green = (($HexColor >> 8) & 0xFF);
		$blue = ($HexColor & 0xFF);
		$this->SendDebug('HexToCIE', 'red: ' . $red . ' green: ' . $green . ' blue: ' . $blue, 0);
		
		$red = ($red > 0.04045) ? pow(($red + 0.055) / (1.0 + 0.055), 2.4) : ($red / 12.92);
		$green = ($green > 0.04045) ? pow(($green + 0.055) / (1.0 + 0.055), 2.4) : ($green / 12.92);
		$blue = ($blue > 0.04045) ? pow(($blue + 0.055) / (1.0 + 0.055), 2.4) : ($blue / 12.92);

		$X = $red * 0.664511 + $green * 0.154324 + $blue * 0.162028;
		$Y = $red * 0.283881 + $green * 0.668433 + $blue * 0.047685;
		$Z = $red * 0.000088 + $green * 0.072310 + $blue * 0.986039;
		$this->SendDebug('HexToCIE', 'X: ' . $X . ' Y: ' . $Y . ' Z: ' . $Z, 0);

		If (($X + $Y + $Z) > 0) {
			$cie['x'] = round(($X / ($X + $Y + $Z) * 65536), 0);
			$cie['y'] = round(($Y / ($X + $Y + $Z) * 65536), 0);
		}
		else {
			$cie['x'] = 0;
			$cie['y'] = 0;
		}
		
	return $cie;
	} 
	 
	private function CIEToHex($x, $y)
	{
		$brightness = 255;
		$x = $x / 65536;
		$y = $y / 65536;

		$z = 1.0 - $x - $y;
		$Y = $brightness / 255;
		$X = ($Y / $y) * $x;
		$Z = ($Y / $y) * $z;

		$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 ($red > $blue && $red > $green && $red > 1.0) {
		    $green = $green / $red;
		    $blue = $blue / $red;
		    $red = 1.0;
		} elseif ($green > $blue && $green > $red && $green > 1.0) {
		    $red = $red / $green;
		    $blue = $blue / $green;
		    $green = 1.0;
		} elseif ($blue > $red && $blue > $green && $blue > 1.0) {
		    $red = $red / $blue;
		    $green = $green / $blue;
		    $blue = 1.0;
		}
		$red = $red <= 0.0031308 ? 12.92 * $red : (1.0 + 0.055) * $red ** (1.0 / 2.4) - 0.055;
		$green = $green <= 0.0031308 ? 12.92 * $green : (1.0 + 0.055) * $green ** (1.0 / 2.4) - 0.055;
		$blue = $blue <= 0.0031308 ? 12.92 * $blue : (1.0 + 0.055) * $blue ** (1.0 / 2.4) - 0.055;

		$red = ceil($red * 255);
		$green = ceil($green * 255);
		$blue = ceil($blue * 255);
		
		$Hex = ($red << 16) | ($green << 8) | $blue;
	return $Hex;
	} 

Was ich zuvor nicht richtig gemacht hatte war die Skalierung, aber jetzt sieht es gut aus!

Danke!

Joachim

Ich würde brightness optional mit als Parameter aufnehmen.

Grüße,
Kai