[Neues Modul] BOSE SoundTouch

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

Vorheriges Thema - Nächstes Thema

rakete123

Hört sich gut an, zeig mal her ;-)

Wobei ich aktuell überlege MPD, Logitech Squeeze oder ähnliches einzuführen.
Das Bose Zeug ist einfach unzuverlässig. Nicht das FHEM Module, einfach die ganze Software.
Zwave: ZMEEUZB1 (Fibaro, Aeotec, diverse)
Zigbee: Conbee (HUE, Xiaomi, osram)
Homematic: HM-MOD-RPI-PCB + diverse HM-CC-RT-DN
Sonstiges: Harmony, Android, Netatmo, Jabber (talk2fhem)
https://resize2fs.de

rakete123

#586
Okay also via curl hab ich genau was ich brauche.
Auf die HDMI Quelle umschalten:

curl \
--request POST \
--header "Content-Type: text/xml" \
--data '
<ContentItem source="PRODUCT" sourceAccount="HDMI_1">
    <itemName>HDMI_1</itemName>
</ContentItem>
' \
http://st-wohnzimmer:8090/select


@dominik: Würdest du das ins Module einbauen? Ich sehe zwar du nutzt den /select endpoint bereits, aber für andere Dinge glaube ich. Wenn du keine Zeit hast, wäre ein kurze Info nett dann versuche ich mal am Wochenende einen Patch zu erstellen.
Zwave: ZMEEUZB1 (Fibaro, Aeotec, diverse)
Zigbee: Conbee (HUE, Xiaomi, osram)
Homematic: HM-MOD-RPI-PCB + diverse HM-CC-RT-DN
Sonstiges: Harmony, Android, Netatmo, Jabber (talk2fhem)
https://resize2fs.de

Prof. Dr. Peter Henning

#587
Dafür ist die Soundqualität besser als bei Sonos...

Aber die Software von Bose ist wirklich eine Unverschämtheit - wird nur noch durch den Support unterboten.

"Zeig mal her", soso.

Da ich im Moment wenig Zeit habe, poste ich den ganzen Kram mal ohne Erklärungen (Kommentare sind drin). Einige der darin enthaltenen Codezeilen sind schon in das Modul Text2Speech eingeflossen.

#############################################################################
#
#  Restore previous state after speech command
#
#############################################################################
 
sub BOSERepsas($){ 
  my ($bid) = @_;
 
  my ($cur,$cha,$src,$acc,$trk,$vol,$cmd);
  $cmd = "";
  #-- current state
  $cur = ReadingsVal($bid,"state","unknown");
  $cha = ReadingsVal($bid,"channel","");
  $src = ReadingsVal($bid,"contentItemSource","");
  $acc = ReadingsVal($bid,"contentItemSourceAccount","");
  $trk = ReadingsVal($bid,"track","");
  $vol = ReadingsVal($bid,"volume","");
 
  if( $cur eq "playing" ){
    if( $src =~ /STORED.*/ ){
      $cmd = "set $bid volume $vol;; set $bid channel $cha";
    }elsif( $cha ne "" || $src =~ /TUNEIN.*/ ){
      $cmd = "set $bid volume $vol;; set $bid channel $cha";
    }elsif( $src eq "PRODUCT" && $acc eq "TV" ){
      $cmd = "set $bid volume $vol;; set harmony_55418949 InputTv";
    }else{
      $cmd = "set $bid volume $vol;; set $bid off";
    }
  }else{
    $cmd = "set $bid volume $vol;; set $bid off";
  }
  fhem("setreading $bid restorecmd $cmd");
  return $cmd;
}
 
##############################################################################
#
#  Sprachausgabe
#
##############################################################################

