mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 17:27:10 +00:00
Merge pull request #1077 from xrolfex/wink_garage_door_support
Wink Garage Door Support
This commit is contained in:
commit
4ce1a67c13
@ -152,7 +152,7 @@ omit =
|
||||
homeassistant/components/thermostat/honeywell.py
|
||||
homeassistant/components/thermostat/proliphix.py
|
||||
homeassistant/components/thermostat/radiotherm.py
|
||||
|
||||
homeassistant/components/garage_door/wink.py
|
||||
|
||||
[report]
|
||||
# Regexes for lines to exclude from consideration
|
||||
|
@ -21,6 +21,7 @@ COMPONENTS_WITH_DEMO_PLATFORM = [
|
||||
'binary_sensor',
|
||||
'camera',
|
||||
'device_tracker',
|
||||
'garage_door',
|
||||
'light',
|
||||
'lock',
|
||||
'media_player',
|
||||
|
108
homeassistant/components/garage_door/__init__.py
Normal file
108
homeassistant/components/garage_door/__init__.py
Normal file
@ -0,0 +1,108 @@
|
||||
"""
|
||||
homeassistant.components.garage_door
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Component to interface with garage doors that can be controlled remotely.
|
||||
|
||||
For more details about this component, please refer to the documentation
|
||||
at https://home-assistant.io/components/garage_door/
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from homeassistant.const import (
|
||||
STATE_CLOSED, STATE_OPEN, STATE_UNKNOWN, SERVICE_CLOSE, SERVICE_OPEN,
|
||||
ATTR_ENTITY_ID)
|
||||
from homeassistant.components import (group, wink)
|
||||
|
||||
DOMAIN = 'garage_door'
|
||||
SCAN_INTERVAL = 30
|
||||
|
||||
GROUP_NAME_ALL_GARAGE_DOORS = 'all garage doors'
|
||||
ENTITY_ID_ALL_GARAGE_DOORS = group.ENTITY_ID_FORMAT.format('all_garage_doors')
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
|
||||
# Maps discovered services to their platforms
|
||||
DISCOVERY_PLATFORMS = {
|
||||
wink.DISCOVER_GARAGE_DOORS: 'wink'
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def is_closed(hass, entity_id=None):
|
||||
""" Returns if the garage door is closed based on the statemachine. """
|
||||
entity_id = entity_id or ENTITY_ID_ALL_GARAGE_DOORS
|
||||
return hass.states.is_state(entity_id, STATE_CLOSED)
|
||||
|
||||
|
||||
def close_door(hass, entity_id=None):
|
||||
""" Closes all or specified garage door. """
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
hass.services.call(DOMAIN, SERVICE_CLOSE, data)
|
||||
|
||||
|
||||
def open_door(hass, entity_id=None):
|
||||
""" Open all or specified garage door. """
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
hass.services.call(DOMAIN, SERVICE_OPEN, data)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
""" Track states and offer events for garage door. """
|
||||
component = EntityComponent(
|
||||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, DISCOVERY_PLATFORMS,
|
||||
GROUP_NAME_ALL_GARAGE_DOORS)
|
||||
component.setup(config)
|
||||
|
||||
def handle_garage_door_service(service):
|
||||
""" Handles calls to the garage door services. """
|
||||
target_locks = component.extract_from_service(service)
|
||||
|
||||
for item in target_locks:
|
||||
if service.service == SERVICE_CLOSE:
|
||||
item.close_door()
|
||||
else:
|
||||
item.open_door()
|
||||
|
||||
if item.should_poll:
|
||||
item.update_ha_state(True)
|
||||
|
||||
descriptions = load_yaml_config_file(
|
||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
||||
hass.services.register(DOMAIN, SERVICE_OPEN, handle_garage_door_service,
|
||||
descriptions.get(SERVICE_OPEN))
|
||||
hass.services.register(DOMAIN, SERVICE_CLOSE, handle_garage_door_service,
|
||||
descriptions.get(SERVICE_CLOSE))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class GarageDoorDevice(Entity):
|
||||
""" Represents a garage door within Home Assistant. """
|
||||
# pylint: disable=no-self-use
|
||||
|
||||
@property
|
||||
def is_closed(self):
|
||||
""" Is the garage door closed or opened. """
|
||||
return None
|
||||
|
||||
def close_door(self):
|
||||
""" Closes the garage door. """
|
||||
raise NotImplementedError()
|
||||
|
||||
def open_door(self):
|
||||
""" Opens the garage door. """
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
closed = self.is_closed
|
||||
if closed is None:
|
||||
return STATE_UNKNOWN
|
||||
return STATE_CLOSED if closed else STATE_OPEN
|
49
homeassistant/components/garage_door/demo.py
Normal file
49
homeassistant/components/garage_door/demo.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""
|
||||
homeassistant.components.garage_door.demo
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Demo platform that has two fake garage doors.
|
||||
"""
|
||||
from homeassistant.components.garage_door import GarageDoorDevice
|
||||
from homeassistant.const import STATE_CLOSED, STATE_OPEN
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Find and return demo garage doors. """
|
||||
add_devices_callback([
|
||||
DemoGarageDoor('Left Garage Door', STATE_CLOSED),
|
||||
DemoGarageDoor('Right Garage Door', STATE_OPEN)
|
||||
])
|
||||
|
||||
|
||||
class DemoGarageDoor(GarageDoorDevice):
|
||||
""" Provides a demo garage door. """
|
||||
def __init__(self, name, state):
|
||||
self._name = name
|
||||
self._state = state
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
""" No polling needed for a demo garage door. """
|
||||
return False
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Returns the name of the device if any. """
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def is_closed(self):
|
||||
""" True if device is closed. """
|
||||
return self._state == STATE_CLOSED
|
||||
|
||||
def close_door(self, **kwargs):
|
||||
""" Close the device. """
|
||||
self._state = STATE_CLOSED
|
||||
self.update_ha_state()
|
||||
|
||||
def open_door(self, **kwargs):
|
||||
""" Open the device. """
|
||||
self._state = STATE_OPEN
|
||||
self.update_ha_state()
|
0
homeassistant/components/garage_door/services.yaml
Normal file
0
homeassistant/components/garage_door/services.yaml
Normal file
67
homeassistant/components/garage_door/wink.py
Normal file
67
homeassistant/components/garage_door/wink.py
Normal file
@ -0,0 +1,67 @@
|
||||
"""
|
||||
homeassistant.components.garage_door.wink
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Support for Wink garage doors.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/garage_door.wink/
|
||||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.garage_door import GarageDoorDevice
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN
|
||||
|
||||
REQUIREMENTS = ['python-wink==0.5.0']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Wink platform. """
|
||||
import pywink
|
||||
|
||||
if discovery_info is None:
|
||||
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
|
||||
|
||||
pywink.set_bearer_token(token)
|
||||
|
||||
add_devices(WinkGarageDoorDevice(door) for door in
|
||||
pywink.get_garage_doors())
|
||||
|
||||
|
||||
class WinkGarageDoorDevice(GarageDoorDevice):
|
||||
""" Represents a Wink garage door. """
|
||||
|
||||
def __init__(self, wink):
|
||||
self.wink = wink
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
""" Returns the id of this wink garage door """
|
||||
return "{}.{}".format(self.__class__, self.wink.device_id())
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Returns the name of the garage door if any. """
|
||||
return self.wink.name()
|
||||
|
||||
def update(self):
|
||||
""" Update the state of the garage door. """
|
||||
self.wink.update_state()
|
||||
|
||||
@property
|
||||
def is_closed(self):
|
||||
""" True if device is closed. """
|
||||
return self.wink.state() == 0
|
||||
|
||||
def close_door(self):
|
||||
""" Close the device. """
|
||||
self.wink.set_state(0)
|
||||
|
||||
def open_door(self):
|
||||
""" Open the device. """
|
||||
self.wink.set_state(1)
|
@ -22,6 +22,7 @@ DISCOVER_LIGHTS = "wink.lights"
|
||||
DISCOVER_SWITCHES = "wink.switches"
|
||||
DISCOVER_SENSORS = "wink.sensors"
|
||||
DISCOVER_LOCKS = "wink.locks"
|
||||
DISCOVER_GARAGE_DOORS = "wink.garage_doors"
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
@ -42,7 +43,8 @@ def setup(hass, config):
|
||||
pywink.get_powerstrip_outlets, DISCOVER_SWITCHES),
|
||||
('sensor', lambda: pywink.get_sensors or
|
||||
pywink.get_eggtrays, DISCOVER_SENSORS),
|
||||
('lock', pywink.get_locks, DISCOVER_LOCKS)):
|
||||
('lock', pywink.get_locks, DISCOVER_LOCKS),
|
||||
('garage_door', pywink.get_garage_doors, DISCOVER_GARAGE_DOORS)):
|
||||
|
||||
if func_exists():
|
||||
component = get_component(component_name)
|
||||
|
@ -151,6 +151,9 @@ SERVICE_ALARM_TRIGGER = "alarm_trigger"
|
||||
SERVICE_LOCK = "lock"
|
||||
SERVICE_UNLOCK = "unlock"
|
||||
|
||||
SERVICE_OPEN = "open"
|
||||
SERVICE_CLOSE = "close"
|
||||
|
||||
SERVICE_MOVE_UP = 'move_up'
|
||||
SERVICE_MOVE_DOWN = 'move_down'
|
||||
SERVICE_STOP = 'stop'
|
||||
|
@ -194,6 +194,7 @@ python-telegram-bot==3.2.0
|
||||
python-twitch==1.2.0
|
||||
|
||||
# homeassistant.components.wink
|
||||
# homeassistant.components.garage_door.wink
|
||||
# homeassistant.components.light.wink
|
||||
# homeassistant.components.lock.wink
|
||||
# homeassistant.components.sensor.wink
|
||||
|
0
tests/components/garage_door/__init__.py
Normal file
0
tests/components/garage_door/__init__.py
Normal file
51
tests/components/garage_door/test_demo.py
Normal file
51
tests/components/garage_door/test_demo.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""
|
||||
tests.components.garage_door.test_demo
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Tests demo garage door component.
|
||||
"""
|
||||
import unittest
|
||||
|
||||
import homeassistant.core as ha
|
||||
import homeassistant.components.garage_door as gd
|
||||
|
||||
|
||||
LEFT = 'garage_door.left_garage_door'
|
||||
RIGHT = 'garage_door.right_garage_door'
|
||||
|
||||
|
||||
class TestGarageDoorDemo(unittest.TestCase):
|
||||
""" Test the demo garage door. """
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
self.hass = ha.HomeAssistant()
|
||||
self.assertTrue(gd.setup(self.hass, {
|
||||
'garage_door': {
|
||||
'platform': 'demo'
|
||||
}
|
||||
}))
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""" Stop down stuff we started. """
|
||||
self.hass.stop()
|
||||
|
||||
def test_is_closed(self):
|
||||
self.assertTrue(gd.is_closed(self.hass, LEFT))
|
||||
self.hass.states.is_state(LEFT, 'close')
|
||||
|
||||
self.assertFalse(gd.is_closed(self.hass, RIGHT))
|
||||
self.hass.states.is_state(RIGHT, 'open')
|
||||
|
||||
def test_open_door(self):
|
||||
gd.open_door(self.hass, LEFT)
|
||||
|
||||
self.hass.pool.block_till_done()
|
||||
|
||||
self.assertFalse(gd.is_closed(self.hass, LEFT))
|
||||
|
||||
def test_close_door(self):
|
||||
gd.close_door(self.hass, RIGHT)
|
||||
|
||||
self.hass.pool.block_till_done()
|
||||
|
||||
self.assertTrue(gd.is_closed(self.hass, RIGHT))
|
Loading…
x
Reference in New Issue
Block a user