Linn Forums

Full Version: Sending SOAP requests to Ds using AppleScript
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

I'm trying to communicate with a Sneaky Ds using AppleScript (on Mac OS X), which supports making SOAP rpc calls. My problem is that as soon as I am sending parameters _to_ the Ds (IN paramaters) I get a very unhelpful "UPnPError" and I can't figure out where I am going wrong.

Here's what I do:

1. Start Script Editor, enter this script (replace the IP with whatever IP your Ds device has, I gleaned my from the Linn Config app) making sure this amounts to 3 lines:

tell application "http://192.168.0.40:55178/Ds/Media/control"
return call soap {method name:"PlaylistSequence", method namespace uri:"urn:linn-co-uk:service:Media:1", SOAPAction:"urn:linn-co-uk:service:Media:1#PlaylistSequence"}
end tell

2. Run the script and it will respond with the sequence number (in my case "10"). Great. So I can send actions to the Ds and it responds, but in this case there were no IN parameters.

3. Enter this next script, making sure you swap the IP and sequence number (the "10" after aSeqSmile from step 2:

tell application "http://192.168.0.40:55178/Ds/Media/control"
return call soap {method name:"PlaylistTrackCount", method namespace uri:"urn:linn-co-uk:service:Media:1", parameters:{aSeq:"10"}, SOAPAction:"urn:linn-co-uk:service:Media:1#PlaylistTrackCount"}
end tell

4. Running this script results in "control got an error: UPnPError".


I was thinking the problem might be that the "method namespace" is wrong. I looked through the docs for the Media service on Linn's site and I also checked the service XML (which I got from the Ds itself) but the namespace is not mentioned anywhere. From what I can understand, the UPnP specs (which are just not very easy to read) says that the namespace should be the urn for the service, which is what I entered above.

Has anybody got any other idea what the problem may be? I doubt it has anything to do with AppleScript -- all it does is to http POST a SOAP request to the IP specified.

Thanks,
Björn

Bjorn Wrote:
tell application "http://192.168.0.40:55178/Ds/Media/control"
return call soap {method name:"PlaylistTrackCount", method namespace uri:"urn:linn-co-uk:service:Media:1", parameters:{aSeq:"10"}, SOAPAction:"urn:linn-co-uk:service:Media:1#PlaylistTrackCount"}
end tell


Just a thought - the aSeq parameter is a ui4 (integer) so should it maybe be unquoted in your script ?

Hi Bjorn:

Here's a sample request for the Media service's PlaylistSequence:

Quote:
POST /Ds/Media/control HTTP/1.1
HOST: 172.20.4.30:55178
SOAPACTION: "urn:linn-co-uk:service:Media:2#PlaylistSequence"
CONTENT-TYPE: text/xml ; charset="utf-8"
Content-Length: 277

<?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:PlaylistSequence xmlns:u="urn:linn-co-uk:service:Media:2" />
</s:Body>
</s:Envelope>


And here's the response:

Quote:
HTTP/1.1 200 OK
Ext:
Content-Type: text/xml; charset="utf-8"
Server: RTEMS/4.7.99, UPnP/1.0, Linn UPnP Stack/2.0
Content-Length: 307

<?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:PlaylistSequenceResponse xmlns:u="urn:linn-co-uk:service:Media:2"><aSeq>51</aSeq></u:PlaylistSequenceResponse></s:Body></s:Envelope>


For the PlaylistTrackCount request, here's some more reference text:

Quote:
POST /Ds/Media/control HTTP/1.1
HOST: 172.20.4.30:55178
SOAPACTION: "urn:linn-co-uk:service:Media:2#PlaylistTrackCount"
CONTENT-TYPE: text/xml ; charset="utf-8"
Content-Length: 334

<?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:PlaylistTrackCount xmlns:u="urn:linn-co-uk:service:Media:2">
<aSeq>51</aSeq>
</u:PlaylistTrackCount>
</s:Body>
</s:Envelope>


And the response:

Quote:
HTTP/1.1 200 OK
Ext:
Content-Type: text/xml; charset="utf-8"
Server: RTEMS/4.7.99, UPnP/1.0, Linn UPnP Stack/2.0
Content-Length: 325

<?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:PlaylistTrackCountResponse xmlns:u="urn:linn-co-uk:service:Media:2"><aTrackCount>11</aTrackCount></u:PlaylistTrackCountResponse></s:Body></s:Envelope>


Clearly the ip address needs to be changed to reflect your local network.

There's a great tool called Intel Upnp Device Spy which allows you to generate these and more. You can get it here:

http://www.intel.com/cd/ids/developer/as...m#anchor_2

It's written in .NET and so it's probably possible to get it running on Mac. But you may be better running it virtualised.

Hope this helps...

Thanks for both replies.

Changing the "aSeq" to an integer instead of string unfortunately did not help so I started tcpdump to compare the HTTP requests with keithr's sample request. The relevant part of the communication for the "PlaylistTrackCount" action was the following:

Quote:
POST /Ds/Media/control HTTP/1.1
User-Agent: Mac OS X; WebServicesCore.framework (1.0.0)
Host: 192.168.0.40
Content-Type: text/xml
Soapaction: "urn:linn-co-uk:service:Media:1#PlaylistTrackCount"
Content-Length: 597
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<mTonguelaylistTrackCount xmlns:m="urn:linn-co-uk:service:Media:1">
<aseq xsi:type="xsd:int">10</aseq>
</mTonguelaylistTrackCount>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

HTTP/1.1 500 Internal Server Error
Ext:
Content-Type: text/xml; charset="utf-8"
Server: RTEM

UPnP/1.0, Linn UPnP Stack/2.0

<?xml version="1.0"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body><s:Fault>
<faultcode>s:Client</faultcode><faultstring>UPnPError</faultstring>
<detail><UPnPError xmlns="urn:schemas-upnp-org:control-1-0">
<errorCode>501</errorCode>
<errorDescription>Invalid XML</errorDescription>
</UPnPError></detail></s:Fault>
</s:Body></s:Envelope>


Apparently the XML generated by the AppleScript "call soap" call differs from the XML keithr posted and I guess this is what is going wrong (also, that is what the error message seems to imply).

Does UPnP use some kind of "special" SOAP syntax or is the AppleScript generating syntax for some different version of SOAP? I know next to nothing about SOAP, so maybe somebody could clue me in on why the XML generated by AppleScript doesn't match the XML keithr posted.

Thanks,
Björn

Bjorn Wrote:
<aseq xsi:type="xsd:int">10</aseq>


aSeq has become aseq somewhere along the line. Pretty sure that args are case sensitive, hence this would be giving you an issue. The actual XML itself looks OK as XML.

rockfather Wrote:
aSeq has become aseq somewhere along the line. Pretty sure that args are case sensitive, hence this would be giving you an issue.


You are absolutely right. It seems the Script Editor makes all parameters lowercase behind the scenes.

To confirm that it actually works when the parameter is capitalized properly I created a raw Apple Event and sent it with AESend() (using Objective-C instead of Script Editor) -- this way I could ensure the paramter name was "aSeq" instead of "aseq".

If anybody is interested in the details I can post some sample code. It is messy, but at least it provides a simple way of sending SOAP actions to the Ds and get replies synchronously on Mac OS X (without the use of any extra libraries).

Björn

Hey Bjorn,

You seem to imply it's a problem with the Script Editor rather than the AppleScript 'call soap' function.

If so, could this AppleScript problem be solved using a more plain editor? Or are the Script Editor and AppleScript largely inseparable?

Graham
Hi Graham,

grahamd Wrote:
You seem to imply it's a problem with the Script Editor rather than the AppleScript 'call soap' function.

If so, could this AppleScript problem be solved using a more plain editor? Or are the Script Editor and AppleScript largely inseparable?


I'm not sure myself, but upon reading the AppleScript language documentation it would seem that this is a problem with AppleScript itself since "Identifiers" are case-insensitive. From the "AppleScript Language Guide":

Quote:
Identifiers are not case sensitive. For example, the identifiers myvariable and MyVariable are equivalent.

AppleScript remembers and enforces the first capitalization it comes across for an identifier. So if it first encounters an identifier as myAccount, it will later, during compilation, change versions such as MyAccount and myaccount to myAccount.


This would seem to imply that if you consistently wrote "aSeq" it would use the proper capitalization, but I've been trying a couple of different ways of running scripts now (Script Editor, osascript) and it always seems to turn "aSeq" into "aseq". Maybe somebody with more AppleScript experience than me can figure this one out. For now, I don't mind terribly since I can make AppleScript calls programmatically and it all works fine -- I just thought it'd be nice to do prototyping with the Script Editor first.

Björn

i want to bring up this thread again.
@bjorn: have you managed to get applescript to send the commands?
i want to read the playlist from the DS, then delete it and resend a "shuffled" version of it back to my DS. this way i could create a shuffle mode, which i really like on my ipod.

markus
Hi Markus,

What OS - I can give you some Python (v2.5) which can read a DSs playlist - or some JavaScript which runs under FireFox to do the same.

Regards,

Rik
Pages: 1 2
Reference URL's