my %ttsPhrases = (
"001_jeanniehilfe" => "Hallo, ich bin Jeannie. Wie kann ich Dir helfen?",
"011_hoftuer_sichern" => "Die Hoftür wird gesichert.",
"012_hoftuer_gesichert" => "Die Hoftür ist gesichert.",
"013_hoftuer_entsichern" => "Sicherung der Hoftür aufgehoben.",
"014_hoftuer_ungesichert" => "Die Hoftür ist nicht gesichert.",
"015_haustuer_sichern" => "Die Hauseingangstür wird gesichert.",
"016_haustuer_gesichert" => "Die Hauseingangstür ist gesichert.",
"017_haustuer_entsichern" => "Sicherung der Hauseingangstür aufgehoben.",
"018_haustuer_ungesichert" => "Die Hauseingangstür ist ungesichert.",
"019_haustuer_offen" => "Die Hauseingangstür ist offen.",
"020_badezimmerfenster" => "Das Badezimmerfenster ist offen.",
"021_kellerfenster" => "Ein Kellerfenster ist offen.",
"022_terrassentuer" => "Die Terrassentür ist offen.",
"023_hoftuer" => "Die Hoftür ist offen.",
"024_vorratskeller" => "Die Tür zum Vorratskeller ist offen.",
"025_garagebew" => "Das Garagentor wird bewegt.",
"026_dominiczimmerfenster" => "Das Fenster in Dominics Zimmer ist offen.",
"027_schlafzimmertuer" => "Die Balkontür im Schlafzimmer ist offen.",
"030_bewaus" => "Die Bewässerung wurde ausgeschaltet.",
"031_bewvorgarten" => "Die Bewässerung im Vorgarten läuft.",
"032_bewterrasse" => "Die Bewässerung rund um die Terrasse läuft.",
"033_bewhecke" => "Die Bewässerung der Hecke läuft.",
"034_bewrasen" => "Die Rasenbewässerung läuft.",
"049_alarmverz" => "Alarmanlage wird verzögert scharf geschaltet.",
"050_alarmscharf" => "Alarmanlage scharf geschaltet.",
"051_alarmunscharf" => "Alarmanlage unscharf geschaltet.",
"052_stoerung" => "Achtung, Systemstörung!",
"053_feuchtebad" => "Achtung, hohe Feuchtigkeit im Bad.",
"054_feuchtekeller" => "Achtung, hohe Feuchtigkeit im Keller.",
"055_zirkulation" => "Warmwasserzirkulationspumpe für 5 Minuten eingeschaltet.",
"059_widerruf" => "Alarm widerrufen.",
"061_haus_sichern" => "Das Hau swird in Kürze gesichert.",
"062_haus_gesichert" => "Das Haus ist gesichert.",
"063_haus_entsichern" => "Sicherung des Hauses aufgehoben.",
"064_haus_ungesichert" => "Das Haus ist nicht gesichert.",
"065_zutrittsversuch" => "Achtung, unerlaubter Zutrittsversuch.",
"066_zutrittbewohner" => "Ein Bewohner betritt das Haus.",
"067_willkommen" => "Willkommen zu Hause.",
"069_posteinwurf" => "Bitte wwerfen Sie das richtig ein!",
"081_teewasser" => "Bitte an das Teewasser denken.",
"100_gutenachtmeister" => "Gute Nacht, Meister!",
"101_gutenachtjac" => "Gute Nacht, Jacqueline!",
"102_gutenacht" => "Gute Nacht!",
"103_gutenmorgenmeister" => "Guten Morgen, Meister!",
"104_gutenmorgenjac" => "Guten Morgen, Jacqueline!",
"105_gutenmorgen" => "Guten Morgen!",
"106_hausschonnacht" => "Das Haus ist schon im Nachtzustand.",
"107_hausschontag" => "Das Haus ist schon im Tagzustand.",
"108_hausschonentsichert" => "Das Haus ist schon entsichert.",
"109_hausschongesichert" => "Das Haus ist schon gesichert.",
"110_hausgeschuetzt" => "Das Haus ist jetzt geschützt.",
"111_hausueberwacht" => "Das Haus wird jetzt überwacht.",
"113_dndeingesch" => "Nicht-Stören-Modus eingeschaltet",
"114_partieingesch" => "Partimodus eingeschaltet.",
"115_abweseingesch" => "Abwesenheitsmodus eingeschaltet.",
"116_dndbeendet" => "Nicht-Stören-Modus beendet.",
"117_partibeendet" => "Partimodus beendet.",
"118_abwesbeendet" => "Abwesenheitsmodus beendet.",
"119_dachf_wind" => "Die Dachfenster werden wegen starken Windes geschlossen.",
"120_dachf_regen" => "Die Dachfenster werden wegen Regen geschlossen.",
"121_dachfoffen" => "Mindestens ein Dachfenster ist offen."
);

