[Neues Modul] BOSE SoundTouch

Begonnen von dominik, 05 Januar 2016, 22:28:40

Vorheriges Thema - Nächstes Thema

Prof. Dr. Peter Henning

#690
Zitat von: betateilchen am 04 Januar 2026, 14:05:36Das wird also ein Feature sein, das ich ab Februar nicht mehr nutzen kann. Ok, das ist kein Weltuntergang, ich setze das bisher nur an einer einzigen Stelle in FHEM ein und es lässt sich problemlos durch andere Signalisierungsarten ersetzen.

Doch, das geht problemlos ohne BOSE-Cloud.

1. Gewünschte MP3-Datei erzeugen. Bedeutet bei mir:
- teste den Text auf enhaltene Substrings :xxx: (drei Ziffern). Das sind vordefinierte Nachrichten (phrases), die schon als MP3 existieren z.B. :017: = "Die Tür zum Vorratskeller ist offen".
- hole alle anderen substrings als MP3-speechlet von AWS oder Google, oder aus meinem tts-Cache (eine SQLite-db)
- setze den ganzen Kram zusammen, z.B. mit sox oder mp3wrap
- für die BOSE-Boxen setze noch etwas MP3-Stille davor, bestimme die Gesamtdauer
- schreibe den Titel "fhemspeech" als MP3-Tag
- speichere das in die Datei /home/fhem/tts/speech.mp3

2. Das Verzeichnis /home/fhem/tts ist von einer NAS gemountet, auf der NAS läuft irgendein Streaming-Server (z.B. Minim)
3. Die BOSE-Boxen kennen diesen Server
4. Eventuell gerade abgespielte Dinge (z.B. Fernsehen, Musik, welche Lautstärke) werden in ein paar Variablen gespeichert
5. Die Zielbox bekommt das Kommando "set <device> playTrack fhemspeech", vorher wird noch die Lautstärke geändert
6. Nach Ablauf der Zeit (kennen wir ja von oben) wird das ursprüngliche Abspielen wieder hergestellt.

Funktioniert astrein.

LG

pah

betateilchen

Das ist mir zu umständlich  8)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Prof. Dr. Peter Henning

War auch nicht ganz einfach aufzusetzen. Da ich aber die Sprachausgabe auf ganz unterschiedlichen Geräten mit derselben Stimme verwende (Android Tablets an der Wand, Telegram, Linux-PC, auch Webbrowser und eben diverse BOSE-Boxen) hat sich das gelohnt.

Hoher WAF.

LG

pah

betateilchen

#693
Du hast mich aber auf die Idee gebracht, die einzige Textkonserve, die ich brauche, durch einen der online verfügbaren text-to-speech Konverter als mp3 erzeugen zu lassen.

Da die ST-Boxen inzwischen ja ohnehin die Fritzbox als Mediaserver nutzen, muss ich jetzt nur noch rausfinden, wo ich die mp3 korrekt ablegen muss.



Edit: Ablageort ist gefunden, Abspielen funktioniert einwandfrei.

Jetzt baue ich noch das "Drumrum", also die Zustandsspeicherung und -wiederherstellung, falls die Box schon lief.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: Prof. Dr. Peter Henning am 04 Januar 2026, 16:30:25- für die BOSE-Boxen setze noch etwas MP3-Stille davor, bestimme die Gesamtdauer

Das mit der Stille und der Bestimmung der Gesamtdauer habe ich nicht verstanden. Egal.

Meine Variante sieht nun so aus:

sub playMessage {
  my ($dev,$msg,$vol) = @_;

  # finde die Box mit dem ALIAS ...
  my $d = (devspec2array("alias=$dev"))[0];

  # speichere den aktuellen Zustand
  my %bose;
  $bose{state}   = lc(ReadingsVal($d,"state",""));
  $bose{channel} =    ReadingsNum($d,"channel",undef);
  $bose{content} =    ReadingsVal($d,"contentItemItemName",undef);
  $bose{volume}  =    ReadingsNum($d,"volume",25);
  $bose{restore} = 1;

  if ($bose{state} ne 'playing') {
    $bose{restore} = 0;
  }

  # baue eine lange FHEM Befehlskette
  my $cmd  = "set $d stop; sleep 0.1;";
     $cmd .= "set $d volume $vol; sleep $d:volume:.$vol;";
     $cmd .= "set $d playTrack $msg; sleep $d:source:.INVALID_SOURCE;";
     $cmd .= "set $d volume $bose{volume}; sleep $d:volume:.$bose{volume};";

  # lege die Schlussaktion nach dem Abspielen fest
  if ($bose{restore}) {
    if (defined($bose{channel})) {
  $cmd .= "set $d channel $bose{channel}";
} else {
  $cmd .= "set $d playTrack $bose{content}";
}
  } else {
  $cmd .= "set $d off";
  }
 
  # führe die lange Befehlskette aus
  fhem $cmd;
}

und funktioniert bei mir sowohl, wenn die Box gerade Radio spielt, als auch, wenn sie ausgeschaltet ist.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

FlatTV

Folgendes ist mir zu dem Modul im Offline-Modus (ohne Bose-Cloud) noch aufgefallen.
- Speichern der Presets 1-6 sollte hinzugefügt werden
curl -X POST http://<ip>:8090/storePreset -d '<preset id="5">
    <ContentItem source="STORED_MUSIC" type="" location="5:audio5:part11:21:5 TRACK" sourceAccount="fa095ecc-e13e-40e7-8e6c-2C91ABDE431B/0" isPresetable="true">
      <itemName>181.FM Soul</itemName>
      <containerArt></containerArt>
    </ContentItem>
  </preset>' | xmllint --format -
- Aktualisieren der Readings für die Presets 1-6, falls die Speicherung extern erfolgt ist.
Raspi3 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

fred_feuerstein

Zitat von: betateilchen am 04 Januar 2026, 14:05:36Ok, jetzt habe ich doch etwas gefunden, das ohne Internetverbindung nicht funktioniert.

Über FHEM kann man mit "set <BoseDevice> speak ..." Nachrichten/Texte ausgeben lassen.
Ohne ins Internet verbunden zu sein, funktioniert das nicht.

Das wird also ein Feature sein, das ich ab Februar nicht mehr nutzen kann. Ok, das ist kein Weltuntergang, ich setze das bisher nur an einer einzigen Stelle in FHEM ein und es lässt sich problemlos durch andere Signalisierungsarten ersetzen.

ich nutze "set <BoseDevice> speak ..." sehr häufig mit unterschiedlichsten zusammengebauten dynamischen Texten, Variablen etc.
Ist das feature "speak" etwas von der Bose-Cloud? Oder funktioniert es bei dir aktuell nur nicht, weil Du die Bose-Boxen vom Internet getrennt hast.

Dachte bisher, dass die Sprachausgabe über "speak" über Google läuft und nicht primär mit Bose selbst zu tun hat. Somit auch nach Februar funktionieren sollte, oder?

Ich würde ohnehin sicherheitshalber jedem empfehlen sich die aktuelle Firmware von seinen Bose-Lautsprechern zu sichern, bzw. downzuloaden:
Ein Archiv dazu gibt es hier:
https://archive.org/download/bose-soundtouch-software-and-firmware/
Dann kann man falls von Bose ein Abschiedsgeschenk kommt, manuell per USB wieder auf eine ältere Firmware zurückgehen.
Testen welche Firmware gerade installiert ist: Taste 4 und Minus Taste drücken und dann mit Minus bis zu Punkt 4.2 "scrollen".



Gruß, Fred

NEU: FHEM auf Raspberry PI 5, OS: Bookworm, mit Z-Wave RaZberry-Modul, 868CUL (WMBUS), LaCrosseCUL (Temp) und knapp 300 Devices aller Art
ALT: FHEM auf Raspberry PI 3B+ im 7Zoll TouchDisplay Gehäuse, OS: Bullseye, mit Z-Wave RaZberry-Modul, 868CUL (WMBUS), LaCrosseCUL (Temp)

betateilchen

Zitat von: fred_feuerstein am 05 Januar 2026, 15:46:10Ist das feature "speak" etwas von der Bose-Cloud? Oder funktioniert es bei dir aktuell nur nicht, weil Du die Bose-Boxen vom Internet getrennt hast.

Keine Ahnung, ich habe das nicht weiter erforscht.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

FlatTV

Zitat von: FlatTV am 05 Januar 2026, 08:53:30...
- Aktualisieren der Readings für die Presets 1-6, falls die Speicherung extern erfolgt ist.

Ich wollte nochmal genauer auf den 2.Punkt eingehen.
Wenn ein Preset 1-6 über die Bose App gesetzt wird, wird auch das entsprechende Reading für alle Boxen in Fhem geändert.
Setzt man ein Preset ohne die Bose App für eine bestimmte Box, wird dieses Reading in Fhem zur Zeit eben nicht aktualisiert.
Raspi3 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

betateilchen

Zitat von: FlatTV am 05 Januar 2026, 20:05:38Setzt man ein Preset ohne die Bose App für eine bestimmte Box, wird dieses Reading in Fhem zur Zeit eben nicht aktualisiert.

Workaround: die Box löschen, nach der automatischen Neuanlage sind die channels dann korrekt belegt.
Nicht schön, zugegeben. Aber es funktioniert.

Edit: gerade getestet - nach einem FHEM Neustart werden die readings für die channels auch korrekt gefüllt.



Zitat von: fred_feuerstein am 05 Januar 2026, 15:46:10Dachte bisher, dass die Sprachausgabe über "speak" über Google läuft und nicht primär mit Bose selbst zu tun hat. Somit auch nach Februar funktionieren sollte, oder?

Nachdem ich nun ein bisschen im Modulcode gestöbert habe: ja, Du hast recht, das läuft über Google und funktioniert höchstwahrscheinlich wegen des blockierten Internetzugangs bei mir nicht mehr.

Und nach dem Stöbern im Code weiß ich auch, dass ich meine gestern gepostete Variante zum Abspielen eines Textes viel einfacher hätte gestalten können. Das BOSEST Modul stellt die ganzen Funktionen zum Abspeichern das aktuellen Zustandes und zum Wiederherstellen bereits intern zur Verfügung 8)
Wenn ich mal Zeit finde, baue ich meinen Code bestimmt nochmal entsprechend um.




Zitat von: FlatTV am 05 Januar 2026, 20:05:38Setzt man ein Preset ohne die Bose App für eine bestimmte Box, wird dieses Reading in Fhem zur Zeit eben nicht aktualisiert.

Workaround 3:

defmod at_presets at +*00:01:00 {BOSEST_updatePresets($defs{BOSE_000C8A7A8A54},undef)}
Den gleichen Code kann man natürlich auch an ein notify hängen, das auf bestimmte Statusänderungen der BOSE Box reagiert, anstatt jede Minute die presets abzufragen.

Oder man baut sich einen cmdalias daraus - es gibt viele Möglichkeiten, diese Funktion aufzurufen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

FlatTV

Man müsste mal die Bose App Wiresharken.
Die sendet ja an alle Boxen den zu speichernden Preset und im Fhem sind die Readings sofort aktuell.
Raspi3 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

Prof. Dr. Peter Henning

Zitat von: betateilchen am 04 Januar 2026, 19:48:09Das mit der Stille und der Bestimmung der Gesamtdauer habe ich nicht verstanden. Egal.
Insbesondere meine BOSE ST300 benötigt einen Moment, bis sie richtig "wach" ist. Sie hat deshalb immer die erste Silbe von Sprach-MP3 verschluckt. Deshalb kommt eben etwas "Stille" davor, nämlich die angehängte Datei.

Wenn Ihr gerade etwas am Code herumschraubt, zwei Wünsche. Ich hätte gerne ein Kommando "find_again", das auf Wunsch direkt auf die Suche nach der Box geht, wenn diese mal offline war. Außerdem wäre es schön, das "store" und "restore" von Abspielinformationen bei einer kurzzeitigen Unterbrechung direkt im Modul zuhaben. Noch komfortabler wäre, wenn man auch eine Zeit für ein automatisches "restore" übergeben könnte.

LG

pah

betateilchen

Zitat von: Prof. Dr. Peter Henning am 06 Januar 2026, 04:04:59Wenn Ihr gerade etwas am Code herumschraubt

Nun habe ich nicht 47 Seiten des Threads gelesen, aber wird das Modul überhaupt noch gewartet?

dominik ist ja eben gerade online, bin gespannt, ob er hier reinschaut.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: Prof. Dr. Peter Henning am 06 Januar 2026, 04:04:59wäre es schön, das "store" und "restore" von Abspielinformationen bei einer kurzzeitigen Unterbrechung direkt im Modul zuhaben.

Bitteschön:

Index: /opt/fhem/FHEM/98_BOSEST.pm
===================================================================
--- /opt/fhem/FHEM/98_BOSEST.pm (revision 30692)
+++ /opt/fhem/FHEM/98_BOSEST.pm (working copy)
@@ -396,6 +396,7 @@
                 "stop:noArg pause:noArg channel:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 ".
                 "volume:slider,0,1,100 ".$hash->{helper}{supportedBassCmds}." ".
                 "saveChannel:07,08,09,10,11,12,13,14,15,16,17,18,19,20 ".
+                "saveState:noArg restoreState:noArg restoreVolAndOff:noArg ".
                 "addDLNAServer:".$hash->{helper}{dlnaServers}." ".
                 "removeDLNAServer:".ReadingsVal($hash->{NAME}, "connectedDLNAServers", "noArg");
 
@@ -532,6 +533,12 @@
         return "BOSEST: removeFromZone requires deviceID as additional parameter" if(int(@params) < 1);
         #params[0] = deviceID channel
         BOSEST_removeFromZone($hash, $params[0]);
+    } elsif($workType eq "saveState") {
+        BOSEST_saveCurrentState($hash);
+    } elsif($workType eq "restoreState") {
+        BOSEST_restoreSavedState($hash);
+    } elsif($workType eq "restoreVolAndOff") {
+        BOSEST_restoreVolumeAndOff($hash);
     } else {
         return SetExtensions($hash, $list, $name, $workType, @params);
     }

Zitat von: Prof. Dr. Peter Henning am 06 Januar 2026, 04:04:59Noch komfortabler wäre, wenn man auch eine Zeit für ein automatisches "restore" übergeben könnte.

Noch komfortabler wäre es doch, die Zeit gar nicht mitgeben zu müssen?
Wenn eine Ansage zuende ist, bekommt das reading 'source' den Wert 'INVALID_SOURCE'.
Darauf kann man ein nonblocking 'sleep' ansetzen, bevor man dann das restore durchführt.

Wozu brauchst Du da noch eine Zeitangabe?

fhem "set $d playTrack $msg; sleep $d:source:.INVALID_SOURCE; set $d restoreState"
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Prof. Dr. Peter Henning

Den Patch werde ich mal ausprobieren.

Zitat von: betateilchen am 06 Januar 2026, 11:09:55Wozu brauchst Du da noch eine Zeitangabe?
Weil ich auch die BOSE-Kisten mute, so lange eine Ausgabe an anderer Stelle läuft.

Und ja, genau so wie von Dir als Beispiel geliefert, mache ich das derzeit.

LG

pah