This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

SONOS app
Hi,

Just tested it on my Sonos and it works as it should..

This is the command i used:

Code:
-- Load modules
require('socket.http')

-- Set timout
socket.http.TIMEOUT = 5

-- Start say command - xxx.xxx.xxx.26 = my Sonos and xxx.xxx.xxx.203 = my homeLYnk
socket.http.request('http://127.0.0.1/apps/data/sonos/sonos.lp?action=say&ip=192.168.10.26&audiofile=http://192.168.10.203/user/deurbel.mp3&volume=50&duration=10')

BR,

Erwin
Reply
(24.09.2017, 08:18)Erwin van der Zwart Wrote: Hi,

Just tested it on my Sonos and it works as it should..

This is the command i used:

Code:
-- Load modules
require('socket.http')

-- Set timout
socket.http.TIMEOUT = 5

-- Start say command - xxx.xxx.xxx.26 = my Sonos and xxx.xxx.xxx.203 = my homeLYnk
socket.http.request('http://127.0.0.1/apps/data/sonos/sonos.lp?action=say&ip=192.168.10.26&audiofile=http://192.168.10.203/user/deurbel.mp3&volume=50&duration=10')

BR,

Erwin

Thanks Erwin,
I have been using the same code as you but it does not work. Tried again, but this time increasing the duration time.... and that seem to have some effect.

socket.http.request('http://10.0.1.51/apps/data/sonos/sonos.lp?action=sayall&audiofile=http://10.0.1.51/user/doorbell.mp3&volume=30&duration=5') Changed duration to 30 made a difference...

Since the change in code i am (as mentioned before) experiencing a lag when loading a file from local source in the spacelynk. I have tried to use the sayall function together with loading a playlist instead, but I just can't get the command correct (keep getting false as a return value). This is the code I am using....

'http://10.0.1.51/apps/data/sonos/sonos.lp?action=sayall&loadplaylist&listnumber=11&volume=30&duration=10&autoplay=true'

Is there a error in my command?

BR
Mr.D
Reply
Hi,

The combination you are trying to make is not implemented in the API.

You have to pass a audiofile location.

BR,

Erwin
Reply
Hi,

Nice to know Smile

Just a quick question.
When you run your command. Does the Sonos speakers play straight away, or does it take some time before the Sonos players are grouped and the sound actually starts to play?

For my part it takes about 17 seconds from sending the command, and until there is any sound.... thus keeping a duration time of 10 seconds is not possible since it terminates before any sound has been created.... 

BR
Mr.D
Reply
Hi,

The only thing that is happening is that the current track and play + volume state is stored, the audiofile is loaded and played, and after playingtime is passed the current track is loaded again and play state + volume gets restored as before say command. There is no grouping as those are already known in the system

In my original version it was pretty fast but latest versions are done by our development and not myself.

I have asked them to check this out.

BR,

Erwin
Reply
Hi,

Your right, there is no grouping Smile
I would say that it was WAY faster when your version was running.
Hopefully they will fix the lag. I use this for my doorbell and from somebody pushes the doorbell and until we hear something it has already gone 20 seconds.... and if we are a bit slow to respond, the guys outside are "gone" by the time we get to the front door Smile hahaha

Is there a way to roll back to your version?

BR,
Mr.D
Reply
Hi,

No there is no way to roll back to old version, but what i can do is to extract this function to plain LUA so you can run it from event script.

Lets wait what development says.

BR,

Erwin
Reply
Hi,

Ok Smile
Thanks for your help!!

BR,
Mr.D
Reply
Hi,

I've got a problem getting feedback from my Sonos speakers to my homelynk (FW 2.0.1).
I took the script from the end of page 4 of this thread, pasted it into costom java script and adjusted plan ID's and IP's, inserted the visualisation example from page 3 to test it.
The feedback does not work at all. In the app (Version 20170825) it is working perfectly, commands from KNX adresses via lua scripts are working too.