sub tts_allnew(){
  my $polly = Paws->service('Polly', region=>'eu-central-1');
 
  foreach my $file (keys %ttsPhrases) {
    my $converter = Text::Iconv->new("utf-8", "iso-8859-1");
    my $text = $converter->convert($ttsPhrases{$file});
    my $ssmltext="<speak>$text</speak>";
 
    #-- obtain speechlet 
    my $res = $polly->SynthesizeSpeech(
       VoiceId => 'Marlene',
       TextType=> 'ssml',
       Text => $ssmltext,
       OutputFormat => 'mp3');
     
    #-- write stream
    my $mp3;
    open($mp3, '>', "/home/fhem/ttsNew/".$file.".mp3");
    binmode($mp3);
    print $mp3 $res->AudioStream;
    close($mp3);
  }
}
 
#my %ttsMaxChar      = ("Google"     => 100,
#                       "VoiceRSS"   => 300,
#                       "SVOX-pico"  => 1000,
#                       "Amazon-Polly" => 3000
#                       );


my @ttsFiles=();
                                       
sub speak($$){
  my ($name,$text) = @_;
 
  #-- Telegram text, therefore local
  if($name =~ /Telegram.*/){
    telegramRecognition('botreply: ".$text."');
  #-- Bose, therefore local
  }elsif($name =~ /Sound.*/){
    # $text =~ s/ä/ae/g;
    # $text =~ s/ö/oe/g;
    # $text =~ s/ü/ue/g;
    # $text =~ s/Ä/Ae/g;
    # $text =~ s/Ö/Oe/g;
    # $text =~ s/Ü/Ue/g;
    # $text =~ s/ß/ss/g;
    speakBose($name,$text,"p");
  #-- Tablet, therefore distant
  }elsif($name =~ /(Tablet)|(GalaxyTab)|(MediaPad)/){   
    speakTablet($name,"$text");
  #-- HTC,SZ therefore reroutable ==> check here
  }elsif($name =~ /(HTC)|(SZ)/){
    if( (ReadingsVal("houseProfileC","housephase","") eq "daytime") && (Value("Bose_State") eq "On") ){
      speakBose("SoundTouch1.OG","$text","p");
    }else{
      speakTablet("HTC.OG","$text");
    }
  #-- WZ,MSG therefore reroutable ==> check in 193
  }elsif($name =~ /(WZ)|(MSG)|(Msg)/){
    if( Value("BOSE_XXXXXXXXXXXX") eq "playing" ){
      speakBose("SoundTouch.EG","$text","p");
    }else{
      speakTablet("GalaxyTab1.EG","$text");
    }
  }else{
    Log 1,"[speak] Error, Device $name unknown";
  }
}

sub speakTablet{
  my ($name,$text) = @_;
 
  #-- make it sound better
  $text =~ s/(\d)\.(\d)/$1,$2/g;
  $text =~ s/Jeannie/dschini/;
  $text =~ s/Jacqueline/dschacklihn/;
 
  #-- settings
  my $ttspath    = "/home/fhem";
  my $ttsDir     = "/home/fhem/tts/";
 
  fhem194Cmd("setreading SPEAK $name.out ".substr($text,0,12));
 
  #-- obtain list of prerecorded files
  opendir (DIR, $ttsDir);
  while (my $ttsFile = readdir(DIR)) {
    next if ($ttsFile !~ m/\.mp3$/);
      push(@ttsFiles,$ttsFile);
    }
  closedir(DIR);
 
  #-- combining prerecorded files and free text does not yet work
  #-- free text
  if( $text !~ /^\:(.*)\:$/ ){
    if( $name =~ /MediaPad.*/){
      fhem194Cmd("set $name ttsMsg ".$text);
    }else{
      fhem194Cmd("set $name ttsSay ".$text);
    }
  #-- prerecorded file
  }else{
    my $fname   = $1;
    my $ttsPFile = "";
    foreach my $k (@ttsFiles){
      if( $k =~ /$fname/ ){
        $ttsPFile = $k;   
        last;
      }
    }
    if($ttsPFile ne ""){
      Log 5,"[speakTablet] Filename $fname resolved as ".$ttsDir.$ttsPFile;
    }else{
      Log 5,"[speakTablet] Filename $fname not resolved";
    }
    if( $name =~ /MediaPad.*/){
      fhem194Cmd("set $name notifySndFile ".$ttsPFile);
    }else{
      fhem194Cmd("set $name audioPlay /mnt/sdcard/Notifications/".$ttsPFile);
    }
  }
}

