UPDATE 2015-04-06: Das Script wurde überarbeitet und berücksichtig nun die Helligkeit.

Nach reiflicher Überlegung habe ich mich dazu entschlossen ein Philips Hue Set zu kaufen, um das indirekte Licht im Wohnzimmer zu steuern und so für stimmungsvolle Beleuchtung zu sorgen. Das Set ist mit 179,- EUR schon sehr teuer und die Qualität der Komponenten wirkt auf den ersten Blick sehr billig und spiegelt in keiner Weise die hohen Investitionskosten wieder. Dennoch funktioniert die Anbindung mit der App sehr gut. Auch die API bei Philips ist sehr gut dokumentiert, so dass man schnell eigene Anbindungen schaffen kann.

In diesem Beitrag möchte ich zwei Dinge zeigen: die schnelle Einbindung in FHEM und die Programmierung eines Ambilights für Enigma2-Receiver. Hierbei handelt es sich um erste Versuche, die sicherlich noch nicht komplett ausgereift sind, aber super stabil laufen. Zudem ist die Programmierung ausschließlich auf meine Bedürfnisse ausgelegt (kann aber sicherlich schnell erweitert werden). Über Anmerkungen in den Kommentaren freue ich mich daher besonders.

Einbindung in FHEM

Als erstes habe ich – neben der Kopplung an die eigentliche App – die Hue-Bridge in FHEM konfiguriert. Die Einstellungen wurden nach dem Betätigen der „Save“-Funktion von FHEM in die Konfiguration geschrieben. So ist es nun möglich die Lampen entsprechend meiner definierten Aktionen an- bzw. auszuschalten. So weit so gut… und ein erster Schritt zum Ambilight.

Einbindung in Enigma2 (VU+ Solo2)

Da ich einen Sat-Receiver (VU+ Solo2) besitze, der auf Enigma2 basiert, wollte ich herausfinden, ob und wie sich die Hue-Lampen damit steuern lassen. Es gibt verschiedene Ansätze wie z. B. BobLight oder KarateLight, die in Verbindung mit einem zusätzlichen Microcontroller (teilweise auch einem Arduino oder RaspberryPi) ein Ambilight, dass hinter dem Fernseher angebracht wird, ermöglichen.

Wer XBMC nutzt, der kann das PlugIn script.xbmc.hue.ambilight verwenden. Erste Tests haben zwar eine generelle Funktionalität demonstriert, aber sowohl die VU+ Solo2 als auch mein AppleTV und Amazon FireTV waren nicht in der Lage ein ruckelfreies HD-Bild abzuspielen solange das PlugIn aktiv war. Zudem möchte ich auch ein Ambilight beim TV-Live-Bild erzeugen und nicht nur beim Abspielen von Filmen.

Mein Setup besteht leider nur aus zwei Lampen, die den Raum beleuchten sollen. Eine Lampe steht links hinter unserer großen Couch, die andere rechts. So lassen sich auf beiden Seiten unterschiedliche Farbszenen realisieren.

Die Grundüberlegung ist einfach:

Sat-Receiver –> PlugIn –> Hue-Bridge –> Hue-Lampe

Leider gibt es aber kein PlugIn, dass die Hue-Bridge direkt ansteuern kann, so dass dieses Setup leicht verändert werden muss. In einem Dreambox-Forum bin ich auf einen Beitrag gestoßen, der eine Anbindung an das Philips Hue-Derivat „Mi-Light“ beschreibt. Dieser setzt das PlugIn Boblight für Enigma2-Receiver ein und sendet die Ausgabe des Plugins an ein Python-Script.

Das neue Setup sieht somit wie folgt aus:

Sat-Receiver –> Boblight –> Python-Script –> Hue-Bridge –> Hue-Lampe

Installation von Boblight

Die Installation von Boblight ist sehr leicht.

enigma2-plugin-extensions-boblight-enigma2_0.8r5_mips32el.ipk

