Intelligente Lichtsteuerung mit XBMC/kodi für 3D Filme

Begonnen von Enlightning Man, 18 Januar 2015, 18:12:23

Vorheriges Thema - Nächstes Thema

Enlightning Man

Hallo zusammen,
ich möchte (wenig einfallsreich :) ) die Lichter in meinem Wohnzimmer in Abhängigkeit vom durch Kodi wiedergegebenen Inhalt steuern.


Hinweis: Ich bin neu hier, sollte dieser Beitrag im falschen Forum sein, bitte einfach verschieben.


Ich will dabei etwas über das grundlegende Beispiel aus dem Wiki hinausgehen.

Meine Anforderung:

  • Licht soll nur bei Wiedergabe von 3D Filmen komplett ausgeschaltet werden (stört bei Active Shutter Brillen). Bei 2D Filmen soll erstmal nichts passieren.
  • Beim pausieren oder stoppen soll das Licht auf den vorherigen Wert eingestellt werden. Heißt: Wenn das Licht beim Starten des Films garnicht angeschaltet war soll es auch nicht angehen und falls es an war, soll es auf denselben Wert gedimmt wie vor Filmstart.

Meine Konfiguration:

  • wz_xbmc als definiertes XBMC-Modul
  • wz_dimmer_tisch als Homematic Unterputzdimmer HM-LC-Dim1TPBU-FM
  • Yamaha AVR RX-V575 ist definiert, bietet aber im Event Log derzeit keine Infos, die ich für hilfreich erachte.
  • Samsung Smart TV von 2012. Bei dem sollte man denken der hat hilfreiche Infos, Samsung scheint das aber so einzuschränken, dass der nichts sinnvolles und erst recht nichts verlässliches sendet.

Mein aktuelles Skript:

wz_xbmc:playStatus.* {
  my $media = ReadingsVal("wz_xbmc","currentMedia","none");
  my $isPlaying = ReadingsVal("wz_xbmc","playStatus","n/a") eq "playing";
  Log 3, "Wiedergegebene Datei: " . $media . " isPlaying: " . $isPlaying;
  my $pos = index($media, "3D");
  my $is3d = $pos > 0;
  if ($is3d && $isPlaying) {
     Log 3, $media . " ist 3D!";
     my $currentRunTime = ReadingsVal("wz_xbmc","time","01:00:00.000");
     my $h = substr($currentRunTime, 0,2);
     my $m = substr($currentRunTime, 3,2);
     my $s = substr($currentRunTime, 6,2);
     my $currentRuntimeInSec = $h * 3600 + $m * 60 + $s;
     Log 3, "timeInSeconds: " . $currentRuntimeInSec;
     if ($currentRuntimeInSec < 60) {
        if (Value("wz_dimmer_tisch") eq "on") {
            Log 3, "Licht ist an, schalte aus.";
            fhem("set wz_dimmer_tisch off;");
        } else {
            Log 3, "Licht ist schon aus, mache nix.";
        }
     }
  } else {
     Log 3, $media . " läuft grad nicht oder ist kein 3D";
  }
}



Die Probleme:

Problem 1: Ist die aktuelle Quelle 3D oder nicht?
Das XBMC Modul schickt keine Informationen darüber, ob eine Quelle 3D Inhalt bietet oder nicht. Auch in der XBMC RPC Definition habe ich leider keine solche Info gefunden, daher gehe ich davon aus, dass man es nicht einfach in das XBMC Modul einbauen kann. Wie oben angedeutet scheint auch das STV (Samsung Smart TV Modul) hierfür nicht hilfreich zu sein.
Ich umgehe dieses Problem derzeit so, dass ich manuell dafür sorge, dass meine Bibliothek für 3D Filme auch Dateinamen verwendet, die den String "3D" enthalten. Das taucht als currentMedia in den Events auf.
2015-01-18 16:51:43 XBMC wz_xbmc playlist: clear
2015-01-18 16:51:43 XBMC wz_xbmc playlist: add
2015-01-18 16:51:46 XBMC wz_xbmc playStatus: playing
2015-01-18 16:51:46 XBMC wz_xbmc type: movie
2015-01-18 16:51:46 XBMC wz_xbmc year: 2009
2015-01-18 16:51:46 XBMC wz_xbmc currentOriginaltitle: Movie001
2015-01-18 16:51:46 XBMC wz_xbmc currentTitle: Movie001
2015-01-18 16:51:46 XBMC wz_xbmc label: Movie001
2015-01-18 16:51:46 XBMC wz_xbmc currentMedia: /mnt/Movies/Movie001/Movie001-3D.mkv
2015-01-18 16:51:46 XBMC wz_xbmc movieid: 313
2015-01-18 16:51:46 XBMC wz_xbmc time: 00:00:00.983
2015-01-18 16:51:46 XBMC wz_xbmc shuffle: off
2015-01-18 16:51:46 XBMC wz_xbmc repeat: off
2015-01-18 16:51:46 XBMC wz_xbmc totaltime: 01:40:11.776
2015-01-18 16:51:46 XBMC wz_xbmc partymode: off
2015-01-18 16:51:46 XBMC wz_xbmc playStatus: playing
2015-01-18 16:51:46 XBMC wz_xbmc speed: 1


