Notice: This forum has been recovered from an old backup, so some content, links, and dates may be outdated. The forum is currently read-only while we restore sign-in and registration functionality. Details

If you find this forum valuable and would like to help keep it online, donations to help cover hosting and domain costs are greatly appreciated, but never expected. You can support the forum through Buy Me a Coffee or Ko-fi. Thank you for helping preserve the EventGhost community.

SONOS Plugin

Questions and comments specific to a particular plugin should go here.
Post Reply
jompen152
Posts: 1
Joined: Wed Feb 13, 2013 3:16 pm

SONOS Plugin

Post by jompen152 »

New in this forum. Have someone createdt a sonos plugin to controll sonos with?
techoguy
Experienced User
Posts: 157
Joined: Mon Mar 18, 2013 1:32 am

Re: SONOS Plugin

Post by techoguy »

Hi,
I've been working on a SONOS plugin but i'm still in the phase of reverse engineering the SONOS control protocol. If there is a lot of interest for this, I'll try to push for something to be released sooner than later.
The Latest SONOS Plugin:
Latest version can be found here: http://eventghost.org/forum/viewtopic.p ... 05f#p30309

EventGhost Lets me automate my home the way I want it, I love using it!
Jostein
Experienced User
Posts: 108
Joined: Sun Feb 15, 2009 12:59 pm

Re: SONOS Plugin

Post by Jostein »

Hi.

This might be of help: https://github.com/rahims/SoCo
kalinkamaen
Experienced User
Posts: 138
Joined: Wed Dec 26, 2012 9:23 am

Re: SONOS Plugin

Post by kalinkamaen »

I would love to se this happend. How are you doing with this project?
Jostein
Experienced User
Posts: 108
Joined: Sun Feb 15, 2009 12:59 pm

Re: SONOS Plugin

Post by Jostein »

Hi.

Have found a way to controll the basic functions of sonos from Eventghost.

I wanted to create a plugin using the python class SoCo, but have not had time.

Have instead made a workaround using a command line tool called ZPCMD made by Osler se:
http://forums.sonos.com/showthread.php?t=12649&page=1

Here are the steps to get it working.

1. Run the file called "UniqueDeviceNames.vbs" (this will create a text file called UniqueDeviceNames.txt on C:\ including the id for your devices.)

2. Register the scripts ZonePlayerController.wsc and ZonePlayerFinder.wsc right click on it and press "register".

3. Right click on the example config file Sonos example.xml click "Edit". In notepad select "edit" on the top bar and then "replace".
In the "find what" box insert: RINCON_000E583EABEC01400
In the "replace with" box insert the uuid of the sonos box you want to controll. (se the text file C:\UniqueDeviceNames.txt)
press "replace all". Save and exit.

4. Open the example config file from EG and test if the commands works. If it works you can copy the sonos folder over to your config file.


If you get an ActiveX error you need to register the scripts using the included bat files. If you dont have the scripts in this folder: "C:\Program Files (x86)\EventGhost\plugins\Sonos\WSC\ZonePlayerController\ZonePlayerController.wsc" you need to edit it to the correct paths in the bat files.


This is not the best way to controll sonos but it is the way i do it. Will try to make a plugin later using the SoCo class as this would make for a cleaner install and also provide a 2 way controll with fedbacks and so on.
Attachments
Sonos.zip
(25.06 KiB) Downloaded 197 times
kalinkamaen
Experienced User
Posts: 138
Joined: Wed Dec 26, 2012 9:23 am

Re: SONOS Plugin

Post by kalinkamaen »

Jostein wrote:Hi.

Have found a way to controll the basic functions of sonos from Eventghost.

I wanted to create a plugin using the python class SoCo, but have not had time.

Have instead made a workaround using a command line tool called ZPCMD made by Osler se:
http://forums.sonos.com/showthread.php?t=12649&page=1

Here are the steps to get it working.

1. Run the file called "UniqueDeviceNames.vbs" (this will create a text file called UniqueDeviceNames.txt on C:\ including the id for your devices.)

2. Register the scripts ZonePlayerController.wsc and ZonePlayerFinder.wsc right click on it and press "register".

3. Right click on the example config file Sonos example.xml click "Edit". In notepad select "edit" on the top bar and then "replace".
In the "find what" box insert: RINCON_000E583EABEC01400
In the "replace with" box insert the uuid of the sonos box you want to controll. (se the text file C:\UniqueDeviceNames.txt)
press "replace all". Save and exit.

4. Open the example config file from EG and test if the commands works. If it works you can copy the sonos folder over to your config file.