If I try to get feedback from the lua script on page 1 by sending value 255, it is also not working (i get the error message "User script:82: attempt to index a nil value stack traceback: User script:82: in main chunk").

Is this an authentification problem?
Do I have to put credentials into this script?
Has anything changed in commands or paths so it has to be changed in the script too?
Has anyone similar problems?

Thanks a lot,

Marc
Reply
Hi,

Development changed the feedback from polling to Sonos event services, it could be they removed the command to fetch (poll) the feedback as it was no longer needed..

I will check later today if that’s the case.

BR,

Erwin
Reply
Hi Erwin,

did you find out if the command has been removed?

BR

Marc
Reply
Hi Marc,

No, i just tested it and the command is still available, but i noticed they have changed the structure of the response, that's why you got errors:

Here is the script changed to current response:
Code:
$(function(){ 
  setInterval(function(){
    // Only poll if current page = 1
    //console.log(currentPlanId)
    var sonosip = "127.0.0.1"
    if (currentPlanId == 1 || currentPlanId == 2 || currentPlanId == 3  ){
      if (currentPlanId == 1 ) {
          sonosip = "192.168.10.26"
      }
      if (currentPlanId == 2 ) {
          sonosip = "192.168.10.27"
      }
      if (currentPlanId == 3 ) {
          sonosip = "192.168.10.28"
      }
      // Request data from sonos API
      $.post("/apps/data/sonos/sonos.lp",
      { action: "getextendedstate", ip: sonosip },
      function(data) {
      var res_parsed = JSON.parse(data);
        if (typeof data !== 'undefined'){
          //console.log(res_parsed)

          var protocolinfo = res_parsed.TrackUri.match("x(.*)://");
          //console.log(protocolinfo[0])

          // Update text label with additional class 'volume'
          $("#plan-" + currentPlanId).find(".volume").html(res_parsed.Volume + ' %');

          // Update text label with additional class 'mute'
          $("#plan-" + currentPlanId).find(".mute").html(res_parsed.Mute);

          // Update text label with additional class 'crossfade'
          $("#plan-" + currentPlanId).find(".crossfade").html(res_parsed.Crossfade);

          // Update text label with additional class 'playmode'    
          $("#plan-" + currentPlanId).find(".playmode").html(res_parsed.Playmode);

          // Update text label with additional class 'transport'
          $("#plan-" + currentPlanId).find(".transport").html(res_parsed.TransportState);

          // Update text label with additional class 'trackuri'
          $("#plan-" + currentPlanId).find(".trackuri").html(res_parsed.TrackUri);

          // Update text label with additional class 'duration'
          $("#plan-" + currentPlanId).find(".duration").html(res_parsed.TrackDuration);

          // Update text label with additional class 'playingtime'
          $("#plan-" + currentPlanId).find(".playingtime").html(res_parsed.Playingtime);

          // Update text label with additional class 'tracktitle'
          $("#plan-" + currentPlanId).find(".tracktitle").html(res_parsed.TrackTitle);

          // Update text label with additional class 'creator'
          $("#plan-" + currentPlanId).find(".creator").html(res_parsed.Creator);

          // Hide Album when mediatype = radio
          if (res_parsed.MediaType == 'radio'){
            $("#plan-" + currentPlanId).find(".album").css( "display", "none" );
          } else {
            $("#plan-" + currentPlanId).find(".album").css( "display", "block" );
            // Update text label with additional class 'album'
            $("#plan-" + currentPlanId).find(".album").html(res_parsed.Album);
          }

          // Update image container with additional class 'albumart'
          $("#plan-" + currentPlanId).find(".albumart").find("img").attr('src', res_parsed.AlbumArt);

          // Update text label with additional class 'mediatype'
          $("#plan-" + currentPlanId).find(".mediatype").html(res_parsed.MediaType);
          //$("#plan-" + currentPlanId).find(".trackuri").html(res_parsed.TrackUri);
          //$("#plan-" + currentPlanId).find(".trackurimetadata").html(res_parsed.TrackMetadata);

          //$("#plan-" + currentPlanId).find(".sonosplayerip").html(res_parsed.ip);

          function FormattedTimeToSeconds(formattedtime) {
            var a = formattedtime.split(':'); // split it at the colons
            // minutes are worth 60 seconds. Hours are worth 60 minutes. 
            var seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]); 
            return seconds;
          }

          var passed = 0;
          var durationseconds = FormattedTimeToSeconds(res_parsed.TrackDuration);
          var playingtimeseconds = FormattedTimeToSeconds(res_parsed.PlayingTime)
          if (durationseconds > playingtimeseconds){
              passed = durationseconds - (durationseconds - playingtimeseconds);
              passed = Math.floor(((passed / durationseconds) * 100) * 4); // set to * x for each 100px
          } else {
              passed = 0;
          }  
          $("#plan-" + currentPlanId).find(".playprogress").css("min-width", "0px", 'important');
          $("#plan-" + currentPlanId).find(".playprogress").css("height", "15px", 'important');
          $("#plan-" + currentPlanId).find(".playprogress").css("border-radius", "0px", 'important');
          $("#plan-" + currentPlanId).find(".playprogress").css("max-width", passed + "px", 'important');
          $("#plan-" + currentPlanId).find(".playprogress").css("width", passed + "px");
        }
    }
  ); }; }, 1000);
});