sub speakBose{
  my ($name,$text,$ttsResource) = @_;
  my ($bid,$vol,$cmd,$bosecmd);
 
  #-- default voice
  $ttsResource = "p"
    if(!defined($ttsResource));
  my $ttsMaxChar = 3000;
 
  #-- default output EG
  if($name eq "SoundTouch.EG"){
    $bid = "BOSE_XXXXXXXXXXXXXXX";
    $vol = 25; 
  }elsif($name =~ /SoundTouch.?.OG/){
    $bid = "BOSE_XXXXXXXXXXXXXX";
    $vol = 25;
  }else{
    #$bid = "BOSE_XXXXXXXx";
    $bid = "BOSE_XXXXXXXXXXX";
    $vol = 25;
    $text= $name;
  }
 
  #-- command to restore old state
  $bosecmd = BOSERepsas($bid);
 
  #-- make it sound better
  $text =~ s/(\d)\.(\d)/$1,$2/g;
  $text =~ s/Jeannie/dschini/;
  $text =~ s/Jacqueline/dschacklihn/;
 
  fhem194Cmd("setreading SPEAK $name.out ".substr($text,0,12));
 
  #-- settings
  my $joiner     = "mp3wrap";
  my $ttspath    = "/home/fhem";
  my $ttsDir     = "/home/fhem/tts/";
  my $ttsCDir    = "/home/fhem/ttsCache/";
  my $ttsTarget  = "speech";
 
  #-- delete old file to outsmart miniDLNA caching
  unlink $ttsDir.$ttsTarget.".mp3";
  Log 1, "[speakBose] File ".$ttsDir.$ttsTarget.".mp3 could not be deleted"
    if(-e $ttsDir.$ttsTarget.".mp3");
 
  #-- obtain list of prerecorded files
  opendir (DIR, $ttsDir);
  while (my $ttsFile = readdir(DIR)) {
    next if ($ttsFile !~ m/\.mp3$/);
      push(@ttsFiles,$ttsFile);
    }
  closedir(DIR);
 
  #{Dumper(Text2Speech_SplitString(["Das ist ein Test"],10," ",0,"al"))}
  #{Dumper(Text2Speech_SplitString(["Das ist ein Test, in dem ein kleiner Teil <amazon:effect name=\"whispered\">geflüstert</amazon:effect> wird"],10," ",0,"al"))}
  #-- split text at word boundaries
  my @words      = split(' ', $text);
  my @speechlets = ();
  my $speechlet;
   
  my $i=0;
  my $j=0;
  while($i<int(@words)){
    last
      if( !$words[$i] );
    #-- word does not contain prerecorded filename, simply append words
    if( $words[$i] !~ /^\:(.*)\:$/ ){
      $speechlet="";
      while( (length($speechlet) + length($words[$i])) < $ttsMaxChar && $i<int(@words) ){
        $speechlet .= $words[$i]." ";
        $i++;
      }
      push(@speechlets,$speechlet);
      $j++;
      my $ttsKey   = md5_hex($ttsResource."|".$speechlet);
      my $ttsCFile = $ttsTarget."_".$ttsKey;
      my $found    = tts_dblog($ttsKey,$speechlet);

      #-- check if already exists     
      #if( -e $ttsCDir.$ttsCFile.".mp3" ) {
      if( $found == 1 ){
        Log 1,"[speakBose] Speechlet '".$speechlet."' already in cache as ".$ttsCDir.$ttsCFile.".mp3";
      }else{
        if( $ttsResource =~ /p.*$/ ){
          tts_polly($speechlet,$ttsCDir.$ttsCFile);
        }else{
          tts_google($speechlet,$ttsCDir.$ttsCFile);
        }
        Log 1,"[speakBose] Speechlet '".$speechlet."' obtained as ".$ttsCDir.$ttsCFile.".mp3";
      }
      $cmd .= $ttsCDir.$ttsCFile.".mp3 ";
     
    #-- word is prerecorded filename
    }else{
      my $name   = $1;
      my $ttsPFile = "";
      foreach my $k (@ttsFiles){
        if( $k =~ /$name/ ){
          $ttsPFile = $k;   
          last;
        }
      } 
      if($ttsPFile ne ""){
        $cmd .= $ttsDir.$ttsPFile." ";
        Log 5,"[speakBose] Filename $name resolved as ".$ttsDir.$ttsPFile;
      }else{
        Log 5,"[speakBose] Filename $name not resolved";
      }
      $i++; 
    }
  }
 
  #-- join speechlets and auxiliary files
  if( $joiner eq "sox" ){
    $cmd = "sox ".$ttsDir."silence_48_22050_1.mp3 ".$cmd." ".$ttsDir.$ttsTarget.".mp3" ;
  }elsif( $joiner eq "mp3wrap" ){
    $cmd = "mp3wrap ".$ttsDir.$ttsTarget.".mp3 ".$ttsDir."silence_48_22050_1.mp3 ".$cmd." > /dev/null";
    system($cmd);
    $cmd = "mv ".$ttsDir.$ttsTarget."_MP3WRAP.mp3 ".$ttsDir.$ttsTarget.".mp3";
  }else{
    Log 1,"[speakBose] No MP3 joiner defined, playing ".substr($cmd,0,index($cmd,' '));
    #-- todo: take out first file as filename and copy to speech.mp3
    $cmd = "cp ".substr($cmd,0,index($cmd,' '))." ".$ttsDir.$ttsTarget.".mp3";
  }
  Log 1,"[speakBose] duration of final file ".tts_duration($ttsDir.$ttsTarget.".mp3");
  system($cmd);

  #-- play it
  fhem("set $bid volume $vol;set $bid playTrack speech");
 
}

