[Neues Modul] BOSE SoundTouch

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

Vorheriges Thema - Nächstes Thema

FlatTV

Ist bei mir auch so, konnte das nicht weiter prüfen.
2026.05.27 19:38:21 3: BOSEST: failed: 500 Internal Server Error
Raspi4 - im wesentlichen mit Phoscon, HomeMatic ( aktuell über debmatic), CUL, BOSE-ST und Alexa (Connector)

fred_feuerstein

Danke für den Check der Speak Funktion.

Dann liegt also kein lokales Problem bei mir vor.

Also liegt ein Problem bei der Google TTS Abfrage vor. Ich versuche mal herauszufinden wie das genau abgefragt wird im modulcode. Vielleicht kann man es extern prüfen und ggfs. mehr Infos herausbekommen.

Aber normalerweise sind die 500er Fehler ja Serverbasiert...
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

fred_feuerstein

#872
wegen der nicht funktionierenden Speak-Funktion.

Denke hier im Modul erfolgt das mit der Sprachausgabe:
sub BOSEST_speak($$$$$) {
    my ($hash, $text, $volume, $lang, $stopAfterSpeak) = @_;

    $lang = AttrVal($hash->{NAME}, "ttsLanguage", "en") if($lang eq "");
    $volume = AttrVal($hash->{NAME}, "ttsVolume", ReadingsVal($hash->{NAME}, "volume", 20)) if($volume eq "");

    if(length($text) < 100) {
       my $uri_text = uri_escape($text);
       my $translateUrl = "http://translate.google.com/translate_tts?ie=UTF-8&tl=$lang&client=tw-ob&q=$uri_text";
       $translateUrl =~ s/\&/\&amp\;/g;

       if(substr($volume, 0, 1) eq "+" or
          substr($volume, 0, 1) eq "-") {
           $volume = ReadingsVal($hash->{NAME}, "volume", 0) + $volume;
       }

       my $postXml = '<play_info><app_key>Ml7YGAI9JWjFhU7D348e86JPXtisddBa</app_key><url>'.$translateUrl.'</url><service>'.$text.'</service><volume>'.$volume.'</volume></play_info>';
       if(BOSEST_HTTPPOST($hash, '/speaker', $postXml)) {
       }

       if(defined($stopAfterSpeak) && $stopAfterSpeak eq "1") {
           $hash->{helper}{stateCheck}{enabled} = 1;
           #after play the speaker changes contentItemItemName
           $hash->{helper}{stateCheck}{actionContentItemItemName} = "";
           $hash->{helper}{stateCheck}{function} = \&BOSEST_off;
       }

       return undef;
    }
   
   
    my $ttsDir = AttrVal($hash->{NAME}, "ttsDirectory", "");
   
    my $sox = qx(which sox);
    chomp $sox;
    if(!-x $sox) {
        BOSEST_playGoogleTTS($hash, $ttsDir, $BOSEST_READ_CMDREF_TEXT, $volume, $BOSEST_READ_CMDREF_LANG, $stopAfterSpeak);
        return undef;
    }
   
    #download file and play
    BOSEST_playGoogleTTS($hash, $ttsDir, $text, $volume, $lang, $stopAfterSpeak);
   
    return undef;
}

Da ist ja auch ein app_key enthalten. Evtl. hat es damit was zu tun? Abgelaufen?

Hat da jemand mehr Ahnung von als ich?

Ich habe die im Code stehende Abfrage-Url von Google mal manuell getestet. Also der TTS von Google funktioniert.
es scheitert dann wohl beim abspielen der Rückmeldung mit diesem Play und AppKey.
Keine Ahnung wie das abgespielt wird oder was das für ein key ist. Somit kann ich auch nicht schauen ob der key evtl. nicht mehr gültig ist etc.
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

fred_feuerstein

#873
Also ich habe (zusammen mit ChatGPT) an drei Stellen im 98_BOSEST.pm Modul (letzter Stand Version 3.00 aus dem FHEM Update vom 30.06) Änderungen vorgenommen.

Damit läuft der Speak Befehl im Modul wieder.