Anmerkung: Der Original-Server ist leider down. Es empfiehlt sich die Version 0.8r5 zu nehmen, da diese stabiler laufen soll.

Konfigurationsdatei erstellen

Damit Boblight funktioniert, muss eine Konfigurationsdatei erstellt werden (/etc/boblight.conf ).



[global]

[device]
name ambilight
output python /usr/dk/dkhue.py
channels 6
type popen
interval 200000
debug off

[color]
name red
rgb FF0000

[color]
name green
rgb 00FF00

[color]
name blue
rgb 0000FF

[light]
name AL1
color red ambilight 1
color green ambilight 2
color blue ambilight 3
hscan 0 50
vscan 0 100

[light]
name AL2
color red ambilight 4
color green ambilight 5
color blue ambilight 6
hscan 50 100
vscan 0 100

Entscheidend sind hier drei Stellen:

output python /usr/dk/dkhue.py

Diese definiert die Ausgabe von Boblight an python und das Python-Script dkhue.py, dass in dem Ordner /usr/dk liegt.

channels 6

Hier legen wir die Anzahl der Kanäle fest, 2 x 3 Kanäle (RGB).

[light]

Hiermit definieren wir die zwei Lampen und über den Parameter

hscan

wird angegeben, in welchem Bildbereich der Farbwert ermittelt werden soll. In meinem Fall habe ich das Bild halbiert, also die erste Lampe 0-50, die zweite Lampe 50-100.

Wer mehr Lampen hat, der muss die Anzahl der Kanäle jeweils um 3 erhöhen und eine weitere Lampe definieren. Dabei sollte dann auch der Bildbereich über hscan und vscan festgelegt werden.

Vorbereitung der Hue-Bridge

Als nächstes sollte die Hue-Bridge zur Verwendung der API-Schnittestelle vorbereitet werden. Diese wird generell wie folgt angesteuert:

http://meine.ip/api

gefolgt von einem Userkey, den es zu erstellen gilt.

Wer die Konfiguration in FHEM bereits vorgenommen hat, der kann auf diesen Key zurückgreifen. Alternativ könnt ihr einen neuen Key erzeugen. Eine ausführliche Beschreibung findet ihr auf der Herstellerseite von Philips. Das wichtigste in diesem Registrierungsprozess ist das Drücken des Connect-Buttons an der Bridge nachdem man den Post-Request gesendet hat.



Mittels POST die folgende URL ansprechen
http://192.168.xx.xx/api

und den folgenden Inhalt übertragen:
{"devicetype": "Vu", "username": "1234567890"}

Wir müssen nun den Link-Button auf der Hue-Bridge drücken, um in den Pairing-Modus zu wechseln.
Wenn wir nun nochmals den Api-Aufruf starten, dann sollte ein "Success" zurückkommen.

Mit dem Key "1234567890", welchen wir oben angegeben haben (frei wählbar) können wir nun die API aufrufen

Die Steuerungsdatei dkhue.py
Um die Hue-Lampen steuern zu können benötigt man entweder HLS-Werte oder aber XY-Farbkoordinaten (CIE 1931 Farbspektrum für Hue). In diesem Stackoverflow-Beitrag und auf dieser PhilipsHueSDK-Seite wird die Funktionsweise näher erklärt.

Download dkhue.py

Meine Steuerungsdatei sieht wie folgt aus (Debugging-Zeilen wurden entfernt):


import sys
import colorsys
import time
import json
import math
import httplib