In meinem Skript (siehe oben) checke ich also, ob currentMedia Variable "3D" als String enthält.
Das funktioniert für diesen Fall, ich finde es aber nicht sonderlich elegant.
Hat da vielleicht jemand einen anderen Vorschlag wie man feststellen kann, ob eine Datei 3D ist oder nicht?

Problem 2: Wie kann man den vorherigen Lichtzustand wiederherstellen?
Das Beispiel für Lichtschaltung im Wiki schaltet das Licht im Wohnzimmer an, sobald man die Wiedergabe pausiert oder abbricht. Das tut es allerdings unabhängig vom vorherigen Zustand. Also wenn ich tagsüber ein 3D Video schaue und es ist hell im Wohnzimmer, geht sobald ich das Video beende das Licht an. Unschön...

Mein erster Ansatz war, das Ändern der Lichtverhältnisse nur in der ersten Minute der Videowiedergabe zu machen (siehe if ($currentRuntimeInSec < 60) Skript oben). Das verhindert, dass das Licht nach dieser Zeit geschaltet wird, aber es erreicht halt nicht, den vorherigen Zustand wiederherzustellen.

Wie mache ich das genau?
Ich müsste mir vermutlich den Zustand bevor ich das Licht deaktiviere irgendwo merken. Geht das irgendwie in einer globalen Variablen? Ich hab irgendwo gelesen, dass man sowas auch als "reading" im Device selbst setzen kann. Da wollte ich fragen, was hier die empfohlene Herangehensweise ist.

Schöne Grüße,
EM

Rince

Zu 1. fällt mir grad auch nix ein. Die Frage ist, ob Kodi das überhaupt verrät. Wenn ja, müßte vbs das einbauen, damit es auswerbar wird.
Das mit den Dateinamen wäre jetzt auch mein Workaround gewesen.
Das einzige Problem ist dann, wenn du einen 3D Film dennoch nur in 2D ansiehst.

Zu 2.
Definiere dir eine Lightscene.
In die steckst du die betroffenen Lichter. Dann kannst du für deine Lightscene verschiedene Scenes speichern. Alles an, alles aus, temporär und so.
Wenn das entsprechende Event kommt, speichere einfach das aktuelle Setting unter temporär. Dann kannst du die Lichter ausschalten lassen. Am Ende kannst du einfach die temporär Scene wieder laden.
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)

vbs

Also mir ist in Kodi keine API bekannt, die das direkt ausgeben würde ob es 3D ist. Aber man könnte die Methode wie kodi anhand des Dateinamens raus findet, ob es 3D ist, nachbauen: http://kodi.wiki/view/3D
Also im Prinzip ähnlich wie du es schon gemacht hast.

Enlightning Man

@vbs: Ok, hab ich auch so verstanden. Kann auch erstmal mit meinem Ansatz leben. Sieht ja so aus, als würde Kodi da weiterentwickelt.

@Rince:
Danke, LightScene sieht ziemlich genau nach dem aus, was ich gesucht habe. Allerdings habe ich da noch ein Paar kleinere Probleme...

Code mit LightScene:

