Hier mal ein Beispiel zur Ansteuerung von VLC mit linknx. Im Einsatz habe ich einen ähnlichen linknx-Code der ein "Radio" in der Küche und im Bad realisiert.
Hardware bei mir:
Software (ebenfalls bei mir):
Die Regeln sind noch nicht bis ins Detail getestet, da dieser Code für mich als so etwas wie der Einstieg in die LUA-Programmierung diente. Aber bevor der Code in den Tiefen meines Computers verschwindet, dachte ich mir kann ich es auch hier Posten, weil es vielleicht jemand gebrauchen kann, gerade weil es wenig Beispiele für linknx gibt...
Funktionsweise:
Voraussetzung ist ein SSH-Zugriff mit einer Authentifizierung über Public-Keys ohne Passphrase (wenn linknx und VLC auf dem selben Rechner laufen, kann man ssh natürlich auch in den rules rausnehmen).
Eine Anleitung zum Einrichten dieses SSH-Zugriffs unter Ubuntu finde man z.B. hier.
Ablauf der Steuerung:
Hinweis:
Da ich noch nicht so lange linKNX verwende und LUA kenne ich gerade mal zwei Tage, wäre es schön, wenn ihr mir ein wenig Feedback zur Realsierung bzw. Verbesserungsvorschläge gebt.
Folgende GAs bzw. Variablen werden in <Objects> benötigt, wobei die Portnummern 6010 und 8010 nur einmal vorkommen dürfen, die Variablen/Parameter müssen entsprechend angepasst werden:
Folgender Eintrag wird in <services> benötigt, wobei die IP-Adresse und der Port die selben sind wie in den Variablen unter <objects> (RC-Port-Nummer):
Und die Regeln in <rules>:
Hardware bei mir:
- linknx läuft auf einem Wiregate
- Ein Linux-Server mit (mehreren) Soundkarten (darauf läuft VLC)
- Ein 1HE Verstärker im Serverschrank mit Lautsprechern in den Räumen
- Als Bedienteil dient ein Denro One in den Räumen
Software (ebenfalls bei mir):
- linknx 0.0.1.30 mit LUA-Unterstützung
- VLC 2.xx bei mir die Version von Ubuntu 12.04 LTE Server
Die Regeln sind noch nicht bis ins Detail getestet, da dieser Code für mich als so etwas wie der Einstieg in die LUA-Programmierung diente. Aber bevor der Code in den Tiefen meines Computers verschwindet, dachte ich mir kann ich es auch hier Posten, weil es vielleicht jemand gebrauchen kann, gerade weil es wenig Beispiele für linknx gibt...
Funktionsweise:
Voraussetzung ist ein SSH-Zugriff mit einer Authentifizierung über Public-Keys ohne Passphrase (wenn linknx und VLC auf dem selben Rechner laufen, kann man ssh natürlich auch in den rules rausnehmen).
Eine Anleitung zum Einrichten dieses SSH-Zugriffs unter Ubuntu finde man z.B. hier.
Ablauf der Steuerung:
- Wenn ein Wert der GA Play von linknx "empfangen" wird, dann wird per SSH auf dem Server eine VLC Instanz gestartet oder wenn VLC bereits läuft mittels kill beendet. Dies habe ich so gemacht, damit beim Beenden immer ein sauberer Start möglich ist, auch wenn VLC mal abstürzt (VLC ist halt kein mpd
). Die 1 für Play und 0 für Stopp werte ich in den Rules nicht so aus, da der Denro hier nicht sauber arbeitet. Das kann natürlich jeder selbst anpassen, im Bad wird bei mir VLC z.B. über den Präsenzmelder gestartet und beendet.
- Wenn VLC gestartet wird, dann lädt die angegebenen Playlist (bei mir mit verschiedenen Internetstreams) und der erste Eintrag abgespielt.
- Die Steuerung von VLC geschieht dann z.B. mit einer 1 bzw. 0 der GA Vor-Zurück, um ein Stream vor bzw. zurück zuspringen.
- Da ich bisher nur Internetstreams höre, habe ich Pause weggelassen (der Denro hat auch keine Pause-Taste), sondern Beende und Starte VLC immer neu.
- Ein Bearbeiten der Playlist habe ich nicht vorgesehen, dafür kann das Webinterface unter http://xxx.xxx.xxx.xxxx:8010 oder z.B. eine entsprechende iOS oder Android App genutzt werden.
Hinweis:
- Der folgende Code wird für jeden Raum einmal benötigt.
Wird VLC für mehrere Räume benötigt, können mit der "Suchen und Ersetzen"-Funktion eines Texteditors die Begriffe "raum" und "Raum" z.B. durch den Namen des jeweiligen Raumes ersetzt (z.B. essen und Essen oder kueche und Kueche) und dann der "modifizierte" Code in die linknx.xml an den richtigen Stellen einfügt werden. - Weitere Befehle (z.B. Fast Forward usw.) können einfach integriert werden, die Kommandos die das RC-Interface von VLC kennt können mit help angezeigt werden. Die Befehle müssen dann als ASCII-Hexadezimal-Werte mit einem abschließenden CR bzw. "\n" (Hex: 13) eingefügt werden.
Da ich noch nicht so lange linKNX verwende und LUA kenne ich gerade mal zwei Tage, wäre es schön, wenn ihr mir ein wenig Feedback zur Realsierung bzw. Verbesserungsvorschläge gebt.
Folgende GAs bzw. Variablen werden in <Objects> benötigt, wobei die Portnummern 6010 und 8010 nur einmal vorkommen dürfen, die Variablen/Parameter müssen entsprechend angepasst werden:
Code:
<!-- ################################################################################################################################# ## Objekte Radio Raum xyz ## ################################################################################################################################# --> <object type="1.001" id="raum_verstaerker_ein-aus" gad="x/x/x" init="persist" log="true">Verstaerker</object> <object type="5.001" id="raum_lautstaerke" gad="x/x/23" init="persist" flags="cwtus" log="true">Lautstaerke</object> <object type="5.001" id="raum_lautstaerke_status" gad="x/x/x" flags="cwtus" log="true">Lautstaerke Status</object> <object type="1.001" id="raum_play" gad="x/x/x" flags="cwtus" log="true">Play</object> <object type="1.001" id="raum_pause" gad="x/x/x" flags="cwtus" log="true">Pause</object> <object type="1.001" id="raum_play_status" gad="x/x/x" init="persist" flags="cwtus" log="true">Play Status</object> <object type="1.001" id="raum_mute" gad="x/x/x" flags="cwtus" init="persist" log="true">Mute</object> <object type="1.001" id="raum_vor-zurueck" gad="x/x/x" flags="cwtus" log="true">Vor-Zurueck</object> <object type="16.001" id="raum_title" gad="x/x/x" init="persist" log="true">Title</object> <!-- <object type="1.001" id="raum_rewind" gad="x/x/x" log="true">Zurueckspulen</object> <object type="1.001" id="raum_fastforward" gad="x/x/x" log="true">Schnellervorlauf</object>--> <!-- ## Parameter von VLC - Variablen--> <object type="28.001" id="raum_vlc_ip" init="xxx.xxx.xxx.xxx">IP-Adresse von VLC</object> <object type="28.001" id="raum_vlc_port_rc" init="6010">Port des VLC-RC-Interface</object> <object type="28.001" id="raum_vlc_port_web" init="8010">Port des VLC-Web-Interface</object> <object type="28.001" id="raum_vlc_alsa_device" init="hw:0,0">VLC Alsa Soundkarte</object> <object type="5.001" id="raum_vlc_default_volume" init="50">Einschaltlautstärke</object> <object type="5.001" id="raum_vlc_mute_volume" init="10">Mute-Lautstärke</object> <object type="28.001" id="raum_vlc_playlist" init="/Pfad/zur/Playlist">Playlist zum Abspielen</object> <object type="16.001" id="raum_vlc_room" init="Küche">Identifizierung des VLC</object> <!-- VLC Extra Parameter Equalizer mit folgenden moegliche Voreinstellungen: flat, classical, club, dance, fullbass, fullbasstreble, fulltreble, headphones, largehall, live, party, pop, reggae, rock, ska, soft, softrock, techno --> <object type="28.001" id="raum_vlc_options" init="--equalizer-preset largehall">VLC extra Options</object> <!-- SSH Einstellungen --> <object type="28.001" id="raum_vlc_port_ssh" init="22">SSH-Port</object> <object type="28.001" id="raum_vlc_user_ssh" init="xxxNamexxx">Login Benutzername</object> <!-- ## Variablen Ende -->
Code:
<ioports> <ioport id="raum.vlc" type="tcp" host="xxx.xxx.xxx.xxx" port="6010" permanent="true" /> </ioports>
Code:
<!-- ################################################################################################################################# ## Rules VLC Raum xyz ## ################################################################################################################################# --> <rule id="VLC_Raum_ein"> <condition type="and"> <condition type="object" id="raum_play" trigger="true" /> <condition type="object" id="raum_play_status" value="off" /> </condition> <actionlist type="if-true"> <action type="script"> cmd = [[echo 'is_playing' | nc -w 1 ']]..obj("raum_vlc_ip")..[[' ']]..obj("raum_vlc_port_rc")..[[' | sed -n '/> [0|1]/p' | sed 's/>\s//;s/.$//' | tr -d '\n\r']]; handle = io.popen(cmd); result = handle:read("*a"); handle:close(); if result ~= "1" then volume = math.floor(obj("raum_vlc_default_volume") * 255 / 100); cmd = [[ssh ]]..obj("raum_vlc_user_ssh")..[[@]]..obj("raum_vlc_ip")..[[ -p]]..obj("raum_vlc_port_ssh")..[[ "vlc --intf luarc --lua-config \"cli={host='*:]]..obj("raum_vlc_port_rc")..[[', welcome=']]..obj("raum_vlc_room")..[[', flatplaylist=1}\" --novideo --extraintf http --http-port ]]..obj("raum_vlc_port_web")..[[ --aout alsa --alsa-audio-device ]]..obj("raum_vlc_alsa_device")..[[ --volume ]]..volume..[[ --loop ]]..obj("raum_vlc_options")..[[ ]]..obj("raum_vlc_playlist")..[[ >/dev/null 2>]]..'\0381 \038"'; os.execute(cmd); end; set("raum_play_status", "on"); </action> </actionlist> </rule> <rule id="VLC_Raum_aus"> <condition type="and"> <condition type="object" id="raum_play" trigger="true" /> <condition type="object" id="raum_play_status" value="on" /> </condition> <actionlist type="if-true"> <action type="script"> cmd = [[ssh ]]..obj("raum_vlc_user_ssh")..[[@]]..obj("raum_vlc_ip")..[[ -p]]..obj("raum_vlc_port_ssh")..[[ "kill \$(ps x | grep vlc | grep ']]..obj("raum_vlc_port_rc")..[[' | sed 's# ? .*##')"]]; os.execute(cmd); set("raum_play_status", "off"); </action> </actionlist> </rule> <rule id="VLC_Raum_Lautstaerke"> <condition type="object" id="raum_lautstaerke" trigger="true" /> <actionlist type="if-true"> <action type="script"> cmd = "volume "..math.floor(obj("raum_lautstaerke") * 255 / 100).."\n\r"; iosend("Raum.vlc", cmd); set("raum_lautstaerke_status", obj("raum_lautstaerke")); </action> </actionlist> </rule> <rule id="VLC_Raum_Pause"> <condition type="object" id="raum_pause" trigger="true" /> <actionlist type="if-true"> <action type="ioport-tx" ioport="Raum.vlc" hex="true" data="70617573650d0a" /> <action type="set-value" id="raum_play_status" value="on" /> </actionlist> </rule>--> <rule id="VLC_Raum_Mute"> <condition type="object" id="raum_mute" trigger="true" /> <actionlist type="if-true"> <action type="script"> cmd = "volume "..math.floor(obj("raum_vlc_mute_volume") * 255 / 100).."\n\r"; iosend("Raum.vlc", cmd); set("raum_lautstaerke_status", obj("raum_vlc_mute_volume")); </action> </actionlist> </rule> <rule id="VLC_Raum_Vor-Zurueck"> <condition type="object" id="raum_vor-zurueck" value="on" trigger="true" /> <actionlist type="if-true"> <action type="ioport-tx" ioport="Raum.vlc" hex="true" data="6e6578740d0a" /> </actionlist> <actionlist type="if-false"> <action type="ioport-tx" ioport="Raum.vlc" hex="true" data="707265760d0a" /> </actionlist> </rule> <rule id="VLC_Raum_Get_Title"> <condition type="and"> <condition type="object" id="raum_play_status" value="on" trigger="true" /> <!-- Weitere Bedingungen ergaenzen z.B. ein regelmaessiges Abfragen --> </condition> <actionlist type="if-true"> <action type="script"> cmd = [[echo 'get_title' | nc -w 1 ']]..obj("raum_vlc_ip")..[[' ']]..obj("raum_vlc_port_rc")..[[' | sed -n '/>\s.*/p' | sed 's/>\s//;s/.$//;' | tr -d '\n\r' | cut -c1-14]]; handle = io.popen(cmd); result = handle:read("*a"); handle:close(); set("raum_title", result); </action> </actionlist> </rule>
Kommentar