def popen():
	spidev = file('/usr/dk/aufruf.log', "wb")
	key = "HIER API-KEY EINGEBEN"
	ip = "HIER EURE IP EINGEBEN"
	url = '/api/' + key + '/lights/'
	lurl = url + '1/state'
	rurl = url + '2/state'

	while True:
		eingabe = sys.stdin.readline()

		if len(eingabe)>0:

		# Get Input
		lr,lg,lb,rr,rg,rb,x = eingabe.split(' ')

		lr = float(lr)
		lg = float(lg)
		lb = float(lb)
		rr = float(rr)
		rg = float(rg)
		rb = float(rb)

		# Make RED more vivid
		if (lr > 0.04045):
			lr = float( math.pow((lr + 0.055) / (1.0 + 0.055), 2.4) )
		else:
			lr = float(lr / 12.92)

		if (rr > 0.04045):
			rr = float( math.pow((rr + 0.055) / (1.0 + 0.055), 2.4))
		else:
			rr = float(rr / 12.92)

		# Make GREEN more vivid
		if (lg > 0.04045):
			lg = float( math.pow((lg + 0.055) / (1.0 + 0.055), 2.4) )
		else:
			lg = float(lg / 12.92)

		if (rg > 0.04045):
			rg = float( math.pow((rg + 0.055) / (1.0 + 0.055), 2.4))
		else:
			rg = float(rg / 12.92)

		# Make BLUE more vivid
		if (lb > 0.04045):
			lb = float( math.pow((lb + 0.055) / (1.0 + 0.055), 2.4) )
		else:
			lb = float(lb / 12.92)

		if (rb > 0.04045):
			rb = float( math.pow((rb + 0.055) / (1.0 + 0.055), 2.4))
		else:
			rb = float(rb / 12.92)

		# Calculate Luminance
		h,l,s = colorsys.rgb_to_hls(lr,lg,lb)
		l = round(255 * l)
		l = 100 + l
		l = max(2,int(round(l)))

		if (l >=255):
			l = 254

		if (l<1):
			l = 1

		lxx = lr * 0.649926 + lg * 0.103455 + lb * 0.197109
		lyy = lr * 0.234327 + lg * 0.743075 + lb * 0.022598
		lzz = lr * 0.0000000 + lg * 0.053077 + lb * 1.035763
		lsum = lxx + lyy + lzz

		if (lsum > 0):
			lx = lxx / lsum
			ly = lyy / lsum
		else:
			lx = 0
			ly = 0

		rxx = rr * 0.649926 + rg * 0.103455 + rb * 0.197109
		ryy = rr * 0.234327 + rg * 0.743075 + rb * 0.022598
		rzz = rr * 0.0000000 + rg * 0.053077 + rb * 1.035763
		rsum = rxx+ryy+rzz

		if (rsum > 0):
			rx = rxx / rsum
			ry = ryy / rsum
		else:
			rx = 0
			ry = 0

		lon = True
		ron = True

		if (rx < 0.21 and ry < 0.21):
			l = 1
			ron = False

		if (lx < 0.21 and ly < 0.21):
			l = 1
			lon = False

		lparams = {'xy': [lx, ly], 'colormode': 'xy', 'bri': l, 'on': lon}
		rparams = {'xy': [rx, ry], 'colormode': 'xy', 'bri': l, 'on': ron}

		connection = httplib.HTTPConnection(ip, timeout=10)

		connection.request('PUT', lurl, json.dumps(lparams))
		response = connection.getresponse()

		connection.request('PUT', rurl, json.dumps(rparams))
		response = connection.getresponse()

		connection.close()
	else:
		break

import time
time.sleep(7)
popen()

Anmerkung: Bitte auf die korrekte Anordnung der Tabs achten, sonst läuft das Script unter Python nicht.

Die Datei gibt es auch als Download dkhue.py.

Was passiert:

Boblight unterteilt das Bild in zwei Segmente (links und rechts) und analysiert die RGB-Farbwerte. Diese werden an das Script weitergeleitet und entsprechend in XY-Koordinaten umgerechnet. Anschließend werden die Werte an die Hue-Bridge via HTTP-Put übermittelt.

Das System läuft bei mir stabil. Ich bin mit den Farben aber noch nicht komplett einverstanden. Ich werde auch noch versuchen die Helligkeit zu berücksichtigen.

Schreibt wie ihr euer Ambilight realisiert habt oder welche Farbanpassungen euch am besten gefallen.