sub tts_dblog($$){
  my ($key,$text) = @_;
  #-- Create database by
  #  sqlite3 tts.db "CREATE TABLE tts (key INTEGER PRIMARY KEY, count INT, time INT, content TEXT);"
  #  chown fhem:dialout tts.db
  #--
  my $path = "/home/fhem";
  my $dbargs = {AutoCommit => 0, PrintError => 1};
  my $dbh = DBI->connect("dbi:SQLite:dbname=".$path."/tts.db", "", "", $dbargs);
 
  #-- check existence
  my ($res) = $dbh->selectrow_array("SELECT EXISTS ( SELECT 1 FROM tts WHERE key='".$key."')");
  #-- exists
  if( $res == 0 ){
    #-- insert a line
    $dbh->do("INSERT INTO tts (key,count,time,content) VALUES ('".$key."','1','".time()."','".$text."');");
    if ($dbh->err()) {
      Log 1,"[tts_dblog] $DBI::errstr";
    }
  #-- does not exist
  }else{
    #-- modify
    $dbh->do("UPDATE tts SET count = count + 1 WHERE key='".$key."';");
    if ($dbh->err()) {
      Log 1,"[tts_dblog] $DBI::errstr";
    }
  }
  $dbh->commit();
  $dbh->disconnect();
  return $res;
}

sub tts_dbshow(){
  #--
  my $path   = "/home/fhem";
  my $dbargs = {AutoCommit => 0, PrintError => 1};
  my $dbh    = DBI->connect("dbi:SQLite:dbname=".$path."/tts.db", "", "", $dbargs);
  my $ret    = "";

  #-- print rows
  my $res = $dbh->selectall_arrayref("SELECT key,count,time,content FROM tts;");
  foreach my $row (@$res) {
    my ($keyr,$countr,$timer,$textr) = @$row;
    $ret .= sprintf("%s %d %d %s\n",$keyr,$countr,$timer,$textr);
  }
  $dbh->disconnect();
  return $ret;
}

