Sonos2mqtt - vielleicht hat jemand Lust mitzumachen

Begonnen von Otto123, 31 Mai 2020, 18:30:55

Vorheriges Thema - Nächstes Thema

Otto123

#810
Also wenn ich das einfach so mache wie in der Doku TTS beschrieben - funktioniert das OOTB :)

"mkdir ./cache/templates"
"cp /opt/fhem/cache/KlingelTon.mp3 /opt/fhem/cache/templates/"
attr SonosTTS TTS_FileMapping Klingel:KlingelTon.mp3
set alias=Arbeitszimmer speak 20 Vor der:Klingel:und danach


Was ist grundlegend anders an | und : als Trenner?

geht auch solo - also nur Klingel set alias=Arbeitszimmer speak 20 :Klingel:
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

gib mal ausversehen
Zitatattr SonosTTS TTS_FileMapping Klingel:KlingelTon:mp3
ein und bekomm das wieder raus aus dem Attribut ohne die fhem.cfg zu editieren.

die solo Variante klappt auch bei mir:

set alias=Arbeitszimmer speak 20 Vor der:Klingel:und danach

mit Text nur davor, nur danach und vor und danach nicht.

da bekomm ich einen MP3WRAP Fehler:

2020.12.19 19:41:46 3: MQTT2_DEVICE set Sonos_Wohnzimmer speak 20 bla:Vibrating:
sh: 1: mp3wrap: not found
2020.12.19 19:41:46 3: SonosTTS: MP3WRAP Fehler!, Datei wurde nicht generiert.
2020.12.19 19:41:47 3: MQTT2_DEVICE set Sonos_Wohnzimmer notify 20 http://192.168.188.26:8084/fhem/cache/eb2412cbde69699e6b043867bf023b79.mp3
2020.12.19 19:42:02 3: MQTT2_DEVICE set Sonos_Wohnzimmer speak 20 bla:Vibrating:bla
sh: 1: mp3wrap: not found
2020.12.19 19:42:02 3: SonosTTS: MP3WRAP Fehler!, Datei wurde nicht generiert.
2020.12.19 19:42:02 3: MQTT2_DEVICE set Sonos_Wohnzimmer notify 20 http://192.168.188.26:8084/fhem/cache/0234849a25042bba31e8d3dec2c003a7.mp3
2020.12.19 19:42:29 3: MQTT2_DEVICE set Sonos_Wohnzimmer speak 20 :Vibrating:bla
sh: 1: mp3wrap: not found
2020.12.19 19:42:29 3: SonosTTS: MP3WRAP Fehler!, Datei wurde nicht generiert.
2020.12.19 19:42:30 3: MQTT2_DEVICE set Sonos_Wohnzimmer notify 20 http://192.168.188.26:8084/fhem/cache/788c72e06a83285d1820e80e631f9782.mp3
2020.12.19 19:42:45 3: MQTT2_DEVICE set Sonos_Wohnzimmer speak 20 :Vibrating:
2020.12.19 19:42:45 3: MQTT2_DEVICE set Sonos_Wohnzimmer notify 20 http://192.168.188.26:8084/fhem/cache/templates/Vibrating.mp3


Ich hab auch noch nicht die ganzen Bibliotheken installiert, weil speak bisher auch so funzt, meinst du es kann daran liegen ?

Darum auch

sh: 1: mp3wrap: not found

Otto123

Ja so ist es :
ZitatTTS_UseMP3Wrap
optional: To become a liquid audio response its recommend to use the tool mp3wrap. Each downloaded audio bricks are concatinated to a single audio file to play with mplayer.
Installtion of the mp3wrap source is required.
apt-get install mp3wrap
Notice: Only available in locally instances!

Ich sollte dann wohl das hier aus dem Wiki rausnehmen
attr SonosTTS TTS_UseMP3Wrap 1
oder dazu  schreiben das man TTS Doku lesen muss :)
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

Danke.

Hab aber nur mp3wrap noch installiert, jetzt klappts.

