Sonos2mqtt: Unterschied zwischen den Versionen

Aus FHEMWiki
Zur Navigation springen Zur Suche springen
(→‎Speak Befehl: Beschreibung überarbeitet)
Zeile 124: Zeile 124:
* [[Text2Speech]] im Servermodus, erzeugt mp3 Dateien im cache Verzeichnis und legt einen Link im Reading httpName ab.
* [[Text2Speech]] im Servermodus, erzeugt mp3 Dateien im cache Verzeichnis und legt einen Link im Reading httpName ab.
* Ein HTTP Server stellt die Dateien im gleichen Verzeichnis bereit
* Ein HTTP Server stellt die Dateien im gleichen Verzeichnis bereit
Wichtig ist, dass das Sonos System den Host im Link zur Datei richtig auflösen kann. Deshalb wird der Hostname und Port des Servers im Readings host des TTS Device als Name oder IP Adresse abgelegt! Dies kann entweder mit dem hier gezeigten Befehl oder vollständig manuell erfolgen.<syntaxhighlight lang="perl">
Der speak Befehl im Player Device läuft in 3 Schritten:
# mit dem TTS Gerät wird die mp3 Datei erzeugt,
# mit dem sleep wird auf die Fertigstellung gewartet,
# die Datei wird mit set Player notify volume uri abgespielt.
Für die Funktion ist wichtig, dass das Sonos System den Host im Link zur Datei richtig auflösen kann. Deshalb wird der Hostname und Port des Servers im Reading host des TTS Device als Name oder IP Adresse abgelegt! Dies kann entweder mit dem hier gezeigten Befehl oder vollständig manuell erfolgen.<syntaxhighlight lang="perl">
defmod SonosTTS Text2Speech none
defmod SonosTTS Text2Speech none
attr SonosTTS TTS_UseMP3Wrap 1
attr SonosTTS TTS_UseMP3Wrap 1
Zeile 133: Zeile 137:


defmod SonosSpeakWeb HTTPSRV cache cache SonosSpeakWeb
defmod SonosSpeakWeb HTTPSRV cache cache SonosSpeakWeb
</syntaxhighlight>Der speak Befehl erzeugt mit dem TTS Gerät die mp3 Datei, nach deren Fertigstellung wird der sonos2mqtt notify Befehl ausgeführt. Damit wird die laufende Umgebung wiederhergestellt. Wird der speak Befehl an den Gruppenmaster gesendet wird auch in der Gruppe gespielt. Wird er auf ein Mitglied einer Gruppe gesendet (nicht der Master) wird auch die Gruppe aufgetrennt und wieder hergestellt.
</syntaxhighlight>Durch den "sonos2mqtt notify" Befehl wird die laufende Umgebung wiederhergestellt.  
 