sub tts_dbpurge($$){
  my ($deltime,$mincount) = @_;
  #--
  my $path   = "/home/fhem";
  my $dbargs = {AutoCommit => 0, PrintError => 1};
  my $dbh    = DBI->connect("dbi:SQLite:dbname=".$path."/tts.db", "", "", $dbargs);

  if( defined($deltime) && $deltime > 0){
    my $earliest = time() - 86400*$deltime;
    $dbh->do("DELETE from tts where time < ".$earliest.";");
    if ($dbh->err()) {
      Log 1,"[tts_dblog] $DBI::errstr";
    }
  }elsif( defined($mincount) && $mincount > 0){
    $dbh->do("DELETE from tts where count < ".$mincount.";");
    if ($dbh->err()) {
      Log 1,"[tts_dblog] $DBI::errstr";
    }
  }
  $dbh->disconnect();
}

sub tts_polly($$){
  my ($texti,$file) = @_;
    #-- we may have problems with umlaut characters
  my $converter = Text::Iconv->new("utf-8", "iso-8859-1");
  my $text = $converter->convert($texti);
 
  #<break time="1s"/>
  my $ssmltext = '<speak>'.$text.'</speak>';
 
  #-- obtain speechlet
  my $polly = Paws->service('Polly', region=>'eu-central-1');
  my $res = $polly->SynthesizeSpeech(
     VoiceId => 'Marlene',
     TextType=> 'ssml',
     Text => $ssmltext,
     OutputFormat => 'mp3');

  #-- write stream
  my $mp3;
  open($mp3, '>', $file.".mp3");
  binmode($mp3);
  print $mp3 $res->AudioStream;
  close($mp3);
}

sub tts_google($$){
  my ($text,$file) = @_;
  #-- obtain speechlet
  system("wget -q --user-agent='Mozilla/5.0' \'http://translate.google.de/translate_tts?ie=UTF-8&tl=de&client=tw-ob&q=$text\' -O $file.mp3");


sub tts_duration($) {
  my $time;
  my ($file) = @_;
  eval {
    use MP3::Info;   
    my $tag = get_mp3info($file);
    if ($tag && defined($tag->{SECS})) {
  $time = int($tag->{SECS}+0.5);
    }
  };
  if ($@) {
    return undef;
  }
  return $time;
}


Bei Gelegenheit gibt es auch noch eine Anleitung dazu. Wer schon einsteigen will: paws installieren und einen Amazon-Account beantragen - oder über google gehen.

LG

pah


Eisix

Hallo,

habe aus meine Soundtouch 10  auch eine Squeezebox gemacht. Hab eine Raspi Zero mit Max2Play drauf am AUX. Das funktioniert wenigstens ohne Probleme. Leider reicht die Leistung am USB-Wartungsport nicht um den Raspi vernünftig zu betreiben.

Gruß
Eisix

rakete123

Zitat von: Eisix am 05 September 2019, 11:03:13
Hallo,

habe aus meine Soundtouch 10  auch eine Squeezebox gemacht. Hab eine Raspi Zero mit Max2Play drauf am AUX. Das funktioniert wenigstens ohne Probleme. Leider reicht die Leistung am USB-Wartungsport nicht um den Raspi vernünftig zu betreiben.

Gruß
Eisix

Ach schade auch nicht für den Zero? Alles probiert?
Zwave: ZMEEUZB1 (Fibaro, Aeotec, diverse)
Zigbee: Conbee (HUE, Xiaomi, osram)
Homematic: HM-MOD-RPI-PCB + diverse HM-CC-RT-DN
Sonstiges: Harmony, Android, Netatmo, Jabber (talk2fhem)
https://resize2fs.de

Eisix

Hallo,

hab es mit eine Zero W probiert und das war bei mir nicht stabil. Da der Zero keine Klinke hat habe ich einen HiFi DAC HAT drauf gesetzt und dann war die Leistungsaufnahme zu hoch für den Port. In der Bose Doku steht der Port liefert 0,5 A. Vielleicht gibt der Port der 300 mehr her. Zusammengefaßt Zero W ohne alles am Port lief bei mir aber mit HAT geht nicht.
Was vielleicht noch machbar ist ohne HAT wäre über Bluetooth zu verbinden.

Gruß
Eisix

PS: Sorry für Off Topic

Prof. Dr. Peter Henning

#591
Seit einigen Tagen - mutmaßlich seit dem letzten Update - habe ich das Problem, dass das BOSEST-Modul die Verbindung zu den Bose-Geräten verliert, und diese auch nicht wiederfindet. Lediglich ein Restart von FHEM findet sie dann erfolgreich wieder. Beobachtet das sonst noch jemand ?

Edit: Das ist kein WLAN-Problem - meine ST300 ist via Ethernet angebunden. Handelt sich also um einen Fehler in BOSEST.
EditEdit: Noch keine Lösung dieses Problems gefunden - irgendein Problem in den Bibliotheken, mit denen BOSEST kommuniziert.

LG

pah

fred_feuerstein

Das gleiche Problem habe ich hier auch mit den 4 bose Geräten in fhem.
Nur restart von fhem hilft.
Kam früher nur hin und wieder mal vor. Seit ein paar Wochen recht häufig...
Gruß, Fred

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

Prof. Dr. Peter Henning

#593
Ich bin dem Problem auf der Spur. Offenbar hat Bose im letzten Software-Update etwas eingebaut, das die Verbindungen nach einiger Zeit lahmlegt. Das betrifft sowohl die generelle Verbindung zum Netz, als auch den Websocket zum BOSEST-Modul.

Das erste Problem kann man ganz einfach beheben: Ein PRESENCE-Device mit lan-ping alle 120 Sekunden sorgt dafür, dass die Bose-Box sich nicht komplett aus dem WLAN verabschiedet. Jetzt muss ich nur noch das BOSEST-Modul dazu bringen, ebenfalls in regelmäßigen Abständen eine Statusanfrage an die Box zu senden.

LG

pah

Edit: Derzeit bin ich skeptisch, ob mit dem eingesetzten Mojolicious Framework dieser Fehler beseitigt werden kann. Möglicherweise muss man das mit einem schlankeren Websocket-Client neu aufsetzen.


fred_feuerstein

Würde es was bringen, wenn man alle 2 bis 3 Minuten genauso als workaround über BOSEST die volume um +1 und - 1 abwechselnd verändert? Klar, wäre nur ein workaround, aber so käme immer eine Abfrage vom Modul zur Box. Und +1 - 1 würde man eher kaum merken.
Gruß, Fred

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

Prof. Dr. Peter Henning

k.A., ausprobieren. Stehen die IP-Adressen der Boxen im "staticIP" Attribut?

LG

pah

fred_feuerstein

#596
die automatische Erkennung funktioniert eigentlich bei mir. Deshalb habe ich das Attribut wie im commandref steht noch nicht probiert.
Hast Du das bei Dir gesetzt?

Werde mal ein DOIF auf die Bose-Boxen loslassen, was alle paar Minuten mal die Lautstärke regelt. Mal schauen ob es damit besser wird.

Edit:
So, also habe die Bose-Boxen per Presence lan-ping alle 120 Sekunden dabei und ausserdem wird alle 120 Sekunden die Lautstärke per set abwechseln +1 und -1 geregelt.
Nun gilt es abwarten, ob das Problem noch auftritt...
Gruß, Fred

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

Supadone

Ich hatte die letzten Tage auch immer wieder das Problem dass sich die Bose Lautsprecher nicht über Fhem steuern ließen. Hab heute Mojolicious auf 8.260 geupdatet, seit dem läufts bisher ohne Probleme

Prof. Dr. Peter Henning

Sieh an, ein neues Mitglied - und landet gleich einen Treffer, gratuliere.

Erklärt das Problem zwar nicht, aber scheint es zu beheben.

Wobei ich auch die IP-Adressen meiner Bose-Geräte aus dem Attribut entfernt habe, das verhindert nämlich den "Discover"-Prozess über das Bonjour-Framework.


LG

pah

fred_feuerstein

#599
Nochmal ergänzend zur dem workaround.

Seit der PRESENCE Abfrage und dem zyklischen volume schalten hatte ich das Problem auch nicht mehr.
Das scheint auch zu funktionieren.

//edit
nun auch auf 8.26 aktualisiert. Dann schalte ich mal die Abfragen alle wieder ab und teste.
Gruß, Fred

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