Die Annahme, dass es nicht an Google lag, war wohl korrekt! Bei einem "set BOSEDEVICE speak ..." wurde das scheinbar über einen Bose-Dienst dann direkt auf dem Lautsprecher abgespielt, deshalb dieser appkey (etc.).

Voraussetzung ist nun ein aktiver und funktionsfähiger minidlna (bei mir auf dem gleichen Raspberry wie fhem).
Und der minidlna (bei mir als Name: fhem_tts) muss vom Lautsprecher aus als source erreichbar sein.

Wenn nun ein speak Befehl abgesetzt wird, dann erfolgt die Konvertierung über Google (wie bisher), die mp3 wird im tts Directory gespeichert, kurze Pause von 5 Sekunden um dem minidlna die Zeit zum indizieren zu geben, dann wird die mp3 auf dem Lautsprecher abgespielt. Nach Abspielen der tts mp3 wird wie bisher wieder zum vorigen Zustand gewechselt, also der bisherige Stream, oder falls ausgeschaltet war, wird die Box auch wieder ausgeschaltet.

Hier die drei Änderungen:

im "sub BOSEST_speak":
statt
if(length($text) < 100) {nun
# Bose Cloud TTS wurde im Mai 2026 abgeschaltet.
# Der ursprüngliche Cloud-Weg (1. Pfad) bleibt aus Dokumentationsgründen erhalten,
# wird aber deaktiviert durch folgende Änderung if(0 && ...
if(0 && length($text) < 100) {


im "sub BOSEST_HTTPPOST":
statt
my $ua = LWP::UserAgent->new();nun
# mit der kaputten BOSEST_speak Funktion hat sich fhem teilweise aufgehängt,
# nun timeout von 5 Sekunden aus Sicherheitsgründen.
my $ua = LWP::UserAgent->new(timeout => 5);


im "sub BOSEST_playMessageStringArg":

komplett tauschen von bisher:
sub BOSEST_playMessageStringArg {
    my ($name) = @_;
    my $hash = $main::defs{$name};
   
    BOSEST_playMessage($hash, "v1_".$hash->{helper}{tts}{fulltextmd5}, $hash->{helper}{tts}{volume}, $hash->{helper}{tts}{stopAfterSpeak});
   
    return undef;
}
auf jetzt:
sub BOSEST_playMessageStringArg {
    my ($name) = @_;

    InternalTimer(
        gettimeofday()+5,
        "BOSEST_playMessageStringArgDelayed",
        $name,
        0
    );

    return undef;
}

sub BOSEST_playMessageStringArgDelayed($) {
    my ($name) = @_;
    my $hash = $main::defs{$name};

    BOSEST_playMessage(
        $hash,
        "v1_".$hash->{helper}{tts}{fulltextmd5},
        $hash->{helper}{tts}{volume},
        $hash->{helper}{tts}{stopAfterSpeak}
    );

    return undef;
}

im ttsDirectory landen nun die ganzen mp3s, das kann u.U. recht viel werden, je nachdem, wie viele Speak Befehle man absetzt. (bei mir recht viele Meldungen tagsüber ;) ). Deshalb lasse ich die beiden Varianten der mp3s per cron nachts löschen:
15 3 * * * rm -f /opt/fhem/tts/[0-9a-f]*.mp3 && rm -f /opt/fhem/tts/v1_*.mp3
Ist alles so seit gestern wieder am Laufen.

Kenne mich mit Git usw. nicht so gut aus. Deswegen die Änderungen hier gemeldet.

Zitat von: Prof. Dr. Peter Henning am 26 Mai 2026, 17:24:10Ich hänge immer noch damit hinterher, das neue Modul regulär einzuchecken. Bitte um Nachsicht, aber mein neues Buchmanuskript hat in 3 Wochen Abgabetermin, das geht derzeit vor.
LG
pah

Vielleicht kannst Du die Änderungen siehe oben berücksichtigen fürs offizielle Release.


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

betateilchen

Zitat von: fred_feuerstein am 02 Juli 2026, 13:28:20if(0 && length($text) < 100) {durch diese Änderung wird u.a. die mp3 gespeichert

Kannst Du mir bitte erklären, was dieser logische Vergleich bewirken soll?

Zitat von: fred_feuerstein am 02 Juli 2026, 13:28:20Vielleicht kannst Du die Änderungen siehe oben berücksichtigen fürs offizielle Release.

Hast Du mitbekommen, dass am 30.06. das Modul offiziell neu released und im regulären FHEM update verteilt wurde?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

fred_feuerstein

#875
Erklären kann ich es nicht. Allerdings wird ohne den Vergleich bei mir keine mp3 vom Google response gespeichert.
>> Erklärung 3 Beiträge weiter unten ;)

Und nein, ich habe nicht mitbekommen, dass das Modul nun im regulären Update dabei ist.

Wo hätte ich das sehen können?

Bzw. wer pflegt das Modul nun und wie und wo kann man etwas dazu melden? Denke, es ist hier im Thread ok, oder?
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

betateilchen

Naja, ein logischer Vergleich auf "falsch UND irgendwas anderes" wird halt immer ein "falsch" ergeben. Und 0 bedeutet per se "falsch".

Wo hättest Du das sehen können? Mehrere Möglichkeiten...

-> in einem regulären update: das Modul wird in der update-Liste angezeigt
-> alternativ hier: https://forum.fhem.de/index.php?board=57.0 da werden alle svn commits gesammelt dokumentiert: https://forum.fhem.de/index.php?topic=145025.0

Wer pflegt das? Da pah das eingecheckt hat, vermutlich pah.

Wo kann man Meldungen dazumachen? Solange die MAINTAINER.txt nix anderes sagt, würde ich wie bisher in Multimedia posten.

@pah: magst Du bitte die MAINTAINER.txt noch pflegen?
-----------------------
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

Zitat von: fred_feuerstein am 02 Juli 2026, 18:03:28Bzw. wer pflegt das Modul nun und wie und wo kann man etwas dazu melden? Denke, es ist hier im Thread ok, oder?

Ich. Und ja, hier im Thread ist ok. Ich schau mal, ob ich das einbauen und testen kann - wird aber wegen Urlaub etwa eine Woche dauern.

LG

pah

fred_feuerstein

Wegen dem "0 && irgendwas..."

Habe mir den Code nochmal angeschaut.
im sub Speak gibt es 2 Pfade.

if(length($text) < 100) {
    ...
    # kurzer Text
    # Google-TTS direkt / Cloud-Weg
}
else {
    ...
    # MP3 erzeugen
    # über DLNA abspielen
}

durch die Änderung wird der 1. Pfad über die bose cloud nie mehr ausgewählt, da nicht mehr möglich.
stattdessen immer der mp3 / dlna weg.

War die einfachste Änderung, ohne den ganzen Code für Pfad 1 gleich wegzuwerfen.
ist ja quasi noch Testphase :)
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

