Recently, Belkin released the Wemo Switch, a device that essentially allows you to control an electrical outlet via WiFi. Just one problem–it only works with iOS devices. (Belkin announced an Android app at CES, to enter beta on the Galaxy S3 later this month.)
I, being far too impatient to wait for said beta, and curious as to if it could be used without it, I bought one anyway. This is my story.
Before I get any further, I’d like to give a big shoutout to Issac Kelly, who did a good portion of the heavy lifting, and without whom I would probably not be writing this. Thanks!
So, I got home, unboxed the device, and plugged my lamp in it. The LED blinked orange and blue, letting me know it was awaiting setup. Pushing the power button on the device itself switched the lamp on and off, with the satisfying click of a relay. Clearly my ability to put the right peg in the right hole in kindergarten has yet to escape me.
Normal WeMo setup involves connecting your mobile device to the WeMo’s internal IP (SSID WeMo) and launching the app on your phone. From there, the app shows a list of what APs the WeMo can see, you pick one, type the password, and voila, you’re connected. I soon realized this would not be quite so easy.
Problem 1: Windows and Python
I grabbed miranda.py and miranda.py from Issac’s github. Ran miranda.py, and… failed.
Unmet dependency: No module named IN
Well, damn. What’s IN? To Google we go! Turns out, you don’t need it on Windows. Deleted its import, try again.
Unmet dependency: No module named readline
You’re really not going to make this easy, are you? Luckily, as it turns out, there’s a really easy to set up readline package for Python on Windows called pyreadline. At this point, however, I just decided to switch over to my Ubuntu partition for a while. (This proved to be necessary anyway a little later on.)
Problem 2: WeMo and SSDP
So I got Python working (on Linux, anyway), and quickly hit a new roadblock. Opening miranda and entering the command msearch (the command used to automatically search for UPnP devices) found nothing. I’m hypothesizing (but have no real way to prove this) that because the setup process is exactly the same for every WeMo switch (every device has the same IP address, 10.22.22.1, during setup) that the app need not “discover” anything. Clearly I was going to have to find a workaround.
What about pcap mode, in which it listens for UPnP packets and detects hosts that way? Can’t hurt, right? Well, it seemed to find itself. So I saved the host it found to a new file, which I could, hopefully, modify to point to the WeMo. Turns out, I could! (Props to the miranda crew for making it human-readable). So I made a few changes:
(dp0 I0 (dp1 S'xmlFile' p2 S'http://10.22.22.1:49153/setup.xml' p3 sS'name' p4 S'10.22.22.1:49153' p5 sS'proto' p6 S'http://' p7 sS'deviceList' p8 (dp9 sS'serverType' p10 NsS'upnpServer' p11 S'Linux/2.6.21, UPnP/1.0, Portable SDK for UPnP devices/1.6.6' p12 sS'dataComplete' p13 I00 ss.
Then reran miranda and loaded the newly updated file. But when it came time to enumerate the commands the WeMo offered, it failed. It seemed it was not listening on port 49153 as was found by Issac. So I ran nmap and it’s got 49152 open. Maybe that’s it. Change lines 6 and 10 to 49152, reload, and, we have connection! Just a quick test:
upnp> host send 0 controllee basicevent SetBinaryState
Argument Name: BinaryState
Data Type: Boolean
Allowed Values: 
Set BinaryState value to: 0
And hooray, I’m in the dark! My computer is talking to the WeMo. But could I get it to connect to my WAP?
Problem 3: WiFi Setup
The WeMo advertises a service called WiFiSetup. Probably a good place to start. First I made sure it could even see the WAP:
upnp> host send 0 controllee WiFiSetup GetApList
ApList : Page:1/1/2$
Well, that’s a good sign at least. However, when I tried to send the ConnectHomeNetwork command, miranda crashed. Time to send SOAP requests at the device manually.
Checking http://10.22.22.2:49152/setupservice.xml, I found that the ConnectHomeNetwork command takes five arguments: ssid, auth, password, encrypt, and channel, all of which but the password are supplied by GetApList. So crafting a SOAP request shouldn’t be hard:
<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:ConnectHomeNetwork xmlns:u="urn:Belkin:service:WiFiSetup:1"> <auth>WPA1PSKWPA2PSK</auth> <channel>2</channel> <encrypt>TKIP</encrypt> <password>--redacted--</password> <ssid>Cisco30848G</ssid> </u:ConnectHomeNetwork> </s:Body> </s:Envelope>
And just shoot it over with curl, right? Easy. Got a message saying it was connecting and everything. But the light’s still blinking blue and orange. Maybe check the router UI?
Pulling up my router’s webpage revealed that it was trying to connect… unsuccessfully. I tried both WPA1 and WPA2 individually as well; neither worked. I didn’t want to disable encryption on the router altogether, so instead, I made a virtual AP in DD-WRT called WeMo to which only my WeMo’s MAC can connect. (Not the best security, I know. I hope to move it to its own VLAN and prevent Internet traffic from routing to it soon, and moving it to the encrypted side as soon as the official method is out.)
So I sent a new SOAP request over:
<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:ConnectHomeNetwork xmlns:u="urn:Belkin:service:WiFiSetup:1"> <auth>OPEN</auth> <channel>2</channel> <encrypt>NONE</encrypt> <password></password> <ssid>WeMo</ssid> </u:ConnectHomeNetwork> </s:Body> </s:Envelope>
And it says it’s connecting. But same blue/orange light. Hmm. Maybe it has something to do with this CloseSetup command?
<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:CloseSetup xmlns:u="urn:Belkin:service:WiFiSetup:1"> </u:CloseSetup> </s:Body> </s:Envelope>
Success! The light has stopped blinking! (And my laptop dropped from the WeMo’s internal AP, which has since disappeared.) Reconnecting to my home AP and telling miranda to send on port 49153 and shooting the WeMo some SetBinaryState 0 and SetBinaryState 1 commands successfully flashed the room lights.
Problem 4: WeMo and SSDP, Part Two
So it’s connected to my WAP–maybe now it’ll respond to discovery requests. Sadly, this does not seem to be the case. I’m wondering if my router may be interfering with UPnP in some way. No worries, I can hardcode it. I’ve set my router up to always assign it the same IP address, so telling my scripts to talk to 10.0.0.103 won’t be too hard. (Plus, I’ll avoid waiting for it to discover the device every single time I run a script.)
Problem 5: User Experience
Sadly, I don’t get quite as rich an experience as iOS users; I can’t yet control from my mobile (though it would be trivial to write a small web app where you push a button and it toggles the status of the switch). I did, however, using Issac’s wemo.py write three little Python scripts that will switch the device on, off, or toggle the state of the switch, all of which are pretty similar:
# lampOff.py from wemo import off off() # lampOn.py from wemo import on on() # lampToggle.py from wemo import on, off, get if get(): off() else: on()
After hardcoding the IP into wemo.py, running each of the three scripts gave the expected result. Finally, success was truly mine. I made a taskbar shortcut to flip the lights on and off from my computer, and added a Windows Scheduled Task to turn them on at 6:45 AM on every weekday, in conjunction with my alarm clock.
So, it’s possible to use a WeMo without an iPhone. It took me many hours of trial and error to get it right, but I finally got it. And, now that I’ve done it once, in the future it shouldn’t take me any more than about 10 minutes to get working again. Hopefully this provides you with the tools to do the same. Thanks again to Issac Kelly, without whose work I would not be writing this, and in fact would probably have taken the damn thing back to the store by now.
Update (2/16/13 12:56 AM CST): I’ve received word that Belkin have just released their beta Android app for the Galaxy S3 (which may also work on other ICS devices). So if you’ve got one of those, there’s that.