BR,

Erwin
Reply
Hi Erwin,

it works. Thank you very much!

BR,

Marc
Reply
Hi ,
Which is the code in order to execute clear Queue on sonos ?
Reply
Hi,

You can't call clear the queue separate, the command is internal available when switching between lists, but there is no way to trigger it from the API at this moment.

If you really need it, you could use this as script command to upnpcmd instead: 

Code:
function upnpavcmd(host, port, cmd, param)
   local client, soap, reqs, service, res, err
   
   require('socket')
   client = socket.tcp()
   client:settimeout(3)
   
   -- try connecting to upnp endpoint
   res, err = client:connect(host, port)
   if not res then
   return nil, err
   end
   
   -- guess service name based on command
 if cmd =='SetGroupVolume' or cmd == 'SetGroupMute' or cmd == 'SnapshotGroupVolume' then
   service = 'GroupRenderingControl'
 elseif cmd == 'SetVolume' or cmd == 'GetVolume' or cmd == 'SetMute' or cmd == 'GetMute' then
   service = 'RenderingControl'
   else
   service = 'AVTransport'
   end
 
   -- soap envelope
   soap = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' ..
   '<s:Body>' ..
   '<u:' .. cmd .. ' xmlns:u="urn:schemas-upnp-org:service:' .. service .. ':1">' ..
   '<InstanceID>0</InstanceID>' ..
   (param or '') ..
   '</u:' .. cmd .. '>' ..
   '</s:Body>' ..
   '</s:Envelope>'
   
   -- http request
   reqs = 'POST /MediaRenderer/' .. service .. '/Control HTTP/1.1\r\n' ..
   'CONNECTION: close\r\n' ..
   'HOST: ' .. host .. ':' .. port .. '\r\n' ..
   'CONTENT-LENGTH: ' .. soap:len() .. '\r\n' ..
   'CONTENT-TYPE: text/xml; charset="utf-8"\r\n' ..
   'SOAPACTION: "urn:schemas-upnp-org:service:' .. service .. ':1#' .. cmd .. '"\r\n' ..
   '\r\n' .. soap
   
   -- send http request
   res, err = client:send(reqs)
   if not res then
   return nil, err
   end
   
   -- get reply and close connection
   res, err = client:receive('*a')
   client:close()
   
   return res, err
end

Code:
upnpavcmd('192.168.0.24', 1400, 'RemoveAllTracksFromQueue')

BR,

