I have a SONOS music system in my home office…I would like the SONOS music system to automatically start when I come home and automatically stop when I leave home.
I have looked at the AppleScript Dictionary only to discover that SONOS’ Desktop Controller – the OS X app used to control the SONOS music system – is not scriptable
I have thought about this somewhat and am hoping that I can code / program this functionality using the following two step process:
An AppleScript to trigger the start / stop of the SONOS music system; and
An Automator Workflow to actually start / stop the SONOS music system.
I have thought further about 1. above and have concluded that one way to trigger the start / stop Automator Workflows is to start / stop the Automator Workflow when my iPhone’s static IP address on my home network is / is not detected.
In terms of an AppleScript I have coding the following script which does successfully detect the presence / absence of my iPhone:
set EndofTime to false
repeat while not EndofTime
try
set IP_address to "aaa.bbb.ccc.ddd" - iPhone static IP address
set ping to do shell script ("ping -c 2 " & IP_address & "| head -2 | tail -1 |cut -d = -f 4")
if ping contains "ms" then
set iPhoneDetected to "True"
display dialog ("iPhone Detected - " & ping) buttons {"OK"} default button 1 with title "iPhone Detection Test" giving up after 3
else if ping contains "timeout" then
set iPhoneDetected to "False"
display dialog "iPhone Not Detected " buttons {"OK"} default button 1 with title "iPhone Detection Test" giving up after 3
end if
end try
end repeat
While the above AppleScript needs further development [i.e. if iPhone detected then retest in 5 minute increments, etc.] I have run into a few problems for which I would appreciate some assistance. While the compiled script can be added to the user’s Login Item list [i.e. System Preferences / Users & Groups / Login Items] to automatically load when the user logs on:
How do I ensure that the perpetual running of the script does not become a memory hog [i.e. is there a way to stop the script and then restart the script, etc.]?
Is there code / a way to stop the script from running without Activity Monitor / force quit once the script is perpetually running.
While we are on the subject – is my proposed two step process workable?
@ Kel, appreciate the response though I now need to read up and learn about launch agents!
@ All - and unrelated – I am now concerned that my two step process is not workable for the same reason an AppleScript is not possible [i.e. SONOS Desktop Controller is not scriptable app] in that I do not see SONOS in the Automator’s library list…would appreciate commentary on this as well!
Basically, what you do is create your launch agent plist. You store it in your library launch agents. Then you load it and it starts firing. The good part about this is that it uses very little memory or cpu time. Great stuff.
I will try to get my AS’ to run perpetually once I know that I can actually control my SONOS Music System [i.e. no point in spending time on something that cannot be achieved]. With this in mind:
I went over to the SONOS Forum to see how others have controlled their SONOS Music Systems using AS only to find out no one has tried this [or, at least posted about i] since SONOS rewrote their OS X Desktop Controller.
One poster did post the following:
One way to pause / play the SONOS Music system is to use curl (which I believe is included in OS X). The codes are:
I then went over to another forum and found the following:
Sure, the command line utility curl is one way. Applescripts can use command line utilities with the “do shell script” command. So try this…
set theURL to "http://my.server.com?type=Show&name=Big+Bang+Theory"
do shell script "curl " & quoted form of theURL
so might be possible as AS does seem to recognize curl commands.
So armed with the above I tried the following AS:
set theURL to "--header 'SOAPACTION: "urn:schemas-upnp-org:service:AVTransport:1#Play"' --data '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><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>' [url=http://192.168.2.42:1400/MediaRenderer/AVTransport/Control]http://192.168.2.42:1400/MediaRenderer/AVTransport/Control"[/url]
do shell script "curl " & quoted form of theURL
which I could not even test because I got a compile error [i.e. Syntax Error, A identifier can’t go after this “”".] where the reference is to the "urn portion of the set command.
Would very much appreciate your help and assistance in solving this.
you have to escape each inner double quote with a backslash
set theURL to "--header 'SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"' --data '<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><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>' [url=http://192.168.2.42:1400/MediaRenderer/AVTransport/Control]http://192.168.2.42:1400/MediaRenderer/AVTransport/Control"[/url]
do shell script "curl " & quoted form of theURL
A script to determine whether I am / am not home based on whether my iPhone is present on my home LAN noting that obviously I need a better method of starting / topping this script:
set EndofTime to false
repeat while not EndofTime
try
set IP_address to "10.193.23.180"
set ping to do shell script ("ping -c 2 " & IP_address & "| head -2 | tail -1 |cut -d = -f 4")
if ping contains "ms" then
set iPhoneDetected to "True"
display dialog ("iPhone Detected - " & ping) buttons {"OK"} default button 1 with title "iPhone Detection Test"
else if ping contains "timeout" then
set iPhoneDetected to "False"
display dialog "iPhone Not Detected " buttons {"OK"} default button 1 with title "iPhone Detection Test"
end if
end try
end repeat
So what are the issues…I know that to make this work I need to i) comment out / remove the display dialog boxes as they are there for testing purposes and need not be there once the script is running ii) insert a call to the scripts “pause SONOS” and “play SONOS” within the “if blocks” depending on whether my iPhone is detected…what I don’t know and what I need help with is how to add code that controls the script so that can i) ensure the script does not take up too many resources as it will be running at all times ii) start / stop the script when necessary [i.e. I need a way to stop the script which does not currently exist] and iii) whatever else is needed when constantly running such a script.
Would greatly appreciate the boar’s assistance in making this work.
Appreciate the response and don’t doubt what you are saying BUT…
Could you be so kind to explain why you recommend against continuously sending ping commands; and
I took a fast read of python code and while I recognize that I don’t need to understand I would not even know where to begin vis-a-vis its setup as I don’t have an Indigo server, I don’t know python at all, etc.
I would be open to trying / using the Cocao equivalent but would need someone to walk me through the process step by step.
polling is always expensive because it consumes permanently system resources like CPU, network bandwidth and potentially also RAM.
The python and the Cocoa method uses a callback function to be notified about a change, the system resources costs are negligible.
Assuming the Cocao approach will be better / easier for me [remember, I have only been playing with AS for a month or so] what do you suggest is the best way for me to get the Coca call back function up and running noting I know nothing about Cocoa.
As much as I wanted to move this project / script forward I have hit a standstill in that:
I am going to heed StefanK’s suggestion warning about not perpetually ping my iPhone’s IP address for the reasons he notes in post #17 to this thread.
I was – because I am not familiar with the use of Cocoa’s NSNetServiceBrowser – going to use the method approach suggested by Adam Bell in post #9 of this thread but ran into problems in that I cannot pair my iPhone 5S to my mid-2012 MBA as I seem to be one of the many users who are having this pairing problem [so much for the Apple ecosystem “just works” which is why I moved from Windows to OS X].
I spent 3+ hours on the pie with Apple technical support and got nowhere…in fact, no one really wanted to help in that the MBA people passed me to the iOS people who on turned wanted to pass me back to the MBA people…this is extremely frustrating given this is a known issue between product both of which are made by the same company!
With 1. and 2. above I am stuck in that I i) either need someone to teach or walk me through NSNetServiceBrowser or ii) for Apple to fix this pairing problem.
sorry for having mentioned Cocoa.
With “playing with AS for a month” and “I know nothing about Cocoa” I guess it’s as difficult to implement as the python method
When using your polling method at least create a stay open application with an on idle handler and a return value of one or more seconds to reduce the overload