Saturday, January 26, 2013

SMART Airconditioner, Part II

I started trying to figure out my air conditioner, and have made some fairly good progress.

Unfortunately, though I've been able to do a simple proof of concept; it's ambiguous as to how I can really make use of the resulting code - the terms of service narrowly define only interfaces provided by Samsung can be used to access their services.

I'd wager that a restful service is "provided by Samsung" in all of the technical senses, but I don't really have the desire to explore the legal interpretations of that.


As a first step, you want to authenticate your restful client against the Samsung SSO interface.

I made use of Mechanize and providing my credentials to correctly generate an authorisation cookie for the samsung service; in an identical fashion to how chrome would do this step.

There are a few steps to this, and a lot of javascript going back and forth.

A post to to get the login form (with a ServiceID and ActionID); followed by submitting the actual login form.
There's yet more javascript that changes the form submit to location, so you end up manually pointing your requests at

A final form submit completes the sign in, and you have a cookie somewhere in there generated.
After that, a fairly overwhelming interface renders itself. A lot of javascript happens to dynamically load UI controls and so forth.

Rather than deal with this tag soup, I took my DUID (the mac address from before) and relied on the existing cookie to go forward.

Mechanize wasn't going to let me do much with POST and raw XML, and I tried a few different clients - I didn't find one I was happy with.

RestClient was close, but to be honest I would likely just use Net::HTTP directly in other situations.
After I had the authorisation, I sat in chrome and watched what was happening.
First, there's a call to understand your device's capabilities - selectDevice().

You tend to get a lot of data back, and it took me a while to figure out that this is probably just the same UPnP service description file I was looking for.

Interestingly, Samsung spell out all of the operations you can perform on the machine - it's certainly not a WSDL, but not too hard to see how they would create a number of dynamic UPnP control devices/services/UIs.

      <Power type="string">
      <OperationMode type="string">

Actually using the interface they provide, I saw requests to:

After a bit of probing, this looks very like the 'key value pair' style of controlling a UPnP device.
For example, to switch on your AC:

Cookie: (What you had before)
duid: (mac address)
<ControlCommand LastUpdateTime="1359114535"><Device><Status Power="On" /></Device></ControlCommand>

The response to this is an acknowledgement and a UUID, known as a CommandId.

The website them proceeds to spam the hell out of the services - 1-2 requests a second, polling - just to see if your command worked at all; and to update the device status.

GET checkControl
CommandId: UUIDFromBefore

<rsp stat="ok"><ControlResult DUID="...">Processing</ControlResult></rsp>

GET checkControl
CommandId: UUIDFromBefore

<rsp stat="ok"><ControlResult DUID="...">Success</ControlResult></rsp>

Given the previous work sniffing packets, I would think I've just sent basically the UPnP packets to the AC, and would be doing little to no transformation of them; beyond adding/removing from a queue.

At this point, I was ready to try controlling the AC with my restful code and start publishing it to github - unfortunately; I thought to read the ToS and found the narrowly worded agreement.

While I'd usually consider that hard to enforce, I don't really want to find out the ramifications of "unauthorised use of a computer" in Australian law - even if the end service is a Thing in My House that arguably doesn't need traffic going to Korea for it.

However, since I now have a pretty good idea of the other half of the conversation; I'm going to look closely at UPnP in the local environment again. If the services look similar, and it's just a matter of the same requests; but over UDP, I'm sorted!

No comments: