I’ve been playing with my WeMo Link device again. A couple of weekends ago I made a mistake, I used the Belkin WeMo Android app to turn a light on (rather than ask Alexa to turn it on via Node-RED). While doing this the app suggested I update the firmware on the Link device. I decided to let it do the update, this led to whole host of issues with the device not wanting to connect to the WiFi.
In the end I had to reset the device, and re-pair the bulbs. The re-pairing worked, but the Osram bulbs didn’t show up in the WeMo android app any more. It turns out the app no longer show bulbs which haven’t been “WeMo Certified”. They still show up when you query the API directly and I can control them via my Node-RED nodes but I couldn’t add the bulbs to groups. The WeMo Link supports the ZigBee Light Link protocol just like Osram Lightify, Philips Hue and the Innr lights so there is no reason why all of these things shouldn’t be able to play nicely with each other.
This sent me back to reverse engineering the SOAP API to interact with the WeMo Link.
I’ve had a pretty good go at working out the protocol already, resulting in the wemo-control.js script and the Node-RED WeMo nodes, but this is just basic discovery and control not really “admin” tasks. I decided to break this work out into it’s own script.
There are 2 main tasks that this script will have to do, add new bulbs and create groups.
This was actually pretty easy, the API end points were pretty obvious in the list.
- OpenNetwork – allows bulbs to join the mesh
- GetEndDevices – when used with the UNPAIRED_LIST filter it shows just the new bulbs.
- IdentifyDevice – makes a bulb flash so you can work out which bulb is which if you discover new bulbs
- AddDevice – adds a new bulb to the mesh
- CloseNetwork – stops bulbs joining the mesh
None of these calls take any complex arguments and all are available either via discovery responses or other simple calls. If you chain them together in the order above you end up with your new bulbs available (at least to my scripts even if not in the WeMo app).
This one was a little harder, while the API list a CreateGroup endpoint, it says that it takes as a single argument if type ReqCreateGroup which is listed to be a string. Now from experience I can guess that this string is actually a URL encoded XML fragment. There are no hints as to what this XML fragment might look like. This led to a slight diversion down a rabbit hole to set up a raspberry pi as a WiFi AccessPoint bridged on to my local network so I could run tcpdump to make sure I captured all sides of the conversation between my tablet and the WeMo Link. A little bit of formatting and collating in Wireshark and we hit pay dirt:
<?xml version="1.0" encoding="UTF-8"?> <CreateGroup> <GroupID>1489757700</GroupID> <GroupName>Lighting Group</GroupName> <DeviceIDList>94103EA2B278030F,94103EA2B27803ED</DeviceIDList> <GroupCapabilityIDs>10008,10006,30008,30009,3000A</GroupCapabilityIDs> <GroupCapabilityValues>255:0,0,,,</GroupCapabilityValues> </CreateGroup>
The full capture can be found here.
It all looks pretty self explanatory,
- A unique id for the group (looks like it’s epoch time in seconds)
- Name of the group (probably should be XML escaped, but we’ll keep them simple)
- The list of device IDs to include in the group
- The subset of capabilities that all the devices in the group support
- Some starting values for those capabilities
Now I had the format of the messages I need to send it’s time to actually write some code. The first pass is up here, it’s a little rough and ready but I’ll try and clean it up a bit later and add a command to rename devices, but it’s Friday afternoon and I’m typing this up in a bar…
To add a bulb you would follow this flow of commands:
node bridge.js open ... node bridge.js unpaired ... <?xml version="1.0" encoding="utf-8"?><DeviceLists><DeviceList><DeviceListType>Unpaired</DeviceListType><DeviceInfos><DeviceInfo><DeviceIndex>5</DeviceIndex><DeviceID>00158D0001696252</DeviceID><FriendlyName>OnOff Light</FriendlyName><IconVersion>1</IconVersion><FirmwareVersion>01</FirmwareVersion><CapabilityIDs>10006,10008,30008,30009,3000A</CapabilityIDs><CurrentState>,,,,</CurrentState><Manufacturer>innr</Manufacturer><ModelCode>BY 165</ModelCode><productName>lighting</productName><WeMoCertified>NO</WeMoCertified></DeviceInfo></DeviceInfos></DeviceList></DeviceLists> node bridge.js indentify <device id> ... node bridge.js add <device id> ... node bridge.js close ...
To create a new group:
node bridge.js createGroup "Group Name" "00158D0001696252,00158D0001696253" "10006,10008,30008,30009,3000A", "0,255:0,,,"