betateilchen

Zitat von: Prof. Dr. Peter Henning am 02 Juli 2026, 19:49:00Und ja, hier im Thread ist ok. Ich schau mal, ob ich das einbauen und testen kann

Wäre es nach 59 Seiten Beiträge nicht sinnvoll, für das komplett überarbeitete Modul einen neuen Thread aufzumachen und diesen schließen zu lassen?
-----------------------
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

Zitat von: fred_feuerstein am 02 Juli 2026, 19:52:51ist ja quasi noch Testphase
Äh - nö.
Das Modul ist jetzt produktiv in Version 3.0, sonst wäre es nicht in der regulären Distribution. Dass ich das Thema TTS dabei ausgespart habe liegt daran, dass unklar war, wie das mit TTS via BOSE Cloud weitergehen würde.

Also hiermit Ankündigung: Nachdem der Weg über die BOSE Cloud nicht mehr funktioniert, besteht kein Anlass mehr, das so im Modul zu belassen. Stattdessen werde ich set ... speak so umbauen, dass damit eine der anderen (und durchaus vielfältigen) Sprachausgabemethoden in FHEM aufgerufen wird (konfigurierbar über Attribut) und nur die Ausgabe der erzeugten MP3-Datei über die BOSE-Geräte erfolgt.

Mit anderen Worten: Für Nutzer des SoundTouch-Moduls werden ca. 3-5 zusätzliche Einstellungen nötig sein, dann funktioniert es wieder wie gehabt. Dafür wird aber eine erhöhte Flexibilität bei der Ausgabe bestehen, z.B. vorgefertigte Texte ebenso wie die Kombination aus entsprechenden Bausteinen möglich sein, sowie andere TTS-Systeme als Google nutzbar sein.

Hintergrund: Schon seit mehr als 10 Jahren erzeuge ich meine TTS-Ansagen nicht mit Google, sondern mit Amazon Polly (via direkter TTS-Bibliothek auf Android-Geräten, via AWS-Aufruf auf den BOSE-Geräten). Der klare Vorteil dabei ist, dass alle Sprachausgaben mit derselben Stimme erfolgen - egal wo man sich befindet. Darüber hinaus gibt es ca. 300 verschiedene Ausgabetexte, die als MP3 vorliegen (z.B., gerade gehört: "Solares Überschussladen des ID7 beginnt"). Diese Texte sind als dreistelliger Code adressierbar z.B. hier als Nr. 156, und ein Perl-Aufruf
speak("SoundTouch.EG",":156:") erzeugt genau diese Ausgabe. Mehr noch:
speak("SoundTouch.EG","Guten Morgen, ich will Dir jetzt etwas mitteilen: :156:") lässt auf meiner BOSE ST300 sehr schön erklingen:
"Guten Morgen, ich will Dir jetzt etwas mitteilen: Solares Überschussladen des ID7 beginnt".

Zusammen mit einem effektiven Caching für Bausteine wie "Guten Morgen, ich will Dir jetzt etwas mitteilen:" reduziert das die TTS-Anfragen bei einem Cloud-Service um rund 90 Prozent. Und ja: Das ist ein aktiver Beitrag zum Klimaschutz.

LG

pah

fred_feuerstein

#881
das mit der Testphase bezog sich nicht auf deinen Stand vom Bosest Modul, sondern auf meine Änderungen für google tts. Damit läuft der speak Befehl bei mir endlich wieder. Und die Google-Stimme ist jetzt nicht sooo schlecht ;)

set BOSE_2C6B7DB9D239 speak "Guten Morgen am [BOSE_2C6B7DB9D239:userAktTag], den [BOSE_2C6B7DB9D239:userAktDat] [BOSE_2C6B7DB9D239:userAktMonat], {(sprintf('%d',(substr(FmtTime(time()),0,2))))} Uhr {(sprintf('%d',(substr(FmtTime(time()),3,2))))} "
spricht in Google-Sprache auch schön:
Guten Morgen am Freitag, den 3. Juli, 9 Uhr 24
Die erzeugte mp3 wird per minidlna bereitgestellt und auf dem Bose Speaker abgespielt. Von daher. Alles gut aktuell.
Und theoretisch könnten über diesen Weg auch bereits als mp3 vorliegende Dateien erhalten bleiben und als "Bausteine" zur Verfügung gestellt werden. Ist ja in der sqlite entsprechend mit IDs hinterlegt. Somit auch über diese IDs immer aufrufbar.


Aber wenn Du den Speak-Befehl umbauen und aufbohren möchtest mit Polly etc.
immer gerne. bin gespannt :)
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

fred_feuerstein