Was von den anderen Bibliotheken bereits "vorinstalliert" ist mit OS hab ich nicht nachgeschaut.

Otto123

Ich ergänze das. Wir brauchen mp3wrap in jedem Fall. Wir wollen ja eine komplette mp3 Datei - auch bei längeren Texten.
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

kjmEjfu

Ist das aber letztlich nicht wieder was, wo wir versuchen eine Lösung nachzubauen, die es eigentlich schon gibt? Deshalb wäre ich ja noch immer ein Freund davon, wenn "einfach" das SONOS-Modul so erweitert würde, dass es sowohl native als auch mqtt bedienen kann ;-)

Aber davon unabhängig wäre es doch die Funktion SONOS_GetSpeakFile aus https://svn.fhem.de/trac/browser/trunk/fhem/FHEM/00_SONOS.pm ab Zeile 4788 und dann SONOS_CombineMP3Files (ab Zeile 4902).

Ich finde halt, wir dürfen nicht vergessen, dass es für die Sprachausgabe zwei Varianten gibt (Fhem TTS und sonos-tts-polly). Betrachten wir nur eine, gibt es hinterher Probleme mit der anderen.
Migriere derzeit zu Home Assistant

kjmEjfu

Migriere derzeit zu Home Assistant

Otto123

Hallo sonso2mqtt Liebhaber,

ich habe in Vorbereitung einer 99_mySonosUtils.pm mal noch etwas versucht die existierenden Dinge zu verifizieren und vielleicht besser zu strukturieren.

Ich habe das devStateIcon mal überarbeitet und etwas Code in userReadings ausgelagert, den Code kann man komplett in die Raw Definition fallen lassen:
# stateFormat nicht mehr nach state mappen, stateFormat auf transportState setzen
attr a:model=sonos2mqtt_speaker jsonMap volume_Master:volume mute_Master:mute
attr a:model=sonos2mqtt_speaker stateFormat transportState

# Master Name und Status isMaster und inGroup ermitteln - 
attr a:model=sonos2mqtt_speaker userReadings Master:groupName.* {(split(' ',ReadingsVal($name,'groupName','')))[0]},\
inGroup:groupName.*  {ReadingsVal($name,"name","0") ne ReadingsVal($name,'groupName','0')?1:0},\
isMaster:groupName.*  {ReadingsVal($name,'name','') eq (split(' ',ReadingsVal($name,'groupName','')))[0]?1:0},\
Input:currentTrack_TrackUri.* {my $currentTrack_TrackUri = ReadingsVal($name,'currentTrack_TrackUri','');;\
   $currentTrack_TrackUri =~ 'x-rincon-stream'\
      ? 'LineIn': $currentTrack_TrackUri =~ 'spdif'\
      ? 'TV'    : ReadingsVal($name,'enqueuedMetadata_UpnpClass','') eq 'object.item.audioItem.audioBroadcast'\
      ? 'Radio' : 'Playlist'}

