Skip to content

andmeek/wemo

This branch is 8 commits ahead of mnoble/wemo:master.

Folders and files

NameName
Last commit message
Last commit date
Jan 23, 2017
Apr 20, 2019
Jan 23, 2017
Mar 2, 2019
Mar 2, 2019
Jan 23, 2017
Apr 20, 2019
Aug 3, 2013
Mar 2, 2019

Repository files navigation

WeMo Control Center

Simple dashboard of networked WeMo Switches.

Install

$ git clone https://github.com/mnoble/wemo.git
$ cd wemo
bin/setup

CLI Usage

$ thor list           # list commands
$ thor list_devices   # list devices and their state
$ thor turn_on        # turn on all devices
$ thor turn_off       # turn off all devices

The API

The main thing you'll work with is a Wemo::Switch object. A Switch represents a physical WeMo switch on your network. They're identified by the IP address and port the switch lives at.

switch = Wemo::Switch.new("10.0.0.11:49153")

switch.on?  # => true
switch.off? # => false

switch.on!
switch.off!

The Radar

If you don't know the specific location of WeMos on your network, you can discover them using Wemo::Radar. A Radar is initialized with the device type you want to find.

radar = Wemo::Radar.new("urn:Belkin:device:controllee:1")
radar.scan # => [#<Wemo::Switch:0x007f8>, #<Wemo::Switch:0x007f9>]

Services

WeMo Switches have a series of Services they offer. These are SOAP endpoints used to retrieve or manipulate data about the Switch.

We only care about one service, for now, BasicEvent service. This is the one used to turn the switch on and off.

Creating a service, in terms of the code, means subclassing Wemo::Services::Service and implementing two methods, service_id and control_uri.

class BasicEvent < Wemo::Services::Service
  def service_id
    "urn:Belkin:service:basicevent:1"
  end

  def control_uri
    "/upnp/control/basicevent1"
  end
end

Actions

Each Service implements many actions. The BasicEvent service mentioned above has two actions that we care about, GetBinaryState and SetBinaryState.

Adding new Actions to the library is similar to adding new Services. Subclass Wemo::Actions::Action and implement name and payload. Actions are instantiated with an options hash that payload can then use.

class GetBinaryState < Wemo::Actions::Action
  def name
    "GetBinaryState"
  end

  def payload
    <<-XML
<?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:GetBinaryState xmlns:u="urn:Belkin:service:basicevent:1"></u:GetBinaryState>
</s:Body>
</s:Envelope>
    XML
  end
end

Responses

The WeMo will send back an XML payload, Responses will need to parse out any data from that which is relevant.

Services will use the Wemo::Responses::Raw response by default. It just collects the response, parses the XML into a Hash and nothing more.

Building new responses is just a matter of implementing a class that takes a string in it's initializer.

class RawResponse
  def initialize(response)
    @data = Hash.from_xml(response)
  end
end

Discovering New Services/Actions

Services and Actions are specific to a type of device. You can explore them all by looking through the various XML documents exposed by devices. To get to these documents, comb through Wemo::Switch#attributes. Specifically, attributes["root"]["serviceList"]["service"] and the accompanying SCPDURL attributes. Yea... SOAP is awesome, isn't it?

wemo = Wemo::Switch.new("10.0.0.11:49153")
wemo.attributes
# => { ...Gigantic list of attributes and crap... }

About

WeMo Hacking

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Ruby 99.3%
  • Shell 0.7%