If you get an ActiveX error you need to register the scripts using the included bat files. If you dont have the scripts in this folder: "C:\Program Files (x86)\EventGhost\plugins\Sonos\WSC\ZonePlayerController\ZonePlayerController.wsc" you need to edit it to the correct paths in the bat files.


This is not the best way to controll sonos but it is the way i do it. Will try to make a plugin later using the SoCo class as this would make for a cleaner install and also provide a 2 way controll with fedbacks and so on.



When i run "UniqueDeviceNames.vbs" i get a text file like this.
But i cant find the uniqeid in the file.


Option Explicit

Dim ZonePlayerFinder
Dim ZoneInfo
Dim ZoneCount
Dim fso
Dim File
Dim I

Set ZonePlayerFinder = CreateObject("ZonePlayer.Finder")

ZonePlayerFinder.FindZonePlayers
ZoneInfo = ZonePlayerFinder.GetZoneInfo
ZoneCount = ZonePlayerFinder.GetZoneCount

Set ZonePlayerFinder = Nothing

Set fso = CreateObject("Scripting.FileSystemObject")
Set File = fso.OpenTextFile("c:\UniqueDeviceNames.txt", 2, True)
For I = 0 To (ZoneCount - 1)
File.Write(ZoneInfo(I,0) & ": " & ZoneInfo(I,1) & vbCRLF)
Next
File.Close
Set File = Nothing
Set fso = Nothing
kalinkamaen
Experienced User
Posts: 138
Joined: Wed Dec 26, 2012 9:23 am

Re: SONOS Plugin

Post by kalinkamaen »

I managed to get further but now i have problem with eventghost.

Image

What have i done wrong here??
Jostein
Experienced User
Posts: 108
Joined: Sun Feb 15, 2009 12:59 pm

Re: SONOS Plugin

Post by Jostein »

Hi.

My text file looks like this:
sonos 2.jpg
Here you can see the name off the player and also the id. Mine is uuid:RINCON_000E583EABEC01400. Is this how your file looks?


Sorry for that you also need to change the directory of the commands to the ZPCMD.exe file.

You need to duble click on the commands and change the path to the file see screnshot
sonos.png
Would recomend editing the path from notepad using the same way as on the 3rd step just serching for "C:\\Program Files (x86)\\EventGhost\\plugins\\Sonos\\ZPCMD.exe" and replacing it with your path to the zpcmd.exe as this is mutch faster than changing every command by it self.


Hope you can get it working.
kalinkamaen
Experienced User
Posts: 138
Joined: Wed Dec 26, 2012 9:23 am

Re: SONOS Plugin

Post by kalinkamaen »

Hello thank you.

I managed to fix it.

But i have 2 play 3 units thats not working with the script.
All my 3 connects are working 100%.

Thanks for the help.
kalinkamaen
Experienced User
Posts: 138
Joined: Wed Dec 26, 2012 9:23 am

Re: SONOS Plugin

Post by kalinkamaen »

Seems like we have to wait on the soco based plugin. I have googled
up and down, but i cant find any info about controling play 3 on this setup.
I can see that another guy have the same problem with his playbar. I am not sure about the
Play 5 because i doent own one.

A sonos plugin is something i really would be happy to see for EG. I wish i had
the knowledge my self to do it. Since i am not, i am happy to give a donation
to help get this started. And hope people will follow me.

For you guys that wants sonos to mute every time your phone rings. You can install
macronos--> https://play.google.com/store/apps/deta ... onos&hl=no
With this app you also get a tasker plugin, so you can send info to tasker--> terremote --> eventghost on computer.
But i not sure if ican go the other way.

Best regards Morten
techoguy
Experienced User
Posts: 157
Joined: Mon Mar 18, 2013 1:32 am

Re: SONOS Plugin

Post by techoguy »

Jostein,
Does that plugin accurately control grouped zones?
I have not tried that specific tool. But I have tried many others and they never handle grouped zp accurately which then can cause confusion when a room stops playing but the rest of the group still is. While SONOS uses standard UPNP media rendering commands, grouping ZPs changes how the commands should be sent.

I currently can control basic functions of SONOS and have linked these to my insteon keypadlincs. For example, i press a button to start playing or double tap to pause it, have another button for next/previous, and 2 buttons for volume control (w/ double taps jumping to a preset volume). The next step is to sync the keypadlinc LED to the state of the ZP play state but that takes a lot more effort. The difference from most implementations is that these commands will still control grouped ZPs accurately.

