mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Added WeMo support
This commit is contained in:
parent
bb771d802d
commit
6063ffeb5b
25
README.md
25
README.md
@ -5,37 +5,37 @@ Home Assistant provides a platform for home automation. It does so by having mod
|
|||||||
|
|
||||||
It is currently able to do the following things:
|
It is currently able to do the following things:
|
||||||
* Track if devices are home by monitoring connected devices to a wireless router (currently supporting modern Netgear routers or routers running Tomato firmware)
|
* Track if devices are home by monitoring connected devices to a wireless router (currently supporting modern Netgear routers or routers running Tomato firmware)
|
||||||
* Track which lights are on
|
* Track and control lights
|
||||||
* Track what your Chromecasts are up to
|
* Track and control WeMo switches
|
||||||
|
* Track and control Chromecasts
|
||||||
* Turn on the lights when people get home when the sun is setting or has set
|
* Turn on the lights when people get home when the sun is setting or has set
|
||||||
* Slowly turn on the lights to compensate for light loss when the sun sets and people are home
|
* Slowly turn on the lights to compensate for light loss when the sun sets and people are home
|
||||||
* Turn off lights and connected devices when everybody leaves the house
|
* Turn off lights and connected devices when everybody leaves the house
|
||||||
* Start YouTube video’s on the Chromecast
|
|
||||||
* Quit current running application on a Chromecast
|
|
||||||
* Download files to the host machine
|
* Download files to the host machine
|
||||||
* Open a url in the default browser at the host machine
|
* Open a url in the default browser at the host machine
|
||||||
* Simulate key presses on the host for Play/Pause, Next track, Prev track, Volume up, Volume Down
|
* Simulate key presses on the host for Play/Pause, Next track, Prev track, Volume up, Volume Down
|
||||||
* Controllable via a REST API and web interface
|
* Controllable via a REST API and web interface
|
||||||
* Support for thin client Home Assistant instances that will forward all their commands to the main instance
|
* Support for remoting Home Assistant instances through a Python API
|
||||||
* Android Tasker project to control Home Assistant from your phone and report charging state. Combine it with AutoVoice to be able to tell your phones to turn the lights off!
|
* Android Tasker project to control Home Assistant from your phone and report charging state.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Current compatible devices:
|
Current compatible devices:
|
||||||
* Wireless router running [Tomato firmware](http://www.polarcloud.com/tomato)
|
* [WeMo switches](http://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/)
|
||||||
* Netgear wireless routers (tested with R6300)
|
|
||||||
* [Philips Hue](http://meethue.com)
|
* [Philips Hue](http://meethue.com)
|
||||||
* [Google Chromecast](http://www.google.com/intl/en/chrome/devices/chromecast)
|
* [Google Chromecast](http://www.google.com/intl/en/chrome/devices/chromecast)
|
||||||
|
* Wireless router running [Tomato firmware](http://www.polarcloud.com/tomato)
|
||||||
|
* Netgear wireless routers (tested with R6300)
|
||||||
|
|
||||||
The system is built modular so support for other wireless routers, other devices or actions can be implemented easily.
|
The system is built modular so support for other devices or actions can be implemented easily.
|
||||||
|
|
||||||
Installation instructions
|
Installation instructions
|
||||||
-------------------------
|
-------------------------
|
||||||
* Install python modules [PyEphem](http://rhodesmill.org/pyephem/), [Requests](http://python-requests.org) and [PHue](https://github.com/studioimaginaire/phue): `pip install pyephem requests phue`
|
* The core depends on [PyEphem](http://rhodesmill.org/pyephem/) and [Requests](http://python-requests.org). Depending on the components you would like to use you will need [PHue](https://github.com/studioimaginaire/phue) for Philips Hue support, [PyChromecast](https://github.com/balloob/pychromecast) for Chromecast support and [ouimeaux](https://github.com/iancmcc/ouimeaux) for WeMo support. Install these using `pip install pyephem requests phue ouimeaux pychromecast`.
|
||||||
* Clone the repository and pull in the submodules `git clone --recursive https://github.com/balloob/home-assistant.git`
|
* Clone the repository and pull in the submodules `git clone --recursive https://github.com/balloob/home-assistant.git`
|
||||||
* Copy home-assistant.conf.default to home-assistant.conf and adjust the config values to match your setup.
|
* Copy home-assistant.conf.default to home-assistant.conf and adjust the config values to match your setup.
|
||||||
* For Tomato you will have to not only setup your host, username and password but also a http_id. The http_id can be retrieved by going to the admin console of your router, view the source of any of the pages and search for `http_id`.
|
* For Tomato you will have to not only setup your host, username and password but also a http_id. The http_id can be retrieved by going to the admin console of your router, view the source of any of the pages and search for `http_id`.
|
||||||
* Setup PHue by running `python -m phue --host HUE_BRIDGE_IP_ADDRESS` from the commandline.
|
* If you want to use Hue, setup PHue by running `python -m phue --host HUE_BRIDGE_IP_ADDRESS` from the commandline and follow the instructions.
|
||||||
* While running the script it will create and maintain a file called `known_devices.csv` which will contain the detected devices. Adjust the track variable for the devices you want the script to act on and restart the script or call the service `device_tracker/reload_devices_csv`.
|
* While running the script it will create and maintain a file called `known_devices.csv` which will contain the detected devices. Adjust the track variable for the devices you want the script to act on and restart the script or call the service `device_tracker/reload_devices_csv`.
|
||||||
|
|
||||||
Done. Start it now by running `python start.py`
|
Done. Start it now by running `python start.py`
|
||||||
@ -205,6 +205,9 @@ Action: sets the state per device and maintains a combined state called `all_dev
|
|||||||
**Light**
|
**Light**
|
||||||
Keeps track which lights are turned on and can control the lights.
|
Keeps track which lights are turned on and can control the lights.
|
||||||
|
|
||||||
|
**WeMo**
|
||||||
|
Keeps track which WeMo switches are in the network and allows you to control them.
|
||||||
|
|
||||||
**device_sun_light_trigger**
|
**device_sun_light_trigger**
|
||||||
Turns lights on or off using a light control component based on state of the sun and devices that are home.
|
Turns lights on or off using a light control component based on state of the sun and devices that are home.
|
||||||
Depends on: light control, track_sun, DeviceTracker
|
Depends on: light control, track_sun, DeviceTracker
|
||||||
|
@ -128,6 +128,12 @@ def from_config_file(config_path):
|
|||||||
else:
|
else:
|
||||||
chromecast_started = False
|
chromecast_started = False
|
||||||
|
|
||||||
|
# WeMo
|
||||||
|
if has_section("wemo"):
|
||||||
|
wemo = load_module('wemo')
|
||||||
|
|
||||||
|
add_status("WeMo", wemo.setup(bus, statemachine))
|
||||||
|
|
||||||
# Light control
|
# Light control
|
||||||
if has_section("light.hue"):
|
if has_section("light.hue"):
|
||||||
light = load_module('light')
|
light = load_module('light')
|
||||||
|
@ -21,6 +21,7 @@ import homeassistant as ha
|
|||||||
import homeassistant.util as util
|
import homeassistant.util as util
|
||||||
|
|
||||||
ATTR_ENTITY_ID = 'entity_id'
|
ATTR_ENTITY_ID = 'entity_id'
|
||||||
|
ATTR_FRIENDLY_NAME = "friendly_name"
|
||||||
|
|
||||||
STATE_ON = 'on'
|
STATE_ON = 'on'
|
||||||
STATE_OFF = 'off'
|
STATE_OFF = 'off'
|
||||||
|
143
homeassistant/components/wemo.py
Normal file
143
homeassistant/components/wemo.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
"""
|
||||||
|
Component to interface with WeMo devices on the network.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import socket
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
import homeassistant as ha
|
||||||
|
import homeassistant.util as util
|
||||||
|
from homeassistant.components import (group, STATE_ON, STATE_OFF,
|
||||||
|
SERVICE_TURN_ON, SERVICE_TURN_OFF,
|
||||||
|
ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME)
|
||||||
|
DOMAIN = 'wemo'
|
||||||
|
|
||||||
|
GROUP_NAME_ALL_WEMOS = 'all_wemos'
|
||||||
|
ENTITY_ID_ALL_WEMOS = group.ENTITY_ID_FORMAT.format(
|
||||||
|
GROUP_NAME_ALL_WEMOS)
|
||||||
|
|
||||||
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
|
|
||||||
|
ATTR_TODAY_KWH = "today_kwh"
|
||||||
|
ATTR_CURRENT_POWER = "current_power"
|
||||||
|
ATTR_TODAY_ON_TIME = "today_on_time"
|
||||||
|
ATTR_TODAY_STANDBY_TIME = "today_standby_time"
|
||||||
|
|
||||||
|
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
def setup(bus, statemachine):
|
||||||
|
""" Track states and offer events for WeMo switches. """
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ouimeaux.environment as wemo_env
|
||||||
|
import ouimeaux.device.switch as wemo_switch
|
||||||
|
import ouimeaux.device.insight as wemo_insight
|
||||||
|
except ImportError:
|
||||||
|
logger.exception(("Failed to import ouimeaux. "
|
||||||
|
"Did you maybe not install the 'ouimeaux' "
|
||||||
|
"dependency?"))
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
env = wemo_env.Environment()
|
||||||
|
|
||||||
|
try:
|
||||||
|
env.start()
|
||||||
|
except socket.error:
|
||||||
|
# If the socket is already in use
|
||||||
|
logger.exception("Error starting WeMo environment")
|
||||||
|
return False
|
||||||
|
|
||||||
|
env.discover(5)
|
||||||
|
|
||||||
|
if len(env.list_switches()) == 0:
|
||||||
|
logger.error("No WeMo switches found")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Dict mapping serial no to entity IDs
|
||||||
|
sno_to_ent = {}
|
||||||
|
# Dict mapping entity IDs to devices
|
||||||
|
ent_to_dev = {}
|
||||||
|
|
||||||
|
def _update_wemo_state(device):
|
||||||
|
""" Update the state of specified WeMo device. """
|
||||||
|
|
||||||
|
# We currently only support switches
|
||||||
|
if not isinstance(device, wemo_switch.Switch):
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
entity_id = sno_to_ent[device.serialnumber]
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
# New device, set it up
|
||||||
|
entity_id = ENTITY_ID_FORMAT.format(util.slugify(device.name))
|
||||||
|
|
||||||
|
sno_to_ent[device.serialnumber] = entity_id
|
||||||
|
ent_to_dev[entity_id] = device
|
||||||
|
|
||||||
|
state = STATE_ON if device.get_state(True) else STATE_OFF
|
||||||
|
|
||||||
|
state_attr = {ATTR_FRIENDLY_NAME: device.name}
|
||||||
|
|
||||||
|
if isinstance(device, wemo_insight.Insight):
|
||||||
|
pass
|
||||||
|
# Should work but doesn't..
|
||||||
|
#state_attr[ATTR_TODAY_KWH] = device.today_kwh
|
||||||
|
#state_attr[ATTR_CURRENT_POWER] = device.current_power
|
||||||
|
#state_attr[ATTR_TODAY_ON_TIME] = device.today_on_time
|
||||||
|
#state_attr[ATTR_TODAY_STANDBY_TIME] = device.today_standby_time
|
||||||
|
|
||||||
|
statemachine.set_state(entity_id, state, state_attr)
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
def _update_wemos_state(time, force_reload=False):
|
||||||
|
""" Update states of all WeMo devices. """
|
||||||
|
|
||||||
|
# First time this method gets called, force_reload should be True
|
||||||
|
if (force_reload or
|
||||||
|
datetime.now() - _update_wemos_state.last_updated >
|
||||||
|
MIN_TIME_BETWEEN_SCANS):
|
||||||
|
|
||||||
|
logger.info("Updating WeMo status")
|
||||||
|
_update_wemos_state.last_updated = datetime.now()
|
||||||
|
|
||||||
|
for device in env:
|
||||||
|
_update_wemo_state(device)
|
||||||
|
|
||||||
|
_update_wemos_state(None, True)
|
||||||
|
|
||||||
|
# Track all lights in a group
|
||||||
|
group.setup(bus, statemachine,
|
||||||
|
GROUP_NAME_ALL_WEMOS, sno_to_ent.values())
|
||||||
|
|
||||||
|
def _handle_wemo_service(service):
|
||||||
|
""" Handles calls to the WeMo service. """
|
||||||
|
dat = service.data
|
||||||
|
|
||||||
|
if ATTR_ENTITY_ID in dat:
|
||||||
|
device = ent_to_dev.get(dat[ATTR_ENTITY_ID])
|
||||||
|
|
||||||
|
devices = [device] if device is not None else []
|
||||||
|
else:
|
||||||
|
devices = ent_to_dev.values()
|
||||||
|
|
||||||
|
for device in devices:
|
||||||
|
if service.service == SERVICE_TURN_ON:
|
||||||
|
device.on()
|
||||||
|
else:
|
||||||
|
device.off()
|
||||||
|
|
||||||
|
_update_wemo_state(device)
|
||||||
|
|
||||||
|
# Update WeMo state every 30 seconds
|
||||||
|
ha.track_time_change(bus, _update_wemos_state, second=[0, 30])
|
||||||
|
|
||||||
|
bus.register_service(DOMAIN, SERVICE_TURN_OFF, _handle_wemo_service)
|
||||||
|
|
||||||
|
bus.register_service(DOMAIN, SERVICE_TURN_ON, _handle_wemo_service)
|
||||||
|
|
||||||
|
return True
|
Loading…
x
Reference in New Issue
Block a user