* Wird der speak Befehl an den Gruppenmaster gesendet wird die mp3 Datei in der gesamten Gruppe gespielt.  
* Wird der speak Befehl an ein Mitglied einer Gruppe gesendet (nicht den Master) wird die Gruppe aufgetrennt und später wieder hergestellt.
Die Erweiterung der setList im MQTT2 Player Device sieht wie folgt aus. Man kann den Befehl einfach bei allen Playern mit dem obigen [[Sonos2mqtt#Befehle nachr.C3.BCsten|Codeschnipsel]] nachrüsten.<syntaxhighlight lang="perl">
Die Erweiterung der setList im MQTT2 Player Device sieht wie folgt aus. Man kann den Befehl einfach bei allen Playern mit dem obigen [[Sonos2mqtt#Befehle nachr.C3.BCsten|Codeschnipsel]] nachrüsten.<syntaxhighlight lang="perl">
speak:textField { my $tts="SonosTTS";my ($cmd,$vol,$text)=split(' ', $EVENT,3);fhem("set $tts tts $text;sleep $tts:playing:.0 ;set $NAME notify $vol [$tts:httpName]")}
speak:textField { my $tts="SonosTTS";my ($cmd,$vol,$text)=split(' ', $EVENT,3);fhem("set $tts tts $text;sleep $tts:playing:.0 ;set $NAME notify $vol [$tts:httpName]")}

Version vom 13. August 2020, 22:03 Uhr

Grundeinrichtung

Die Grundeinrichtung ist bereits im Artikel MQTT2-Module - Praxisbeispiele beschrieben. Hier soll es um die praktische Verwendung und Erweiterung gehen.

Für alle Erweiterungen wird versucht vorhandene Devices in FHEM zu verwenden.

Viele Dinge werden derzeit noch entwickelt und können frei gestaltet werden - der Vorteil von generischen FHEM Devices.

Tipps zur Verwendung

Die automatische Konfiguration setzt den alias entsprechend dem Namen im Sonos vergeben. Die langen MQTT2_RINCON_ Namen sind unhandlich und schlecht lesbar. Man kann Player mit einem devspec ansprechen, das simpelste ist:

set alias=Büro play

Oder alle Player

set model=sonos2mqtt_speaker leaveGroup

Ansicht der Player

Im Template wird nur ein simples devStateIcon ausgeliefert. Dort kann man sehr viel mehr reinpacken. Hier mal die aktuelle Arbeitsvariante zum nachrüsten in der Raw Definition:

attr MQTT2_RINCON_.* devStateIcon {\
my $wpix = '250px';;\
my $groupname = ReadingsVal($name,'groupName','0');;\
my $sgroupname = (split(' ',ReadingsVal($name,'groupName','')))[0];;\
my $uuidtoname = (devspec2array('DEF='.ReadingsVal($name,'coordinatorUuid','0')))[0];;\
my $vol = ReadingsVal($name,'volume','');;\
my $img = ReadingsVal($name,'currentTrack_AlbumArtUri','');;\
my $mystate = $name eq $uuidtoname \
  ? ReadingsVal($name,'state','FEHLER') : ReadingsVal($uuidtoname,'state','');;\
my $playpic = $mystate eq 'PLAYING'\
  ? 'rc_PAUSE@red'    : $mystate eq 'PAUSED_PLAYBACK'\
  ? 'rc_PLAY@green'   : $mystate eq 'STOPPED'\
  ? 'rc_PLAY@green'   : $mystate eq 'TRANSITIONING'\
  ? 'rc_PLAY@blue'    : $mystate eq 'set_next'\
  ? 'rc_NEXT@blue'    : $mystate eq 'set_previous'\
  ? 'rc_PREVIOUS@blue': $mystate eq 'set_volumeUp'\
  ? 'rc_VOLUP@blue'   : $mystate eq 'set_volumeDown'\
  ? 'rc_VOLDOWN@blue' : $mystate eq 'set_mute'\
  ? 'rc_MUTE@blue'    : 'rc_PLAY@yellow';;\
my $mutecmd = ReadingsVal($name,'mute','0') eq 'false'?'on':'off';;\
my $mutepic = $mutecmd eq 'on'?'rc_MUTE':'rc_VOLUP';;\
my $show = 'FEHLER';;\
my $currentTrack_Artist = ReadingsVal($name,'currentTrack_Artist','FEHLER');;\
my $currentTrack_Title = ReadingsVal($name,'currentTrack_Title','FEHLER');;\
if ($currentTrack_Title =~ 'x-sonosapi-stream:'){$currentTrack_Title=''};;\
my $currentTrack = $mystate eq 'TRANSITIONING'\
  ? 'Puffern...' : $currentTrack_Artist.' - '.$currentTrack_Title;;\
my $nextTrack_Artist = ReadingsVal($name,'nextTrack_Artist','FEHLER');;\
my $nextTrack_Title = ReadingsVal($name,'nextTrack_Title','FEHLER');;\
my $nextTrack = $nextTrack_Artist.' - '.$nextTrack_Title;;\
my $previouspic = 'rc_PREVIOUS';;\
my $nextpic = 'rc_NEXT';;\
my $voldownpic = 'rc_VOLDOWN';;\
my $voluppic = 'rc_VOLUP';;\
my $leavegrouppic = 'rc_LEFT';;\
my $showlg = ReadingsVal($name,"name","0") ne $groupname ? "<a href=\"/fhem?cmd.dummy=set $name leaveGroup&XHR=1\">".FW_makeImage($leavegrouppic)."</a>" : "";;\
if (($mystate eq 'PLAYING')\
  || ($mystate eq 'TRANSITIONING' )\
  || ($mystate eq 'set_next' )\
  || ($mystate eq 'set_previous' )\
  || ($mystate eq 'set_volumeUp' )\
  || ($mystate eq 'set_volumeDown' )\
  || ($mystate eq 'set_mute' )) { \
    my $shownp = ReadingsVal($name,'name','') eq $sgroupname \
    ? "<a href=\"/fhem?cmd.dummy=set $name previous&XHR=1\">".FW_makeImage($previouspic)."</a>\
       <a href=\"/fhem?cmd.dummy=set $name next&XHR=1\">".FW_makeImage($nextpic)."</a>" : "";;  \
    $show = "$showlg <a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>\
    <a href=\"/fhem?cmd.dummy=set $name volumeDown&XHR=1\">".FW_makeImage($voldownpic)."</a>\
    $shownp\
    <a href=\"/fhem?cmd.dummy=set $name volumeUp&XHR=1\">".FW_makeImage($voluppic)."</a>\
    &nbsp;;&nbsp;;&nbsp;;&nbsp;;\
    <a href=\"/fhem?cmd.dummy=set $name mute $mutecmd&XHR=1\">".FW_makeImage($mutepic)."</a><br>";;\
  \
    if (ReadingsVal($name,'name','') eq $sgroupname) {\
      $show = ReadingsVal($name,'currentTrack_TrackUri','') =~ 'spdif'\
      ? 'TV': ReadingsVal($name,'enqueuedMetadata_UpnpClass','FEHLER') ne 'object.item.audioItem.audioBroadcast'\
      ? "$show<marquee style='width: $wpix'>Aktueller Track: $currentTrack<br>Nächster Track: $nextTrack</marquee>"\
      : "$show<marquee style='width: $wpix'>Radio: $currentTrack</marquee>"\
    }\
    elsif (ReadingsVal($name,'name','') ne $groupname) {\
      $show = "$show Master: $sgroupname"}\
    }\
    else {\
      $show = $name eq $uuidtoname\
      ? "$showlg <a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>"\
      : "$showlg <a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a><br>Master: $sgroupname"\
    }\
  "<div>\
   <table>\
     <tr>\
       <td><div style='display: inline-block;; margin-right: 5px;; border: 1px solid lightgray;;\
              height: 4.00em;; width: 4.00em;; background-image: url($img);; background-size: contain;;'></div></td>\
       <td>$show</td>\
     </tr>\
   </table>\
   </div>"\
}

Befehle nachrüsten

Um Befehle nicht manuell in die setList / readingList Einträge jedes Players machen zu müssen, wird diese Routine verwendet.

Der Code ist für die Raw Definition gedacht. Die ersten drei Zeilen sind jeweils anzupassen!

Hier im Beispiel wird der setter für den folgenden Speak Befehl eingefügt bzw. ersetzt.

{my @devlist = devspec2array('MQTT2_RINCON_.*');;\
 my $attr = 'setList';;\
 my $item = q(  speak:textField { my $tts="SonosTTS";;my ($cmd,$vol,$text)=split(' ', $EVENT,3);;fhem("set $tts tts $text;;sleep $tts:playing:.0 ;;set $NAME notify $vol [$tts:httpName]")});;\
 my ($first,$sec)=split(' ',$item,2);;\
 foreach (@devlist) {\
   my @arr = grep {$_ !~ $first} split("\n",AttrVal($_,$attr,''));;\
   push @arr,$item;;\
   my $val = join "\n",@arr;;\
   $val =~ s/;;/;;;;/g;;\
   fhem("attr $_ $attr $val")}\
 return "$attr in ".scalar(@devlist)." Definitionen modifiziert"\
}

Vorhandenen Zeilen werden ersetzt. Identifiziert wird nur der erste Teil.

Speak Befehl

Verwendet wird ein Befehl ähnlich wie in der Sonos Umgebung:

set Player speak <volume> text

Zwei zusätzliche Geräte sind notwendig:

  • Text2Speech im Servermodus, erzeugt mp3 Dateien im cache Verzeichnis und legt einen Link im Reading httpName ab.
  • Ein HTTP Server stellt die Dateien im gleichen Verzeichnis bereit

Der speak Befehl im Player Device läuft in 3 Schritten:

  1. mit dem TTS Gerät wird die mp3 Datei erzeugt,
  2. mit dem sleep wird auf die Fertigstellung gewartet,
  3. die Datei wird mit set Player notify volume uri abgespielt.

Für die Funktion ist wichtig, dass das Sonos System den Host im Link zur Datei richtig auflösen kann. Deshalb wird der Hostname und Port des Servers im Reading host des TTS Device als Name oder IP Adresse abgelegt! Dies kann entweder mit dem hier gezeigten Befehl oder vollständig manuell erfolgen.

defmod SonosTTS Text2Speech none
attr SonosTTS TTS_UseMP3Wrap 1
attr SonosTTS userReadings httpName:lastFilename.* {'http://'.ReadingsVal($name,'host','set host:port first').'/fhem/'.ReadingsVal($name,'lastFilename','')}
attr SonosTTS TTS_CacheFileDir cache
setreading SonosTTS host {(qx(hostname -s|tr -d '\n').':'.InternalVal('WEB','PORT','8083'))}
#setreading SonosTTS host {((split(' ', qx(hostname -I)))[0].':'.InternalVal('WEB','PORT','8083'))}

defmod SonosSpeakWeb HTTPSRV cache cache SonosSpeakWeb

Durch den "sonos2mqtt notify" Befehl wird die laufende Umgebung wiederhergestellt.

  • Wird der speak Befehl an den Gruppenmaster gesendet wird die mp3 Datei in der gesamten Gruppe gespielt.
  • Wird der speak Befehl an ein Mitglied einer Gruppe gesendet (nicht den Master) wird die Gruppe aufgetrennt und später wieder hergestellt.

Die Erweiterung der setList im MQTT2 Player Device sieht wie folgt aus. Man kann den Befehl einfach bei allen Playern mit dem obigen Codeschnipsel nachrüsten.

speak:textField { my $tts="SonosTTS";my ($cmd,$vol,$text)=split(' ', $EVENT,3);fhem("set $tts tts $text;sleep $tts:playing:.0 ;set $NAME notify $vol [$tts:httpName]")}

Will man keine laufenden Sendung unterbrechen sondern einfach eine Ansage machen und danach etwas starten, kann man so vorgehen:

set SonosTTS tts Hier steht die Ansage;sleep SonosTTS:playing:.0 ; set alias=PlayerAlias playUri [SonosTTS:httpName]

Generell kann man feste mp3 Dateien (Klingeltöne, Klänge usw.) auch im cache Verzeichnis ablegen und direkt mit dem Link starten. Mit set magic kann man dabei einfach Teile aus anderen Readings holen.

set alias=Büro notify 25 {('http://[SonosTTS:host]/fhem/cache/KlingelTon.mp3')}

Favoriten starten

ToDo

Radioliste durchtasten

ToDo

Dokumentationen und weiter Entwicklungen

ToDo