Discover, monitor and control Belkin WeMo devices on your local network
- LightSwitch
- Insight
- Switch
- Coffee Maker
- Humidifier
- More coming soon.
- Or feel free to add your favorite.
- Feel free to reach out if you need some help.
1. git clone https://github.com/NationalAssociationOfRealtors/ex_wemo.git
2. cd wemo
3. mix do deps.get, deps.compile
4. iex -S mix
5. WeMo.Client.start(host_ip \\ nil)
6. WeMo.register()
7. SSDP.Client.start()
WeMo.Client.start
registers the WeMo library with the SSDP.Registry
. You can pass WeMo.Client.start
your IP address, or it will attempt to ascertain it by iterating over your network interfaces and using the first non-local ipv4 address it finds. The IP is for setting the CALLBACK
url for the SOAP
actions. Calling WeMo.Client.start
allows you to wait for the network to be up, especially helpful when dealing with Nerves systems.
The WeMo library runs a small cowboy server on port 8083
by default, this is overridable via :ex_wemo, :http_port
, for receiving subscription events from the devices. You should see some success and error messages if you ran the interactive terminal session in the installation section.
Calling WeMo.register()
, registers your process with the WeMo.Registry
. All events and action results are published over this registry. You can handle events using handle_info({:device, device})
in the process that called WeMo.register()
. Where device is the device state shown below.
Once everything is configured we start the SSDP.Client
, again this allows us to wait until the network is up before looking for devices.
The events and action results are the same thing, just the most up-to-date state object from the device. They are both broadcast over the registry in the form {:device, device}
where the device is a State object for the given device type. Each device type Insight, LightSwitch, etc
writes it's unique state to the values
key.
%WeMo.Device.Insight.Values{
average_power: 0,
current_power: 0,
energy_today: 630892,
energy_total: 1128564767,
last_changed_at: 1507047806,
last_on_for: 3,
on_today: 231,
on_total: 1036198,
standby_limit: 0,
state: :off,
timespan: 70729
}
The full device state also includes the SSDP device state device
, subscription registration ids sids
, host_ip
and the pid
of the device process.
{:device,
%WeMo.Device.Insight.State{
device: %{
device: %{
device_type: 'urn:Belkin:device:insight:1',
friendly_name: 'Home Lab Insight',
icon_list: [%{depth: '100', height: '100', mime_type: 'jpg', url: 'icon.jpg', width: '100'}],
manufacturer: 'Belkin International Inc.',
manufacturer_url: 'http://www.belkin.com',
model_description: 'Belkin Insight 1.0', model_name: 'Insight',
model_number: '1.0', model_url: 'http://www.belkin.com/plugin/',
presentation_url: '/pluginpres.html', serial_number: nil,
service_list: [%{control_url: '/upnp/control/WiFiSetup1',
event_sub_url: '/upnp/event/WiFiSetup1', scpd_url: '/setupservice.xml',
service_id: 'urn:Belkin:serviceId:WiFiSetup1',
service_type: 'urn:Belkin:service:WiFiSetup:1'},
%{control_url: '/upnp/control/timesync1',
event_sub_url: '/upnp/event/timesync1',
scpd_url: '/timesyncservice.xml',
service_id: 'urn:Belkin:serviceId:timesync1',
service_type: 'urn:Belkin:service:timesync:1'},
%{control_url: '/upnp/control/basicevent1',
event_sub_url: '/upnp/event/basicevent1',
scpd_url: '/eventservice.xml',
service_id: 'urn:Belkin:serviceId:basicevent1',
service_type: 'urn:Belkin:service:basicevent:1'},
%{control_url: '/upnp/control/firmwareupdate1',
event_sub_url: '/upnp/event/firmwareupdate1',
scpd_url: '/firmwareupdate.xml',
service_id: 'urn:Belkin:serviceId:firmwareupdate1',
service_type: 'urn:Belkin:service:firmwareupdate:1'},
%{control_url: '/upnp/control/rules1',
event_sub_url: '/upnp/event/rules1', scpd_url: '/rulesservice.xml',
service_id: 'urn:Belkin:serviceId:rules1',
service_type: 'urn:Belkin:service:rules:1'},
%{control_url: '/upnp/control/metainfo1',
event_sub_url: '/upnp/event/metainfo1',
scpd_url: '/metainfoservice.xml',
service_id: 'urn:Belkin:serviceId:metainfo1',
service_type: 'urn:Belkin:service:metainfo:1'},
%{control_url: '/upnp/control/remoteaccess1',
event_sub_url: '/upnp/event/remoteaccess1',
scpd_url: '/remoteaccess.xml',
service_id: 'urn:Belkin:serviceId:remoteaccess1',
service_type: 'urn:Belkin:service:remoteaccess:1'},
%{control_url: '/upnp/control/deviceinfo1',
event_sub_url: '/upnp/event/deviceinfo1',
scpd_url: '/deviceinfoservice.xml',
service_id: 'urn:Belkin:serviceId:deviceinfo1',
service_type: 'urn:Belkin:service:deviceinfo:1'},
%{control_url: '/upnp/control/insight1',
event_sub_url: '/upnp/event/insight1', scpd_url: '/insightservice.xml',
service_id: 'urn:Belkin:serviceId:insight1',
service_type: 'urn:Belkin:service:insight:1'},
%{control_url: '/upnp/control/smartsetup1',
event_sub_url: '/upnp/event/smartsetup1', scpd_url: '/smartsetup.xml',
service_id: 'urn:Belkin:serviceId:smartsetup1',
service_type: 'urn:Belkin:service:smartsetup:1'},
%{control_url: '/upnp/control/manufacture1',
event_sub_url: '/upnp/event/manufacture1',
scpd_url: '/manufacture.xml',
service_id: 'urn:Belkin:serviceId:manufacture1',
service_type: 'urn:Belkin:service:manufacture:1'}
],
udn: 'uuid:Insight-1_0-221350K12000B5',
upc: nil
},
uri: %URI{
authority: "192.168.10.19:49153",
fragment: nil,
host: "192.168.10.19",
path: "/setup.xml",
port: 49153,
query: nil,
scheme: "http",
userinfo: nil
},
url: nil,
version: %{major: '1', minor: '0'}
},
host_ip: {192, 168, 10, 5},
pid: :"uuid:Insight-1_0-221350K12000B5",
sids: ["uuid:33db5c96-1dd2-11b2-a2a3-c9a4beb5df50",
"uuid:33dd9164-1dd2-11b2-a2a3-c9a4beb5df50",
"uuid:33e04242-1dd2-11b2-a2a3-c9a4beb5df50",
"uuid:33e1ef3e-1dd2-11b2-a2a3-c9a4beb5df50",
"uuid:347f752e-1dd2-11b2-a2a3-c9a4beb5df50",
"uuid:3481cbc6-1dd2-11b2-a2a3-c9a4beb5df50"
],
values: %WeMo.Device.Insight.Values{
average_power: 0,
current_power: 0,
energy_today: 630892,
energy_total: 1128564767,
last_changed_at: 1507047806,
last_on_for: 3,
on_today: 231,
on_total: 1036198,
standby_limit: 0,
state: :off,
timespan: 70729
}
}
}
Here is the simple test to check an actual WeMo Insight on your network.
defmodule WemoTest do
use ExUnit.Case
doctest WeMo
test "test actual Insight device on network" do
WeMo.Client.start()
WeMo.register()
SSDP.Client.start()
assert_receive {:device, %{device: %{device: %{device_type: 'urn:Belkin:device:insight:1'}}} = device}, 65_000
device.pid |> WeMo.Device.Insight.on()
assert_receive {:device, %{device: %{device: %{device_type: 'urn:Belkin:device:insight:1'}}, values: %{state: :on}} = device}, 10_000
:timer.sleep(800)
device.pid |> WeMo.Device.Insight.off()
assert_receive {:device, %{device: %{device: %{device_type: 'urn:Belkin:device:insight:1'}}, values: %{state: :off}} = device}, 10_000
end
end
If you have more than one Insight on your network, you may want to pattern match on {:device, %{device: %{device: %{udn: device_udn}}}}