Currently i do the above with some python scripts that have hard coded IP addresses (no plugin). But i've been working (on and off) on a full SONOS API executable that would take care of all the heavy lifting in managing the state/control of all the ZPs. Current state i'm at is, I can successfully search a network to find all ZPs and be notified of any new ZPs added or removed at a later time, record IPs, group topology, record names, receiving automatic updates when group topology changes. I know how all the other commands work and are sent, but just haven't had time to implement the code. Soon i'll be able to also have automatic updates for the meta data, play state, volume, and anything else needed. I'll also plan on having a command that will automatically group certain rooms like a preset party mode with certain rooms. Once I get this further along, hopefully i can try and make a plugin to work with this as well so all changes in your SONOS system can be seen as events in eventghost.

If there is any specific commands you would like to see, let me know and i can try to work it in.
The Latest SONOS Plugin:
Latest version can be found here: http://eventghost.org/forum/viewtopic.p ... 05f#p30309

EventGhost Lets me automate my home the way I want it, I love using it!
Jostein
Experienced User
Posts: 108
Joined: Sun Feb 15, 2009 12:59 pm

Re: SONOS Plugin

Post by Jostein »

Hi techoguy.

Sorry for the late response but subscribtion mail ended in spam folder.
I have not tried to use it to control groups as i only have one zone.
Have made it into a plugin which makes setup mutch faster.
Just copy the folder to plugins folder in EG. Start it and run the action Register WSC, and then run the UniqeDeviceNames which will output a file to C: with uuid`s.
Have attached the plugin if anybody wants to try it.
Sonos.zip
(34.17 KiB) Downloaded 202 times
It is still very basic but it does what i need it to do which is Play, Pause, Next and prev. If you want to control more than one zone you need to launch a 2nd instance of the plugin for every zone.

Would be interested in seeing your files, since i beleive your way of controlling sonos is the right way and also the path to go for more advanced control.

I have also wall switches (Smart HDL DLP) that i use for pause, play, and so on. But would like to have some switches for preset radio channels, do you have a script for starting a spesific radio channel?

Regards Jostein
kalinkamaen
Experienced User
Posts: 138
Joined: Wed Dec 26, 2012 9:23 am

Re: SONOS Plugin

Post by kalinkamaen »

Will there be an update that will work for Play 1,3,5 and the surroundbar?
techoguy
Experienced User
Posts: 157
Joined: Mon Mar 18, 2013 1:32 am

Re: SONOS Plugin

Post by techoguy »

Jostein wrote:Hi techoguy.
Would be interested in seeing your files, since i beleive your way of controlling sonos is the right way and also the path to go for more advanced control.
I have also wall switches (Smart HDL DLP) that i use for pause, play, and so on. But would like to have some switches for preset radio channels, do you have a script for starting a spesific radio channel?
Regards Jostein
Hi Jostein,
an example of sending PLAY to a ZP is below. The IP address is hard coded so the SONOS IP addresses should be static (static in the router DHCP table sense SONOS doesn't support static IP). The other rendering commands and volume commands are similar. A plugin for sending basic commands could be made (won't support instant updates from SONOS or automatically finding SONOS components without more work) but I don't have the time to implement that right now. Most of my free time is developing the full SONOS API instead.

As for starting specific radio stations, this can be done similar to the code below. The code would be unique to your SONOS system and the station you want to play (starting spotify and local file play lists are different and a little more complicated, but starting other stations is pretty simple). To get some of the unique variables to place in the code snippet, you would have to use something like Device Spy from http://software.intel.com/en-us/article ... chnologies then run a couple specific commands to any ZP and receive the variables. Then you can copy past them into the code. I haven't done that yet within EventGhost so I don't have a full code example. Maybe I can post a full example of what to do soon if you're still interested in implementing radio station presets this way.

And to the code...
This code should work for any ZP.
Current Example is sending "PLAY" to the proper coordinator for a specific ZP regardless if it's grouped or not.
Putting this in a python script action and updating the IP address to the ZP you want to control is all that should be changed.
What the code does:
1 - looks to see if the ZP is a slave in a group, if it's not, it's the coordinator
2 - If it's a slave, find the IP address of the Coordinator of the group
3 - Send the "PLAY" command to the Coordinator
This works for Play, puase, stop, next, prev, ect.

Code: Select all

from xml.dom.minidom import parse, parseString
import httplib

path = "/MediaRenderer/AVTransport/Control HTTP/1.1"
host = "192.168.0.107"
port = 1400
hostport = host + ":" + str(port)
xml = '''<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <u:GetMediaInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
         <InstanceID>0</InstanceID>
      </u:GetMediaInfo>
   </s:Body>
</s:Envelope>'''
conn = httplib.HTTPConnection(host,port)
conn.request("POST", path, body=xml, headers = {
    "Host": hostport,
    "SOAPACTION": '''"urn:schemas-upnp-org:service:AVTransport:1#GetMediaInfo"''',
    "Content-Type": "text/xml; charset=UTF-8",
    "Content-Length": len(xml)
})
print "finding coordinator of group.."
res = conn.getresponse()
print res.status, res.reason
xml = res.read()
dom = parseString(xml)
uri = dom.getElementsByTagName('CurrentURI')[0].childNodes[0].nodeValue
if uri.find("x-rincon:RINCON_") == 0:
    coordinator = uri.split(":")[1]
    print "current ZP is a slave, coordinator is ", coordinator
    path = "/ZoneGroupTopology/Control HTTP/1.1"
    xml = '''<?xml version="1.0" encoding="utf-8"?>
    <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
       <s:Body>
          <u:GetZoneGroupState xmlns:u="urn:schemas-upnp-org:service:ZoneGroupTopology:1" />
       </s:Body>
    </s:Envelope>'''
    conn = httplib.HTTPConnection(host,port)
    conn.request("POST", path, body=xml, headers = {
        "Host": hostport,
        "SOAPACTION": '''"urn:schemas-upnp-org:service:ZoneGroupTopology:1#GetZoneGroupState"''',
        "Content-Type": "text/xml; charset=UTF-8",
        "Content-Length": len(xml)
    })
    print "requsting group info..."
    res = conn.getresponse()
    print res.status, res.reason
    xml = res.read()
    index = xml.find('UUID="'+coordinator)
    host = xml[index+57:index+86].split(":")[1].replace("//","")
else:
    print "current zp is coordinator"

path = "/MediaRenderer/AVTransport/Control HTTP/1.1"
hostport = host + ":" + str(port)
xml = '''<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <u:Play xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
         <InstanceID>0</InstanceID>
         <Speed>1</Speed>
      </u:Play>
   </s:Body>
</s:Envelope>'''
conn = httplib.HTTPConnection(host,port)
conn.request("POST", path, body=xml, headers = {
    "Host": hostport,
    "SOAPACTION": '''"urn:schemas-upnp-org:service:AVTransport:1#Play"''',
    "Content-Type": "text/xml; charset=UTF-8",
    "Content-Length": len(xml)
})
print "sending PLAY to ", host
res = conn.getresponse()
print res.status, res.reason


For Volume, it's a little easier, the thing to NOTE here is that if you have a stereo pair (2 play1, play3, or soundbar with surrounds) then you need to make sure you're sending the volume commands to the ZP that is the coordinator/master of the pair (the other ZP have an "invisible" flag set, don't send volume commands to these, if you do the volume will only change the one speaker instead of both). The invisible speakers can be found using the device spy program as well.

This is an example of changing the volume relative to the current volume. The volume variable is the step size. Changing down is as simple as adding a "-".
There is a different command to use that can set the volume to a specific value as well.

Code: Select all

import httplib

path = "/MediaRenderer/RenderingControl/Control HTTP/1.1"
host = "192.168.0.107"
port = 1400
hostport = host + ":" + str(port)
volume = 5
xml = '''<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <u:SetRelativeVolume xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1">
         <InstanceID>0</InstanceID>
         <Channel>Master</Channel>
         <Adjustment>+''' + str(volume) +'''</Adjustment>
      </u:SetRelativeVolume>
   </s:Body>
</s:Envelope>'''
conn = httplib.HTTPConnection(host,port)
conn.request("POST", path, body=xml, headers = {
    "Host": hostport,
    "SOAPACTION": '''"urn:schemas-upnp-org:service:RenderingControl:1#SetRelativeVolume"''',
    "Content-Type": "text/xml; charset=UTF-8",
    "Content-Length": len(xml)
})
If there is enough interest, maybe I can put together a basic plugin for controlling at least the basics.
The Latest SONOS Plugin:
Latest version can be found here: http://eventghost.org/forum/viewtopic.p ... 05f#p30309

EventGhost Lets me automate my home the way I want it, I love using it!
Jostein
Experienced User
Posts: 108
Joined: Sun Feb 15, 2009 12:59 pm

Re: SONOS Plugin

Post by Jostein »

Hi techoguy.

Thanks the scripts works great.

Did you also have a script for listing up Sonos IP adresses?

Hope you dont mind but i put together a plugin with the basic commands using your scripts.
Sonos.zip
(5.03 KiB) Downloaded 206 times
kalinkamaen this should work with the Play units. Can you please check and report back?

To find the IP address open the Sonos App on windows press "help" and then "about my sonos system" Ip adresses should be listed there.

Regards Jostein
Post Reply