#882
zu meiner obigen Anpassung (siehe hier: https://forum.fhem.de/index.php?msg=1366105 ), damit der speak Befehl die von google gelieferte mp3-Datei abspeichert und dann über den minidlna bereitgestellt und abgespielt wird (incl. savestate, ttsvolume und anschliessendem Restore), habe ich nun noch erweitert, dass man fertige mp3-Dateien auch als tts-Ausgaben nutzen kann. Somit kann man sich ein beliebiges Setup an diversen mp3-Dateien aufbauen. Hinterlegt diese mit sprechenden Namen im tts-Verzeichnis, bspw. "waschmaschinefertig.mp3", und kann diese mp3 dann entsprechend abspielen.

Das ging ohne Änderung bereits mit
set BOSE_xxx playTrack waschmaschinefertigAllerdings bleibt die Box nach dem Abspielen stehen und geht nicht auf den Ursprungsstatus (Standby oder Play etc.) zurück. Ausserdem bleibt die Lautstärke auf der zuvor eingestellten Lautstärke, was für tts meist zu leise ist.

Es gibt nun einen weiteren Parameter "tts":
set BOSE_xxx playTrack waschmaschinefertig ttsWenn gesetzt wird die gleiche Routine wie beim Speak Befehl genutzt, d.h.
✅ Status wird gespeichert (saveState)
✅ Radio etc. wird sauber gestoppt
✅ TTS-Lautstärke wird verwendet
✅ MP3 wird abgespielt
✅ Ursprünglicher Zustand (Radio, Stream, Standby, Lautstärke) wird wiederhergestellt (restoreState)
✅ Das bisherige playTrack bleibt unverändert und vollständig kompatibel

folgende Änderungen sind dafür nötig:

der bisherige Block:
} elsif($workType eq "playTrack") {
    return "BOSEST: playTrack requires track name as additional parameters"
        if(int(@params) < 1);

    BOSEST_playTrack($hash, $params[0]);

wird zu:
} elsif($workType eq "playTrack") {
    return "BOSEST: playTrack requires track name as additional parameter"
        if(int(@params) < 1);

    my $track = $params[0];
    my $mode  = defined($params[1]) ? lc($params[1]) : "";

    if($mode eq "tts") {
        BOSEST_playTrackTTS($hash, $track);
    } else {
        BOSEST_playTrack($hash, $track);
    }

d.h. der bisherige "playTrack"-Befehl bleibt vollständig kompatibel und wird durch den Parameter tts bei bedarf erweitert.

Zusätzlich wird eine Funktion eingefügt (am besten bei der Reihenfolge hinter "sub BOSEST_playTrack"):

sub BOSEST_playTrackTTS($$) {
    my ($hash, $track) = @_;

    my $name      = $hash->{NAME};
    my $ttsVolume = AttrVal($name, "ttsVolume",
                            ReadingsNum($name, "volume", 25));

    # Aktuellen Zustand einschließlich Lautstärke speichern
    BOSEST_saveCurrentState($hash);

    # Erst stoppen, damit die bisherige Wiedergabe nicht
    # mit der TTS-Lautstärke weiterläuft.
    my $cmd  = "set $name stop;";
       $cmd .= "sleep 0.1;";
       $cmd .= "set $name volume $ttsVolume;";
       $cmd .= "sleep $name:volume:.$ttsVolume;";
       $cmd .= "set $name playTrack \"$track\";";
       $cmd .= "sleep $name:source:.INVALID_SOURCE;";
       $cmd .= "set $name restoreState";

    fhem($cmd);

    return undef;
}

Nach der Änderung um dem Speichern auf dem Server dann noch ein
reload 98_BOSEST.pm
MP3 Dateien für tts (im Prinzip alle statischen tts Ausgaben, die keine aktuellen weiteren Variablen aus fhem (Temperaturen, stati, etc. ) verwenden) können nun nach belieben erstellt und mit Klarnamen gespeichert werden im tts-Verzeichnis (attr BOSE_xxx ttsDirectory /.../...).
Ich nutze als Prefix BOSEST_xxx.mp3, damit funktioniert der oben erwähnte cron Eintrag und löscht nur die live über google geholten MP3-Dateien im Format "a-f_nurZiffern".mp3 oder v1_"a-f_nurZiffern".mp3.
Das heisst alle anderen mp3-Dateien mit Klarnamen und vor allem mit dem Prefix BOSEST_... bleiben im Verzeichnis erhalten.

Wie man sich nun einige MP3-TTS-Dateien erstellt, kann jeder selbst entscheiden. Am einfachsten über den Speak-Befehl im BOSE Device selbst.
Einfach den gewünschten Text eingeben und danach im Verzeichnis die neueste Datei mit v1_...mp3 entsprechend als Klarname umbenennen.

Dann kann sofort getestet werden (mp3-Datei ohne Endung eingeben):
set BOSE_xxx playTrack BOSEST_klarname tts
Viel Spaß!

und noch ein paar Worte bzgl. MiniDLNA. Ich habe den bisher auch quasi nie gebraucht. bei Neuinstallationen vom Raspi gar nicht mitinstalliert. Aber wer sich an die Anleitung vom BOSEST Modul von Seite 1 hier im Thread gehalten hat, der hat den minidlna ohnehin installiert ;)  Ist also relativ schnell nach den Anpassungen einsatzfähig :)
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