Migrate alarm control panel to async (#4807)

* Merge alarm control panel to async

* fix lint
pull/4855/head
Pascal Vizeli 2016-12-11 23:39:20 +01:00 committed by Paulus Schoutsen
parent 46cad514d4
commit 99f1ea9b59
8 changed files with 77 additions and 73 deletions

View File

@ -4,6 +4,7 @@ Component to interface with an alarm control panel.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel/ https://home-assistant.io/components/alarm_control_panel/
""" """
import asyncio
import logging import logging
import os import os
@ -42,40 +43,6 @@ ALARM_SERVICE_SCHEMA = vol.Schema({
}) })
def setup(hass, config):
"""Track states and offer events for sensors."""
component = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
component.setup(config)
def alarm_service_handler(service):
"""Map services to methods on Alarm."""
target_alarms = component.extract_from_service(service)
code = service.data.get(ATTR_CODE)
method = SERVICE_TO_METHOD[service.service]
for alarm in target_alarms:
getattr(alarm, method)(code)
for alarm in target_alarms:
if not alarm.should_poll:
continue
alarm.update_ha_state(True)
descriptions = load_yaml_config_file(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
for service in SERVICE_TO_METHOD:
hass.services.register(DOMAIN, service, alarm_service_handler,
descriptions.get(service),
schema=ALARM_SERVICE_SCHEMA)
return True
def alarm_disarm(hass, code=None, entity_id=None): def alarm_disarm(hass, code=None, entity_id=None):
"""Send the alarm the command for disarm.""" """Send the alarm the command for disarm."""
data = {} data = {}
@ -120,6 +87,53 @@ def alarm_trigger(hass, code=None, entity_id=None):
hass.services.call(DOMAIN, SERVICE_ALARM_TRIGGER, data) hass.services.call(DOMAIN, SERVICE_ALARM_TRIGGER, data)
@asyncio.coroutine
def async_setup(hass, config):
"""Track states and offer events for sensors."""
component = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
yield from component.async_setup(config)
@asyncio.coroutine
def async_alarm_service_handler(service):
"""Map services to methods on Alarm."""
target_alarms = component.async_extract_from_service(service)
code = service.data.get(ATTR_CODE)
method = "async_{}".format(SERVICE_TO_METHOD[service.service])
for alarm in target_alarms:
yield from getattr(alarm, method)(code)
update_tasks = []
for alarm in target_alarms:
if not alarm.should_poll:
continue
update_coro = hass.loop.create_task(
alarm.async_update_ha_state(True))
if hasattr(alarm, 'async_update'):
update_tasks.append(hass.loop.create_task(update_coro))
else:
yield from update_coro
if update_tasks:
yield from asyncio.wait(update_tasks, loop=hass.loop)
descriptions = yield from hass.loop.run_in_executor(
None, load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml'))
for service in SERVICE_TO_METHOD:
hass.services.async_register(
DOMAIN, service, async_alarm_service_handler,
descriptions.get(service), schema=ALARM_SERVICE_SCHEMA)
return True
# pylint: disable=no-self-use # pylint: disable=no-self-use
class AlarmControlPanel(Entity): class AlarmControlPanel(Entity):
"""An abstract class for alarm control devices.""" """An abstract class for alarm control devices."""
@ -138,18 +152,42 @@ class AlarmControlPanel(Entity):
"""Send disarm command.""" """Send disarm command."""
raise NotImplementedError() raise NotImplementedError()
@asyncio.coroutine
def async_alarm_disarm(self, code=None):
"""Send disarm command."""
yield from self.hass.loop.run_in_executor(
None, self.alarm_disarm, code)
def alarm_arm_home(self, code=None): def alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
raise NotImplementedError() raise NotImplementedError()
@asyncio.coroutine
def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
yield from self.hass.loop.run_in_executor(
None, self.alarm_arm_home, code)
def alarm_arm_away(self, code=None): def alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
raise NotImplementedError() raise NotImplementedError()
@asyncio.coroutine
def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
yield from self.hass.loop.run_in_executor(
None, self.alarm_arm_away, code)
def alarm_trigger(self, code=None): def alarm_trigger(self, code=None):
"""Send alarm trigger command.""" """Send alarm trigger command."""
raise NotImplementedError() raise NotImplementedError()
@asyncio.coroutine
def async_alarm_trigger(self, code=None):
"""Send alarm trigger command."""
yield from self.hass.loop.run_in_executor(
None, self.alarm_trigger, code)
@property @property
def state_attributes(self): def state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""

View File

@ -56,11 +56,6 @@ class AlarmDotCom(alarm.AlarmControlPanel):
self._password = password self._password = password
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
@property
def should_poll(self):
"""No polling needed."""
return True
def update(self): def update(self):
"""Fetch the latest state.""" """Fetch the latest state."""
self._state = self._alarm.state self._state = self._alarm.state

View File

@ -71,11 +71,6 @@ class Concord232Alarm(alarm.AlarmControlPanel):
self._alarm.last_partition_update = datetime.datetime.now() self._alarm.last_partition_update = datetime.datetime.now()
self.update() self.update()
@property
def should_poll(self):
"""Polling needed."""
return True
@property @property
def name(self): def name(self):
"""Return the name of the device.""" """Return the name of the device."""
@ -126,7 +121,3 @@ class Concord232Alarm(alarm.AlarmControlPanel):
def alarm_arm_away(self, code=None): def alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
self._alarm.arm('auto') self._alarm.arm('auto')
def alarm_trigger(self, code=None):
"""Alarm trigger command."""
raise NotImplementedError()

View File

@ -97,7 +97,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
def _update_callback(self, partition): def _update_callback(self, partition):
"""Update HA state, if needed.""" """Update HA state, if needed."""
if partition is None or int(partition) == self._partition_number: if partition is None or int(partition) == self._partition_number:
self.hass.async_add_job(self.update_ha_state) self.hass.async_add_job(self.async_update_ha_state())
@property @property
def code_format(self): def code_format(self):

View File

@ -116,7 +116,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._state = STATE_ALARM_DISARMED self._state = STATE_ALARM_DISARMED
self._state_ts = dt_util.utcnow() self._state_ts = dt_util.utcnow()
self.update_ha_state() self.schedule_update_ha_state()
def alarm_arm_home(self, code=None): def alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
@ -125,7 +125,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._state = STATE_ALARM_ARMED_HOME self._state = STATE_ALARM_ARMED_HOME
self._state_ts = dt_util.utcnow() self._state_ts = dt_util.utcnow()
self.update_ha_state() self.schedule_update_ha_state()
if self._pending_time: if self._pending_time:
track_point_in_time( track_point_in_time(
@ -139,7 +139,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._state = STATE_ALARM_ARMED_AWAY self._state = STATE_ALARM_ARMED_AWAY
self._state_ts = dt_util.utcnow() self._state_ts = dt_util.utcnow()
self.update_ha_state() self.schedule_update_ha_state()
if self._pending_time: if self._pending_time:
track_point_in_time( track_point_in_time(
@ -151,7 +151,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
self._pre_trigger_state = self._state self._pre_trigger_state = self._state
self._state = STATE_ALARM_TRIGGERED self._state = STATE_ALARM_TRIGGERED
self._state_ts = dt_util.utcnow() self._state_ts = dt_util.utcnow()
self.update_ha_state() self.schedule_update_ha_state()
if self._trigger_time: if self._trigger_time:
track_point_in_time( track_point_in_time(

View File

@ -62,11 +62,6 @@ class NX584Alarm(alarm.AlarmControlPanel):
self._alarm.list_zones() self._alarm.list_zones()
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
@property
def should_poll(self):
"""Polling needed."""
return True
@property @property
def name(self): def name(self):
"""Return the name of the device.""" """Return the name of the device."""
@ -122,7 +117,3 @@ class NX584Alarm(alarm.AlarmControlPanel):
def alarm_arm_away(self, code=None): def alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
self._alarm.arm('exit') self._alarm.arm('exit')
def alarm_trigger(self, code=None):
"""Alarm trigger command."""
raise NotImplementedError()

View File

@ -61,11 +61,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
else: else:
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
@property
def should_poll(self):
"""Poll the SimpliSafe API."""
return True
@property @property
def name(self): def name(self):
"""Return the name of the device.""" """Return the name of the device."""
@ -104,7 +99,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
return return
self.simplisafe.set_state('off') self.simplisafe.set_state('off')
_LOGGER.info('SimpliSafe alarm disarming') _LOGGER.info('SimpliSafe alarm disarming')
self.update()
def alarm_arm_home(self, code=None): def alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
@ -112,7 +106,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
return return
self.simplisafe.set_state('home') self.simplisafe.set_state('home')
_LOGGER.info('SimpliSafe alarm arming home') _LOGGER.info('SimpliSafe alarm arming home')
self.update()
def alarm_arm_away(self, code=None): def alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
@ -120,7 +113,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
return return
self.simplisafe.set_state('away') self.simplisafe.set_state('away')
_LOGGER.info('SimpliSafe alarm arming away') _LOGGER.info('SimpliSafe alarm arming away')
self.update()
def _validate_code(self, code, state): def _validate_code(self, code, state):
"""Validate given code.""" """Validate given code."""

View File

@ -84,18 +84,15 @@ class VerisureAlarm(alarm.AlarmControlPanel):
hub.my_pages.alarm.set(code, 'DISARMED') hub.my_pages.alarm.set(code, 'DISARMED')
_LOGGER.info('verisure alarm disarming') _LOGGER.info('verisure alarm disarming')
hub.my_pages.alarm.wait_while_pending() hub.my_pages.alarm.wait_while_pending()
self.update()
def alarm_arm_home(self, code=None): def alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
hub.my_pages.alarm.set(code, 'ARMED_HOME') hub.my_pages.alarm.set(code, 'ARMED_HOME')
_LOGGER.info('verisure alarm arming home') _LOGGER.info('verisure alarm arming home')
hub.my_pages.alarm.wait_while_pending() hub.my_pages.alarm.wait_while_pending()
self.update()
def alarm_arm_away(self, code=None): def alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
hub.my_pages.alarm.set(code, 'ARMED_AWAY') hub.my_pages.alarm.set(code, 'ARMED_AWAY')
_LOGGER.info('verisure alarm arming away') _LOGGER.info('verisure alarm arming away')
hub.my_pages.alarm.wait_while_pending() hub.my_pages.alarm.wait_while_pending()
self.update()