# devStateIcon setzen
attr a:model=sonos2mqtt_speaker devStateIcon {\
my $wpix = '210px';;\
my $master = ReadingsVal($name,'Master',$name);;\
my $inGroup = ReadingsNum($name,'inGroup','0');;\
my $isMaster = ReadingsNum($name,'isMaster','0');;\
my $Input = ReadingsVal($name,'Input','');;\
my $cover = ReadingsVal($name,'currentTrack_AlbumArtUri','');;\
my $mutecmd = ReadingsVal($name,'mute','0') eq 'false'?'true':'false';;\
my $mystate = $isMaster ? Value($name) : Value((devspec2array('DEF='.ReadingsVal($name,'coordinatorUuid','0')))[0]);;\
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'    : 'rc_PLAY@yellow';;\
my $mutepic = $mutecmd eq 'true'?'rc_MUTE':'rc_VOLUP';;\
my $line2 = '';;\
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 $linePic = ($inGroup and !$isMaster) ? "<a href=\"/fhem?cmd.dummy=set $name leaveGroup&XHR=1\">".FW_makeImage('rc_LEFT')."</a>" : "";;\
if ($isMaster) {$linePic .= " <a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>"};;\
   $linePic .= "&nbsp;;&nbsp"\
            ."<a href=\"/fhem?cmd.dummy=set $name volumeDown&XHR=1\">".FW_makeImage('rc_VOLDOWN')."</a>"\
            ."<a href=\"/fhem?cmd.dummy=set $name previous&XHR=1\">".FW_makeImage('rc_PREVIOUS')."</a>"\
            ."<a href=\"/fhem?cmd.dummy=set $name next&XHR=1\">".FW_makeImage('rc_NEXT')."</a>"\
            ."<a href=\"/fhem?cmd.dummy=set $name volumeUp&XHR=1\">".FW_makeImage('rc_VOLUP')."</a>"\
            ."&nbsp;;&nbsp"\
            ."<a href=\"/fhem?cmd.dummy=set $name mute $mutecmd&XHR=1\">".FW_makeImage($mutepic)."</a><br>";;\
if ($isMaster and $mystate eq 'PLAYING') {\
    $line2 = $Input =~ /LineIn|TV/ \
      ? $Input : $Input eq 'Radio' \
      ? "$line2<marquee style='width: $wpix'>Radio: $currentTrack</marquee>" \
      : "$line2<marquee style='width: $wpix'>Aktueller Track: $currentTrack<br>Nächster Track: $nextTrack</marquee>"\
    } elsif ($inGroup and !$isMaster) {$line2 .= " Steuerung: $master"}\
my $style = 'display:inline-block;;margin-right:5px;;border:1px solid lightgray;;height:4.00em;;width:4.00em;;background-size:contain;;background-image:';;\
"<div><table>\
     <tr>\
       <td><div style='$style url($cover)'></div></td>\
       <td>$linePic$line2</td>\
     </tr>\
  </table></div>"\
}


Vielleicht hat ja einer Lust zu testen und mir Feedback zu geben, ich würde das dann erstmal im Wiki austauschen. Ich habe damit folgendes realisiert/verbessert:

  • der state wird nicht mehr vom transportState gesetzt, der transportState setzt jetzt direkt den STATE. Damit wird die Auswertung im devstateIcon leichter.
  • der Eingang wird erkannt: LineIn, TV, Radio, Playlist - ist noch nicht vollkommen aber ein Anfang ;)
  • Mastername, ist der Master und ist in einer Gruppe wird erkannt und damit ist der Code im devstateIcon etwas leichter lesbar
  • Die Steuer Icons werden wie folgt zusammengebastelt:

    • leaveGroup - wenn in einer Gruppe und nicht der Master
    • PlayIcon - nur wenn Master
    • leise vor zurück laut mute - jeder Player
  • Lauftext gibt es bei Radio und Playlist ansonsten steht dort der Eingang oder wo die Play Steuerung funktioniert (wenn Mitglied einer Gruppe)
Wenn mir jetzt noch einer verrät ob man die ganzen Readings irgendwie 1:1 mit einem hash und einer direkten Referenz abrufen könnte und nicht einzeln mit ReadingsVal()? :)

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Beta-User

Na ja, ReadingsVal() ist auch nur eine sub, die bestimmte hashes durchsucht...

ABER: MAn. sollte man eher nicht direkt in diesen hashes "rumsudeln" (lesend mag noch verzeihlich sein, wenn man genau weiß, was man tut), und schon gleich nicht in "usercode"...
Ich habe da irgendwo auch noch Rudi im Ohr (ich hoffe, das aus dem Gedächtnis korrekt zu rekonstruieren): Er hat mir mal erklärt, dass sonst nämlich das Risiko besteht, dass man die abgefragten (übergeordneten) Hashes erst "ins Leben ruft" und so "Speicherleichen"  erzeugt. Also wenn du sowas überhaupt weiter anvisierst(die paar Ministeps mehr...), dann möglichst nur versteckt vor dem User (und entsprechend gegen Leichengenerierung abgesichert!) in ...Utils.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Otto123