Erwin
Reply
(25.10.2017, 13:28)Erwin van der Zwart Wrote: Γεια σας,

Δεν μπορείτε να καλέσετε σαφή την ουρά ξεχωριστά, η εντολή είναι εσωτερική διαθέσιμη κατά την εναλλαγή μεταξύ των λιστών, αλλά δεν υπάρχει τρόπος να ενεργοποιηθεί από το API αυτή τη στιγμή.

Εάν το χρειάζεστε πραγματικά, θα μπορούσατε να το χρησιμοποιήσετε ως εντολή σεναρίου για upnpcmd αντί:  BR, Erwin

Code:
function upnpavcmd(host, port, cmd, param)
   local client, soap, reqs, service, res, err
   
   require('socket')
   client = socket.tcp()
   client:settimeout(3)
   
   -- try connecting to upnp endpoint
   res, err = client:connect(host, port)
   if not res then
   return nil, err
   end
   
   -- guess service name based on command
 if cmd =='SetGroupVolume' or cmd == 'SetGroupMute' or cmd == 'SnapshotGroupVolume' then
   service = 'GroupRenderingControl'
 elseif cmd == 'SetVolume' or cmd == 'GetVolume' or cmd == 'SetMute' or cmd == 'GetMute' then
   service = 'RenderingControl'
   else
   service = 'AVTransport'
   end
 
   -- soap envelope
   soap = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' ..
   '<s:Body>' ..
   '<u:' .. cmd .. ' xmlns:u="urn:schemas-upnp-org:service:' .. service .. ':1">' ..
   '<InstanceID>0</InstanceID>' ..
   (param or '') ..
   '</u:' .. cmd .. '>' ..
   '</s:Body>' ..
   '</s:Envelope>'
   
   -- http request
   reqs = 'POST /MediaRenderer/' .. service .. '/Control HTTP/1.1\r\n' ..
   'CONNECTION: close\r\n' ..
   'HOST: ' .. host .. ':' .. port .. '\r\n' ..
   'CONTENT-LENGTH: ' .. soap:len() .. '\r\n' ..
   'CONTENT-TYPE: text/xml; charset="utf-8"\r\n' ..
   'SOAPACTION: "urn:schemas-upnp-org:service:' .. service .. ':1#' .. cmd .. '"\r\n' ..
   '\r\n' .. soap
   
   -- send http request
   res, err = client:send(reqs)
   if not res then
   return nil, err
   end
   
   -- get reply and close connection
   res, err = client:receive('*a')
   client:close()
   
   return res, err
end

Code:
upnpavcmd('192.168.0.24', 1400, 'RemoveAllTracksFromQueue')

thx Erwin 
i'll try it

Hi again Erwin ,
thx for help!!!... It works !!!!
Reply
Gentelmens,

Can you summarize all information about Sonos, step by step, how to control it thru LM ?
At moment I see long discussion with many various samples.
Reply
Hi,
We want it to play all the playlists and it executes only the first one ...
How can we fix that so it can play all of our playlists?
Reply
Hi,

You probably are requesting the wrong playlist as they are not numbered 1,2,3 etcetera but there can be gaps when you delete or add playlists.

To see your playlist numbers you can get them in a browser like this:
Code:
http://192.168.0.10/apps/data/sonos/sonos.lp?action=getplaylists&ip=192.168.0.50
The reply will look like this:
Code:
[{"name":"Adele","id":"19"},{"name":"Pink","id":"34"},{"name":"Top 100","id":"18"},{"name":"Top 1000","id":"30"}]
Then to load the list 'Top 100' you need to request it like this:
Code:
http://192.168.0.10/apps/data/sonos/sonos.lp?action=loadplaylist&ip=192.168.0.50&listnumber=18&autoplay=true
BR,

Erwin
Reply
Photo 
Erwin hello, how do I correctly remove the erroneous icons of crosses on the players sonos? Screenshot I attach to the message.

Attached Files Image(s)
   
Reply


Forum Jump: