Added wink component to auto-load other needed components
parent
249cf244ca
commit
6cd53f2ddf
|
@ -11,6 +11,10 @@ api_password=mypass
|
|||
[light]
|
||||
platform=hue
|
||||
|
||||
[wink]
|
||||
# Get your token at https://winkbearertoken.appspot.com
|
||||
token=YOUR_TOKEN
|
||||
|
||||
[device_tracker]
|
||||
# The following types are available: netgear, tomato, luci, nmap_tracker
|
||||
platform=netgear
|
||||
|
|
|
@ -15,15 +15,13 @@ from homeassistant.external.netdisco.netdisco import DiscoveryService
|
|||
import homeassistant.external.netdisco.netdisco.const as services
|
||||
|
||||
from homeassistant import bootstrap
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START, ATTR_SERVICE
|
||||
from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_START, EVENT_SERVICE_DISCOVERED,
|
||||
ATTR_SERVICE, ATTR_DISCOVERED)
|
||||
|
||||
DOMAIN = "discovery"
|
||||
DEPENDENCIES = []
|
||||
|
||||
EVENT_SERVICE_DISCOVERED = "service_discovered"
|
||||
|
||||
ATTR_DISCOVERED = "discovered"
|
||||
|
||||
SCAN_INTERVAL = 300 # seconds
|
||||
|
||||
SERVICE_HANDLERS = {
|
||||
|
|
|
@ -52,12 +52,13 @@ import logging
|
|||
import os
|
||||
import csv
|
||||
|
||||
from homeassistant.loader import get_component
|
||||
import homeassistant.util as util
|
||||
from homeassistant.const import (
|
||||
STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID)
|
||||
from homeassistant.helpers import (
|
||||
extract_entity_ids, platform_devices_from_config)
|
||||
from homeassistant.components import group
|
||||
from homeassistant.components import group, discovery, wink
|
||||
|
||||
|
||||
DOMAIN = "light"
|
||||
|
@ -89,6 +90,11 @@ FLASH_LONG = "long"
|
|||
|
||||
LIGHT_PROFILES_FILE = "light_profiles.csv"
|
||||
|
||||
# Maps discovered services to their platforms
|
||||
DISCOVERY_PLATFORMS = {
|
||||
wink.DISCOVER_LIGHTS: 'wink',
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -165,19 +171,41 @@ def setup(hass, config):
|
|||
lights = platform_devices_from_config(
|
||||
config, DOMAIN, hass, ENTITY_ID_FORMAT, _LOGGER)
|
||||
|
||||
if not lights:
|
||||
return False
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def update_lights_state(now):
|
||||
""" Update the states of all the lights. """
|
||||
for light in lights.values():
|
||||
light.update_ha_state(hass)
|
||||
if lights:
|
||||
_LOGGER.info("Updating light states")
|
||||
|
||||
for light in lights.values():
|
||||
light.update_ha_state(hass)
|
||||
|
||||
update_lights_state(None)
|
||||
|
||||
# Track all lights in a group
|
||||
group.Group(hass, GROUP_NAME_ALL_LIGHTS, lights.keys(), False)
|
||||
light_group = group.Group(
|
||||
hass, GROUP_NAME_ALL_LIGHTS, lights.keys(), False)
|
||||
|
||||
def light_discovered(service, info):
|
||||
""" Called when a light is discovered. """
|
||||
platform = get_component(
|
||||
"{}.{}".format(DOMAIN, DISCOVERY_PLATFORMS[service]))
|
||||
|
||||
discovered = platform.device_discovered(hass, config, info)
|
||||
|
||||
for light in discovered:
|
||||
if light is not None and light not in lights.values():
|
||||
light.entity_id = util.ensure_unique_string(
|
||||
ENTITY_ID_FORMAT.format(util.slugify(light.get_name())),
|
||||
lights.keys())
|
||||
|
||||
lights[light.entity_id] = light
|
||||
|
||||
light.update_ha_state(hass)
|
||||
|
||||
light_group.update_tracked_entity_ids(lights.keys())
|
||||
|
||||
discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), light_discovered)
|
||||
|
||||
def handle_light_service(service):
|
||||
""" Hande a turn light on or off service call. """
|
||||
|
|
|
@ -1,25 +1,37 @@
|
|||
""" Support for Hue lights. """
|
||||
import logging
|
||||
|
||||
# pylint: disable=no-name-in-module, import-error
|
||||
import homeassistant.external.wink.pywink as pywink
|
||||
|
||||
from homeassistant.helpers import ToggleDevice
|
||||
from homeassistant.const import ATTR_FRIENDLY_NAME
|
||||
from homeassistant.const import ATTR_FRIENDLY_NAME, CONF_ACCESS_TOKEN
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_devices(hass, config):
|
||||
""" Find and return Wink lights. """
|
||||
token = config.get('access_token')
|
||||
token = config.get(CONF_ACCESS_TOKEN)
|
||||
|
||||
if token is None:
|
||||
logging.getLogger(__name__).error(
|
||||
"Missing wink access_token - "
|
||||
"get one at https://winkbearertoken.appspot.com/")
|
||||
return False
|
||||
return []
|
||||
|
||||
pywink.set_bearer_token(token)
|
||||
|
||||
return get_lights()
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
return get_lights()
|
||||
|
||||
|
||||
def get_lights():
|
||||
""" Returns the Wink switches. """
|
||||
return [WinkLight(light) for light in pywink.get_bulbs()]
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from homeassistant.const import (
|
|||
STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID)
|
||||
from homeassistant.helpers import (
|
||||
extract_entity_ids, platform_devices_from_config)
|
||||
from homeassistant.components import group, discovery
|
||||
from homeassistant.components import group, discovery, wink
|
||||
|
||||
DOMAIN = 'switch'
|
||||
DEPENDENCIES = []
|
||||
|
@ -29,8 +29,9 @@ ATTR_CURRENT_POWER_MWH = "current_power_mwh"
|
|||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
|
||||
# Maps discovered services to their platforms
|
||||
DISCOVERY = {
|
||||
discovery.services.BELKIN_WEMO: 'wemo'
|
||||
DISCOVERY_PLATFORMS = {
|
||||
discovery.services.BELKIN_WEMO: 'wemo',
|
||||
wink.DISCOVER_SWITCHES: 'wink',
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -82,22 +83,24 @@ def setup(hass, config):
|
|||
|
||||
def switch_discovered(service, info):
|
||||
""" Called when a switch is discovered. """
|
||||
platform = get_component("{}.{}".format(DOMAIN, DISCOVERY[service]))
|
||||
platform = get_component("{}.{}".format(
|
||||
DOMAIN, DISCOVERY_PLATFORMS[service]))
|
||||
|
||||
switch = platform.device_discovered(hass, config, info)
|
||||
discovered = platform.device_discovered(hass, config, info)
|
||||
|
||||
if switch is not None and switch not in switches.values():
|
||||
switch.entity_id = util.ensure_unique_string(
|
||||
ENTITY_ID_FORMAT.format(util.slugify(switch.get_name())),
|
||||
switches.keys())
|
||||
for switch in discovered:
|
||||
if switch is not None and switch not in switches.values():
|
||||
switch.entity_id = util.ensure_unique_string(
|
||||
ENTITY_ID_FORMAT.format(util.slugify(switch.get_name())),
|
||||
switches.keys())
|
||||
|
||||
switches[switch.entity_id] = switch
|
||||
switches[switch.entity_id] = switch
|
||||
|
||||
switch.update_ha_state(hass)
|
||||
switch.update_ha_state(hass)
|
||||
|
||||
switch_group.update_tracked_entity_ids(switches.keys())
|
||||
switch_group.update_tracked_entity_ids(switches.keys())
|
||||
|
||||
discovery.listen(hass, discovery.services.BELKIN_WEMO, switch_discovered)
|
||||
discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), switch_discovered)
|
||||
|
||||
def handle_switch_service(service):
|
||||
""" Handles calls to the switch services. """
|
||||
|
|
|
@ -24,16 +24,16 @@ def get_devices(hass, config):
|
|||
if isinstance(switch, pywemo.Switch)]
|
||||
|
||||
|
||||
def device_discovered(hass, config, info):
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
_, discovery = get_pywemo()
|
||||
|
||||
if discovery is None:
|
||||
return
|
||||
return []
|
||||
|
||||
device = discovery.device_from_description(info)
|
||||
|
||||
return None if device is None else WemoSwitch(device)
|
||||
return [] if device is None else [WemoSwitch(device)]
|
||||
|
||||
|
||||
def get_pywemo():
|
||||
|
|
|
@ -1,25 +1,37 @@
|
|||
""" Support for WeMo switchces. """
|
||||
import logging
|
||||
|
||||
# pylint: disable=no-name-in-module, import-error
|
||||
import homeassistant.external.wink.pywink as pywink
|
||||
|
||||
from homeassistant.helpers import ToggleDevice
|
||||
from homeassistant.const import ATTR_FRIENDLY_NAME
|
||||
from homeassistant.const import ATTR_FRIENDLY_NAME, CONF_ACCESS_TOKEN
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_devices(hass, config):
|
||||
""" Find and return Wink switches. """
|
||||
token = config.get('access_token')
|
||||
token = config.get(CONF_ACCESS_TOKEN)
|
||||
|
||||
if token is None:
|
||||
logging.getLogger(__name__).error(
|
||||
"Missing wink access_token - "
|
||||
"get one at https://winkbearertoken.appspot.com/")
|
||||
return False
|
||||
return []
|
||||
|
||||
pywink.set_bearer_token(token)
|
||||
|
||||
return get_switches()
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
return get_switches()
|
||||
|
||||
|
||||
def get_switches():
|
||||
""" Returns the Wink switches. """
|
||||
return [WinkSwitch(switch) for switch in pywink.get_switches()]
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
"""
|
||||
Connects to a Wink hub and loads relevant components to control its devices.
|
||||
"""
|
||||
import logging
|
||||
|
||||
# pylint: disable=no-name-in-module, import-error
|
||||
import homeassistant.external.wink.pywink as pywink
|
||||
|
||||
from homeassistant import bootstrap
|
||||
from homeassistant.loader import get_component
|
||||
from homeassistant.helpers import validate_config
|
||||
from homeassistant.const import (
|
||||
EVENT_SERVICE_DISCOVERED, ATTR_SERVICE, ATTR_DISCOVERED, CONF_ACCESS_TOKEN)
|
||||
|
||||
DOMAIN = "wink"
|
||||
DEPENDENCIES = []
|
||||
|
||||
DISCOVER_LIGHTS = "wink.lights"
|
||||
DISCOVER_SWITCHES = "wink.switches"
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
""" Sets up the Wink component. """
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
print(config)
|
||||
|
||||
if not validate_config(config, {DOMAIN: [CONF_ACCESS_TOKEN]}, logger):
|
||||
return False
|
||||
|
||||
pywink.set_bearer_token(config[DOMAIN][CONF_ACCESS_TOKEN])
|
||||
|
||||
# Load components for the devices in the Wink that we support
|
||||
for component_name, func_exists, discovery_type in (
|
||||
('light', pywink.get_bulbs, DISCOVER_LIGHTS),
|
||||
('switch', pywink.get_switches, DISCOVER_SWITCHES)):
|
||||
|
||||
component = get_component(component_name)
|
||||
|
||||
if func_exists():
|
||||
# Ensure component is loaded
|
||||
if component.DOMAIN not in hass.components:
|
||||
# Add a worker on succesfull setup
|
||||
if bootstrap.setup_component(hass, component.DOMAIN, config):
|
||||
hass.pool.add_worker()
|
||||
|
||||
# Fire discovery event
|
||||
hass.bus.fire(EVENT_SERVICE_DISCOVERED, {
|
||||
ATTR_SERVICE: discovery_type,
|
||||
ATTR_DISCOVERED: {}
|
||||
})
|
|
@ -15,6 +15,7 @@ CONF_HOSTS = "hosts"
|
|||
CONF_USERNAME = "username"
|
||||
CONF_PASSWORD = "password"
|
||||
CONF_API_KEY = "api_key"
|
||||
CONF_ACCESS_TOKEN = "access_token"
|
||||
|
||||
# #### EVENTS ####
|
||||
EVENT_HOMEASSISTANT_START = "homeassistant_start"
|
||||
|
@ -23,6 +24,7 @@ EVENT_STATE_CHANGED = "state_changed"
|
|||
EVENT_TIME_CHANGED = "time_changed"
|
||||
EVENT_CALL_SERVICE = "call_service"
|
||||
EVENT_SERVICE_EXECUTED = "service_executed"
|
||||
EVENT_SERVICE_DISCOVERED = "service_discovered"
|
||||
|
||||
# #### STATES ####
|
||||
STATE_ON = 'on'
|
||||
|
@ -54,6 +56,9 @@ ATTR_ENTITY_PICTURE = "entity_picture"
|
|||
# The unit of measurement if applicable
|
||||
ATTR_UNIT_OF_MEASUREMENT = "unit_of_measurement"
|
||||
|
||||
# Contains the information that is discovered
|
||||
ATTR_DISCOVERED = "discovered"
|
||||
|
||||
# #### SERVICES ####
|
||||
SERVICE_HOMEASSISTANT_STOP = "stop"
|
||||
|
||||
|
|
|
@ -214,28 +214,6 @@ class TestLight(unittest.TestCase):
|
|||
light.ATTR_XY_COLOR: [prof_x, prof_y]},
|
||||
data)
|
||||
|
||||
def test_setup(self):
|
||||
""" Test the setup method. """
|
||||
# Bogus config
|
||||
self.assertFalse(light.setup(self.hass, {}))
|
||||
|
||||
self.assertFalse(light.setup(self.hass, {light.DOMAIN: {}}))
|
||||
|
||||
# Test with non-existing component
|
||||
self.assertFalse(light.setup(
|
||||
self.hass, {light.DOMAIN: {CONF_TYPE: 'nonexisting'}}
|
||||
))
|
||||
|
||||
# Test if light component returns 0 lightes
|
||||
platform = loader.get_component('light.test')
|
||||
platform.init(True)
|
||||
|
||||
self.assertEqual([], platform.get_lights(None, None))
|
||||
|
||||
self.assertFalse(light.setup(
|
||||
self.hass, {light.DOMAIN: {CONF_TYPE: 'test'}}
|
||||
))
|
||||
|
||||
def test_light_profiles(self):
|
||||
""" Test light profiles. """
|
||||
platform = loader.get_component('light.test')
|
||||
|
|
Loading…
Reference in New Issue