@Beta-User - überredet :)
War ja nur ne Frage: Der Code sieht so öde aus, ich dachte am Ende definiert man so eine Art Referenz und kann einfach die existierenden Readingnamen abfragen. Oder so mit einer Zeile foreach ... einfach alle Variablen anlegen
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Beta-User

 :) Kein Ding...

Was "foreach" angeht: watndat?!? (Ich fand das früher auch schick, aber immer, wenn mir jetzt eines vor die Flinte läuft, wird es erlegt und ein "for" darf stattdessen das Licht der Welt erblicken ;) ...).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

TomLee

Dachte die Laufschrift entfällt irgendwann, wenn sie weiterhin enthalten ist, hätt ich den Vorschlag scrollamount und scrolldelay zu ergänzen.

Mag sein dass das auch Browserabhängig ist (hab ich mich nicht mit beschäftigt), mir ist die zu schnell von rechts nach links geflitzt, da wird man ja verrückt.

<marquee scrollamount='1' scrolldelay='1' style='width: $wpix'>

Otto123

#822
ZitatDas <marquee> Element ist veraltet und muss bzw. soll nicht mehr verwendet werden. Obwohl manche Browser es immernoch unterstützen, ist es nicht erforderlich. Es wird davon abgeraten, dieses Tag zu benutzen, da es das schlimmste ist, was Sie ihren Besuchern antun können.
Hast Du Vorschlag anstatt Laufschrift?
Ich baue scrollamount='1' ein, dass bewirkt bei mir das gleiche - die scrolldelay='1' würde ignoriert :)
Zitatscrollamount
Definiert den Wert eines Intervalls in Pixel. Der Standardwert beträgt 6.
scrolldelay
Definiert den Intervall zwischen jeder Bewegung in Millisekunden. Der Standardwert ist 85. Merke:  Jeder Wert, der kleiner als 60 ist, wird ignoriert und der Wert 60 wird stattdessen verwendet, außer "truespeed" ist definiert.

Alles was ich als Alternative zu dem marquee Tag finde jeweils gefühlte 27 Seiten HTML/CSS/Javascript Code. Da lasse ich es im Zweifel einfach weg und es wird eben nicht alles dargestellt? 
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

ZitatHast Du Vorschlag anstatt Laufschrift?

marquee wird doch offiziell von keinem Browser mehr unterstützt, die Alternative ist ewig lang, mein Vorschlag bevor marquee ins Spiel kam war mal ($trim30) die Anzahl der anzuzeigenden Zeichen (die max. in eine Spalte passen) zu begrenzen und drei Punkte anzuhängen

Otto123

Ok, Ich habe mal noch etwas gekürzt und gestrichen. Es gibt vor allem noch einen neuen Spezialfall: Das einfache Stereopaar.  ::)

Die Laufschrift ist raus, ich habe mich eher beschränkt in der Ausgabe von Titel und co ;)
Vielleicht ist es so akzeptabel?
Code ist einfach für die Raw Def.
Die Vorbereitung mit Änderung der Readings und userReadings
# stateFormat nicht mehr nach state mappen, stateFormat auf transportState setzen
attr a:model=sonos2mqtt_speaker jsonMap volume_Master:volume mute_Master:mute
attr a:model=sonos2mqtt_speaker stateFormat transportState

# Master Name und Status isMaster und inGroup ermitteln - 
attr a:model=sonos2mqtt_speaker userReadings Master:groupName.* {(split(' +',ReadingsVal($name,'groupName','')))[0]},\
isMaster:coordinatorUuid.* {ReadingsVal($name,'coordinatorUuid','') eq ReadingsVal($name,'uuid','')?1:0},\
inGroup:groupName.* {ReadingsVal($name,'groupName','') =~ / \+ /?1:0},\
inCouple:coordinatorUuid.* {(ReadingsVal($name,'coordinatorUuid','') ne ReadingsVal($name,'uuid','') and (index(ReadingsVal($name,'groupName',''), ReadingsVal($name,'name','')) != -1))?1:0},\
Input:currentTrack_TrackUri.* {my $currentTrack_TrackUri = ReadingsVal($name,'currentTrack_TrackUri','');;\
   $currentTrack_TrackUri =~ 'x-rincon-stream'\
      ? 'LineIn': $currentTrack_TrackUri =~ 'spdif'\
      ? 'TV'    : ReadingsVal($name,'enqueuedMetadata_UpnpClass','') eq 'object.item.audioItem.audioBroadcast'\
      ? 'Radio' : 'Playlist'}

# Ein Trick um die Readings neu zu schreiben, auch die vom Stereopaar
set a:model=sonos2mqtt_speaker volume {(ReadingsVal($DEV,'volume',''))}

Das devStateIcon
# devStateIcon setzen
attr a:model=sonos2mqtt_speaker devStateIcon {\
my $wpix = '210px';;\
my $master = ReadingsVal($name,'Master',$name);;\
my $inGroup = ReadingsNum($name,'inGroup','0');;\
my $isMaster = ReadingsNum($name,'isMaster','0');;\
my $inCouple = ReadingsNum($name,'inCouple','0');;\
my $Input = ReadingsVal($name,'Input','');;\
my $cover = ReadingsVal($name,'currentTrack_AlbumArtUri','');;\
my $mutecmd = ReadingsVal($name,'mute','0') eq 'false'?'true':'false';;\
my $mystate = $isMaster ? Value($name) : Value((devspec2array('DEF='.ReadingsVal($name,'coordinatorUuid','0')))[0]);;\
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'    : 'rc_PLAY@yellow';;\
my $mutepic = $mutecmd eq 'true'?'rc_MUTE':'rc_VOLUP';;\
my $line2 = '';;\
my $title = $mystate eq 'TRANSITIONING' ? 'Puffern...' : ReadingsVal($name,'enqueuedMetadata_Title','FEHLER');;\
my $linePic = ($inGroup and !$isMaster and !$inCouple) ? "<a href=\"/fhem?cmd.dummy=set $name leaveGroup&XHR=1\">".FW_makeImage('rc_LEFT')."</a>" : "";;\
if ($isMaster) {$linePic .= " <a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>"};;\
   $linePic .= "&nbsp;;&nbsp"\
            ."<a href=\"/fhem?cmd.dummy=set $name volumeDown&XHR=1\">".FW_makeImage('rc_VOLDOWN')."</a>"\
            ."<a href=\"/fhem?cmd.dummy=set $name previous&XHR=1\">".FW_makeImage('rc_PREVIOUS')."</a>"\
            ."<a href=\"/fhem?cmd.dummy=set $name next&XHR=1\">".FW_makeImage('rc_NEXT')."</a>"\
            ."<a href=\"/fhem?cmd.dummy=set $name volumeUp&XHR=1\">".FW_makeImage('rc_VOLUP')."</a>"\
            ."&nbsp;;&nbsp"\
            ."<a href=\"/fhem?cmd.dummy=set $name mute $mutecmd&XHR=1\">".FW_makeImage($mutepic)."</a>";;\
if ($isMaster and $mystate eq 'PLAYING') {$line2 = $Input =~ /LineIn|TV/ ? $Input : "$title"}\
    elsif ($inGroup and !$isMaster or $inCouple) {$line2 .= $inCouple ? "Stereopaar":"Steuerung: $master"}\
my $style1 = 'display:inline-block;;margin-right:5px;;border:1px solid lightgray;;height:4.00em;;width:4.00em;;background-size:contain;;background-image:';;\
my $style2 ='background-repeat: no-repeat;; background-size: contain;; background-position: center center';;\
"<div><table>\
     <tr>\
       <td><div style='$style1 url($cover);;$style2'></div></td>\
       <td>$linePic<br><div>$line2</div></td>\
     </tr>\
  </table></div>"\
}

Ich würde jetzt gern noch das attrTemplate und Wiki überarbeiten.
Vielleicht mag ja jemand testen.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz