Ankündigung

Einklappen
Keine Ankündigung bisher.

Musik über Spotify automatisch abspielen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Musik über Spotify automatisch abspielen

    Hallo,

    vielleicht kann mir bei meinem aktuellen Projekt jemand weiterhelfen..

    Ich hab im Badezimmer einen Deckenlautsprecher eingebaut, der an einem kleinen Verstärker inkl. Bluetooth, angeschlossen ist. Momentan muss ich mich also jedesmal mit dem Gerät verbinden und dann die Musik über das Handy abspielen.
    Nun will ich das günstig in mein KNX System implementieren (Szene Duschen --> Licht + Lüfter + Musik EIN).

    Mein eigentlicher Ansatz wäre folgender gewesen:
    • RaspberryPi mit Klinkenstecker zum Verstärker fix in die Decke
    • raspotify auf RaspberryPi
    • Spotify-TUI auf RaspberryPi
    • Node-Red auf RaspberryPi
    • RaspberryPi über WLAN im Heimnetzwerk und somit Zugriff auf die KNX Schnittstelle
    • Szene wird von Taster auf Bus geschickt --> weiter zu NodeRed --> NodeRed startet mit Spotify-TUI die Musikwiedergabe
    Hab bereits alles Installiert und funktioniert auch soweit, ich hab jetzt nur noch das Problem, dass ich nicht weiß wie ich NodeRed und Spotify-TUI kombinieren kann, da ja NodeRed zuerst das richtige Device auswählen muss und dann noch das Abspielen starten/stoppen muss..

    Oder hat eventuell noch jemand eine adere Idee wie ich das relativ günstig realisieren kann (mit Spotify, also kein USB-Stick oder dergleichen in der Decke). Ein Bus-Kabel hätte ich beim Lautsprecher ebenfalls zur Verfügung.

    #2
    Ein sehr ähnliches Thema gab es hier: https://knx-user-forum.de/forum/supp...mdt-glastatser

    Mit NodeRed bin ich da nicht zum Ziel gekommen, mit OpenHab auch leider nur teilweise. Ich bin nicht sicher, ob die Aufgabe wirklich mit OpenSource Tools lösbar ist.

    Problem: Sobal das Zieldevice einmal angesprochen wurde, kennen Spotify und OpenHab das Objekt und du kannst via SpotifyConnect arbeiten (OpenHab verbindet dabei Spotify und KNX). Aber: Bei meinen Tests sind die Zielgeräte bei Spotify (und damit bei OpenHab) immer nach einiger Zeit aus der Liste gefallen, sobald ich diese ein paar Stunden nicht angesprochen habe. Ich würde daher vernuten, dass die Lösung ohne Sonos (die das technisch wohl anders regeln) nicht dauerhaft fliegen wird, ausser du lässt den RPi dauerbestromt und das Objekt damit präsent bleiben...aber dann brauchst du für das Bad einen eigenen Spotify Account, da der ja ständig belegt wäre.

    Good Luck

    Cu
    Frank

    Kommentar


      #3
      Bei mir funktioniert mopidy als Musikplayer auf Linux mit lineout und Spotify, gesteuert über websocket aus ip-symcon ganz gut.

      Kommentar


        #4
        Zitat von tobiasr Beitrag anzeigen
        Bei mir funktioniert mopidy als Musikplayer auf Linux mit lineout und Spotify, gesteuert über websocket aus ip-symcon ganz gut.
        Bist du so nett und postest mal deine Lösung im Detail, wenn das per ip-Symcon geht? Würde dem Themenstarter sicher konkreter helfen ;-) (und ich lerne auch gerne dazu!)

        Cu
        Frank

        Kommentar


          #5
          Also Mopidy aus den Paketquellen installiert und über das eingebaute Webinterface Spotitfy konfiguriert. http://mopidyHost:6680/iris/settings

          Das IP-Symcon PHP Script ist folgendes. Es benötigt eine Websocket Instanz, welche über die Meta Funktion WSC_SendText angesprochen wird. Ähnlich lässt sich das sicherlich auch über NodeRed lösen.

          PHP-Code:
          <?php

          // Lautstärke in verstärker ändern /AUDIO/OUT/4/VOL 0  --- /AUDIO/OUT/4/VOL -1 


          $mopidy_ws 23057;
          // Radio Playlists 
          $werte_playlist = array( => 'https://swr-swr3-live.cast.addradio.de/swr/swr3/live/mp3/128/stream.mp3'// swr3.m3u
                                      
          => 'http://81.92.238.32:80/',  // rtl.m3u
                                      
          => 'http://wdr-wdr2-ruhrgebiet.icecast.wdr.de/wdr/wdr2/ruhrgebiet/mp3/128/stream.mp3',      // wdr2-ruhrgebiet.m3u
                                      
          => 'http://www.ndr.de/resources/metadaten/audio/m3u/ndr2.m3u'// ndr2.m3u
                                      
          => 'http://www.slayradio.org/tune_in.php/56kbps/slayradio.56.m3u'// slayRadio
                                    
          104 => 'spotifylaylist:49UZ2W6CsBvfj7Yb11Kd3g'// Spotify PL A
                                    
          105 => 'm3u:SymconLocal1.m3u8'// Local Playlist 1 (Test)
                                    
          106 => 'm3u:SymconLocal2.m3u8'// Local Playlist 2 (Mathias)
                                      
          ); 


           
          $werte_status = array(=> 'core.playback.play'=> 'core.playback.pause'=> 'core.playback.stop');
           
          $werteStatusReverse = array('paused' => 2'stopped' => 3'playing' => 1);


          // Änderung über Webinterface getriggert
          if ($_IPS['SENDER'] == "WebFront") {
              
          RequestAction($_IPS['VARIABLE'], $_IPS['VALUE']);
          }
          if (
          $_IPS['SENDER'] == "WebHook") {
              
          IPS_LogMessage("Script ".$_IPS['SELF'],"Webhook Get ".print_r($_GET,true));
              
          $uri $_GET['playlist'] ?? "";
              
          $id generateRequest('startSpotifyPlaylist');
              
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": '.$id.', "method": "core.playlists.get_items", "params": {"uri": "' .$uri .'"}}');
          }
          // Request Action auf Variable ausgeführt
          if($_IPS['SENDER'] == "Action"){
              switch(
          $_IPS['VARIABLE']){
                  
          case21704 :
                  
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.mixer.set_volume", "params": {"volume": '.$_IPS['VALUE'].'}}');
                      break;
                  
          case53743 :
                      if (
          $_IPS['VALUE'] == 0/* Aus */) {
                          
          // Aus -> Stop
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.stop"} ');
                      } elseif (
          $_IPS['VALUE'] >= 100/* Playlists: Spotify, Local, etc */) {
                          
          //Hier wird eine Lokale Playlist oder Spotify gestartet
                          
          $id generateRequest('startSpotifyPlaylist');
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": '.$id.', "method": "core.playlists.get_items", "params": {"uri": "' .$werte_playlist[$_IPS['VALUE']] .'"}}');
                      } else {
                          
          // Radio Sender abspielen
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.tracklist.clear"} ');
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.tracklist.add", "params": {"uris": ["' .$werte_playlist[$_IPS['VALUE']] .'"]}}');
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.play"} ');
                          
          SetValue($_IPS['VARIABLE'], $_IPS['VALUE']);
                      }
                      
          SetValue($_IPS['VARIABLE'], $_IPS['VALUE']);
                      break;
                  
          case54384 :
                      switch (
          $_IPS['VALUE']) {
                          
          case0:
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.previous"} ');
                          break;
                          
          case1:
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.play"} ');
                          break;
                          
          case2:
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.pause"} ');
                          break;
                          
          case3:
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.stop"} ');
                          break;
                          
          case4:
                          
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.next"} ');
                          break;
                      }
                      break;
                  
          case26053 :
                      
          $prozent $_IPS['VALUE'];
                      
          $geslan GetValueInteger(24151);
                      
          $pos = (int) ($prozent $geslan /100);
                      
          //IPS_LogMessage("Liedposition ".__LINE__, "Value: ".$_IPS['VALUE']." Länge in 'Liedposition': ".$geslan." berechnet: ".$pos);
                      
          WSC_SendText($mopidy_ws'{"method":"core.playback.seek","params":{"time_po sition":'.$pos.'},"jsonrpc":"2.0","id":1230}');
                      break;
                  
          case52296:
                      
          $value = ($_IPS['VALUE']) ? "true" "false";
                      
          WSC_SendText($mopidy_ws'{"method":"core.tracklist.set_repeat","params":['.$value.'],"jsonrpc":"2.0","id":178}');
                      break;
                  
          case45202 :
                      
          $value = ($_IPS['VALUE']) ? "true" "false";
                      
          WSC_SendText($mopidy_ws'{"method":"core.tracklist.set_random","params":['.$value.'],"jsonrpc":"2.0","id":178}');
                      break;
              }

              
          //
                  

          }

          // Daten von Mopidy Empfangen
          if ($_IPS['SENDER'] == "RegisterVariable") {
              
          $mopidygesendet json_decode ($_IPS['VALUE'], true);
              
          //IPS_LogMessage ("jsonLog ".__LINE__, print_r ($mopidygesendet, true)); 
              
          if (isset($mopidygesendet ['event'])) {
                  switch (
          $mopidygesendet ['event']) {
                      case
          'volume_changed':
                          
          SetValueInteger (21704$mopidygesendet['volume']);
                      break;
                      case
          'stream_title_changed':
                          
          SetValueString (58333$mopidygesendet['title']);
                          break;
                      case
          'playback_state_changed':
                          
          // Aktueller Status play/pause/stop wird gesendet
                          
          SetValueInteger (54384$werteStatusReverse[$mopidygesendet['new_state']]); // Umwertung von Text in Symcon Variablen Wert ID

                          
          if($mopidygesendet['new_state'] == 'playing' && GetValue(53743) >= 4/* Playlist */ ){
                              
          // Wenn play und Quelle nicht Webradio, Anfrage-Timer aktivieren
                              
          IPS_SetScriptTimer($_IPS['SELF'], 1);
                          }elseif(
          $mopidygesendet['new_state'] == 'paused'){
                              
          IPS_SetScriptTimer($_IPS['SELF'], 0);
                          }else{
                              
          IPS_SetScriptTimer($_IPS['SELF'], 0);
                              
          SetValueInteger(26053,0); // bei stop oder play mit Radio Position auf 0 setzen
                          
          }
                          break;
                      case
          "track_playback_started":
                          
          // aktueller Track hat sich geändert. Titel , Interpret und Liedlänge auslesen
                          
          $title $mopidygesendet['tl_track'] ['track'] ['name'];

                          
          // Künstler, ggf. mehrere Zusammensetzen
                          
          $countArtists sizeof($mopidygesendet['tl_track'] ['track'] ['artists']);
                          
          $artist $mopidygesendet['tl_track'] ['track'] ['artists'] [0] ['name'];
                          for(
          $i 1$i<$countArtists$i++) {
                              if ((
          $i+1) == $countArtists) {
                              
          $artist .= ' und ';
                              }
                              else {
                                  
          $artist .= ', ';
                              }
                              
          $artist .=$mopidygesendet['tl_track'] ['track'] ['artists'] [$i] ['name'];
                          }
                          
          SetValueString (58333$title .' von ' .$artist); // Titel und Künstler in Variable schreiben
                          
          SetValueInteger (24151$mopidygesendet['tl_track'] ['track'] ['length']); // Liedlänge zwischenspeichern, wird benötigt um aktuelle Liedposition in % anzuzeigen
                          //if ($title == "Wires") RequestAction(37303, true); // Test, wenn  Wires von The Neighbourhood in die Warteschlange ist, wird Lüfter Büro links eingeschaltet
                          
          break;
                      case
          "options_changed":
                          
          // Wird ausgelöst, wenn Repeat, Random, Consume (gehörte Lieder aus Playlist löschen) geändert wird. Dann Abfrage des neuen Status starten
                         //WSC_SendText($mopidy_ws, '{"method":"core.tracklist.get_consume","params":{ },"jsonrpc":"2.0","id":'.generateRequest('core.tra cklist.get_consume').'}');
                         
          WSC_SendText($mopidy_ws'{"method":"core.tracklist.get_random","params":{} ,"jsonrpc":"2.0","id":'.generateRequest('core.tracklist.get_random').'}');
                         
          WSC_SendText($mopidy_ws'{"method":"core.tracklist.get_repeat","params":{} ,"jsonrpc":"2.0","id":'.generateRequest('core.tracklist.get_repeat').'}');

                  }
              }elseif (isset(
          $mopidygesendet ['result'])) {
                  
          // Daten kommen vmtl aus vorheriger Abfrage, prüfen, ob zur ID ein Datensatz besteht:
                  
          $id $mopidygesendet['id'];
                  
          $buffer_string RegVar_GetBuffer(56414);
                  
          $buffer json_decode($buffer_stringtrue);
                  
          //IPS_LogMessage("RegVar ". __LINE__, print_r($buffer, true));
                  
          if(isset($buffer[$id])){
                      switch (
          $buffer[$id]){
                          case
          'core.playback.get_time_position':
                              
          // Liedpositionsanzeige ist als 100% ausgeführt. Dieses Code empfängt die Antwort der aktuellen Position und rechnet in 0-100% um.
                              
          $zeit $mopidygesendet ['result'];
                              
          $geslan GetValueInteger(24151);
                              
          //IPS_LogMessage("Zeitberechnung", "pos: ".$mopidygesendet ['result'] . "   Gesl: ".$geslan ." errechnet: ".($zeit/$geslan*100));
                              
          if($geslan >0){
                                  
          SetValueInteger(26053, (int) ($zeit/$geslan*100));
                              }
                              break;
                          case
          'startSpotifyPlaylist':
                              
          // Playlist wurde angefordert. Mopidy sendet eine Liste mit allen enthaltenen Liedern. Diese müssen dann dem Player hinzugefügt werden
                              
          foreach($mopidygesendet['result'] as$key => $value){
                                  
          $var[] = $value['uri'];
                              }
                              
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.tracklist.clear"} ');
                              
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.tracklist.add", "params": {"uris": ' json_encode($var) .'}}');
                              
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": 1, "method": "core.playback.play"} ');
                             break;

                          
          // {"jsonrpc": "2.0", "id": $id, "result": false / true}
                          
          case'core.tracklist.get_repeat':
                              
          SetValue(52296$mopidygesendet['result']);
                              break;
                          case
          'core.tracklist.get_random':
                              
          SetValue(45202$mopidygesendet['result']);
                              break;
                          case
          'ListPlaylist'// Liste an Playlists in HTML Variable
                          //.ipsCategory > .container .content .visual > .enum > div,
                             // $out = '<div class="ipsContainer container nestedEven ipsVariable ipsVariableProfile[ELA.Gong]"><div class="content tr"><div class="ipsContainer enum">';
                             
          $out="<script>
                             var items = document.getElementsByClassName("
          playlist")
                             for (var i = 0; i < items.length; i++) {
                                  items[i].addEventListener('click', showAlert);
                              }
                             function showAlert() { 
                                 var elem = event.target,
                                      uri = elem.getAttribute ('hidden');  
                                      var HTTP = new XMLHttpRequest();
                                          HTTP.open("
          GET","/hook/changePlaylist?playlist=" + uri,true);
                                          HTTP.send(); }</script>
                             
                              "
          ;
                              
          $out.= '<div class="content"><div class="visual"><div class="ipsContainer enum" style="height:100%;">';
                              foreach(
          $mopidygesendet['result'] as$key => $value){
                                  
          $out.= "<div hidden="{$value['uri']}"class="playlist">{$value['name']}</div>";
                              }
                              
          $out.="</div></div></div>";
                              
                              
          //<div class="ipsCategory"><div class="container"></div><div class="visual"><div class="enum">
                              
          SetValueString(32092$out);
                      }
                      unset(
          $buffer[$id]); // aktuelle Anfrage ID aus Buffer entfernen
                  
          }else{
                      
          // Daten nicht im Buffer, zu Testzwecken von neuen Funktionen
                      // IPS_LogMessage("unbekannter Datensatz ".__LINE__, print_r($mopidygesendet,true));
                  
          }
                  
          // Buffer ggf. um aktuelle Anfrage reduziert wieder speichern
                  
          RegVar_SetBuffer(56414json_encode($buffer));
              }else{
                      
          // Daten nicht im Buffer, zu Testzwecken von neuen Funktionen
                      // IPS_LogMessage("unbekannter Datensatz ".__LINE__, print_r($mopidygesendet,true));
                  
          }
          }

          if (
          $_IPS['SENDER'] == "TimerEvent") {
              switch(
          $_IPS['EVENT']){
                  
          case15805:
                      
          // 1x täglich neuladen der verfügbaren Playlisten
                      
          $id generateRequest('ListPlaylist');
                      
          WSC_SendText($mopidy_ws'{"jsonrpc": "2.0", "id": '.$id.', "method": "core.playlists.as_list"}');
                  break;
                  
          case19254
                      
          // Wenn Musikstatus auf Play und Playlist (also kein Radiostream), ist ein Timer gestartet und dieser führt u.s. Code aus. Dadurch wird die aktuelle Songposition abgefragt
                      
          $zaehler generateRequest('core.playback.get_time_position');
                      
          WSC_SendText($mopidy_ws'{"method":"core.playback.get_time_position","para ms":{},"jsonrpc":"2.0","id":'.$zaehler.'} ');
                  break;
              }
          }
          if(
          $_IPS['SENDER'] == "Execute"){
              
          // wenn dieses script per Hand im Scripteditor gestartet wird, setzt man die Buffer Variable zurück. Im Fehlerfall notwendig
              
          RegVar_SetBuffer(56414 ,"");
              
          print_r(RegVar_GetBuffer(56414));

              
          // Test zum Bau einer Playlist-Liste
              //$id = generateRequest('ListPlaylist');
              //WSC_SendText($mopidy_ws, '{"jsonrpc": "2.0", "id": '.$id.', "method": "core.playlists.as_list"}');
              
          }


          // Diese Funktion speichert im Buffer den Typ der aktuellen Anfrage und gibt eine eindeutige ID zurück
          // Eingabe: Typ der Anfrage
          // Rückgabe: (int) RequestID 
          function generateRequest ($typ){
              
          $zaehler rand(1,500);
              
          $buffer_string =  RegVar_GetBuffer(56414);
              
          $buffer json_decode($buffer_stringtrue);
              if(
          sizeof($buffer)>20$buffer=array(); // Wenn mehr als 20 Anfragen offen, Wahrscheinlichkeit auf alte Antworten sehr gering. Anfragebuffer leeren.
              
          $buffer[$zaehler] = $typ;
              
          $buffer_string json_encode($buffer);
              
          RegVar_SetBuffer(56414$buffer_string);
              
          //IPS_LogMessage("Reg Buff ".__LINE__, $buffer_string);
              
          return $zaehler;
          }
          Achtung: Einerseits müssen natürlich selbst für die IP-Symcon Nutzer die Variablen IDs angepasst werden, andererseits hat das Forum ein paar Leerzeichen verschluckt.

          Kommentar


            #6
            Top, danke :-)

            Kommentar

            Lädt...
            X