wz_xbmc:playStatus.* {
  my $media = ReadingsVal("wz_xbmc","currentMedia","none");
  my $isPlaying = ReadingsVal("wz_xbmc","playStatus","n/a") eq "playing";
  my $pos = index($media, "3D");
  my $is3d = $pos > 0;
  if ($is3d && $isPlaying) {
     my $currentRunTime = ReadingsVal("wz_xbmc","time","01:00:00.000");
     my $h = substr($currentRunTime, 0,2);
     my $m = substr($currentRunTime, 3,2);
     my $s = substr($currentRunTime, 6,2);
     my $currentRuntimeInSec = $h * 3600 + $m * 60 + $s;
     if ($currentRuntimeInSec > 0) {
        if (ReadingsVal("wz_dimmer_tisch", "pct", 0) > 0) {
            Log 3, "Licht ist an, speichere kino_licht Szene und dimme 3s aus.";
            fhem("set kino_licht save tmp_pre_movie_state;");
            fhem("set kino_licht scene 3d_movie;");
        }
     }
  } elsif ($is3d) {
     Log 3, "Der Film ist pausiert oder zu Ende, schalte Licht auf 60%.";
     fhem("set kino_licht scene tmp_pre_movie_state;");
     fhem("set kino_licht remove tmp_pre_movie_state;");
  }
}


Ich habe mir hierfür eine LightScene kino_licht definiert und lege on-the-fly den Zustand tmp_pre_movie_state bevor ich auf den Zustand 3d_movie (gedimmte Lampen) wechsle. Sobald der Film pausiert wird, wird zurück auf scene tmp_pre_movie_state geswitched und die scene wird danach direkt wieder gelöscht.

Soweit so gut... Aber:

Problem A - LightScene scheint zu spät zu speichern:
Die Abfolge der Befehle

fhem("set kino_licht save tmp_pre_movie_state;");
fhem("set kino_licht scene 3d_movie;");

legt korrekt einen neuen Scene Zustand an, allerdings wird bei mir für die Lampe in der Scene immer der ausgeschaltete Zustand in der Scene gespeichert und nicht der aktuelle.
Verwende ich

fhem("set kino_licht save tmp_pre_movie_state;");
fhem("set wz_dimmer_tisch 0 0 3;");

dann klappt es und die tmp_pre_movie_state hat den korrekten Zustand. Das hört sich für mich verdächtig nach einer Race Condition an, dass das speichern erst die Daten abfragt, nachdem die Scene schon gewechselt hat oder so. Kann das sein? Muss ich da irgendwie mit Sleep arbeiten?

Problem B - Kann man die aktuell aktive Scene abfragen?
Derzeit frage ich ab ob eine bestimmte Lampe an ist oder nicht um zu entscheiden, ob ich in die 3d_movie LightScene switchen soll. Schöner wäre, wenn ich abfragen könnte, welche scene die gerade aktive ist. Habe diese beiden Varianten erfolglos ausprobiert:

Log 3, "Current light scene of kino_licht: " . ReadingsVal("kino_licht", "scene", "n/a");
Log 3, "Current light scene of kino_licht: " . fhem("get kino_licht scene;");

Ist denke ich ein einfacher Denkfehler meinerseits, wie man an diese Info rankommt.

Problemchen C - Der Dimmvorgang ist jetzt sehr schnell
Das ist ein kleines Problem, aber ich hatte den Dimmvorgang zuvor auf 3 Sekunden eingestellt und das wechseln der Scenes macht das jetzt in der schnelleren Default Geschwindigkeit des Dimmers. Das is natürlich nicht mehr so eindrucksvoll wie vorher. Kann man das irgendwie konfigurieren? Vielleicht via setcmd in der LightScene?  Die Commandref ist leider nicht so wirklich intuitiv verständlich und das Wiki zu Lightscene ist noch leerer...

Danke auf jeden Fall schonmal für euer Feedback :)

vbs


Enlightning Man

Klasse.
Danke fürs einbauen, funktioniert einwandfrei.

Ich werd meine Fragen zu LightScene mal in einen neuen Thread packen weil es recht unabhängig von der initialen Fragestellung ist, und den Thread hier schließen.

Für Leute, die das hier später lesen:
Das reading in XBMC ist mittlerweile umbenannt in 3dfile.

Enlightning Man