Migrate cover to async. (#5717)

This commit is contained in:
Pascal Vizeli 2017-02-02 21:39:13 +01:00 committed by Paulus Schoutsen
parent bc65452efb
commit f63874eb8c
5 changed files with 110 additions and 32 deletions

View file

@ -4,9 +4,11 @@ Support for Cover devices.
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/cover/ https://home-assistant.io/components/cover/
""" """
import os import asyncio
from datetime import timedelta from datetime import timedelta
import functools as ft
import logging import logging
import os
import voluptuous as vol import voluptuous as vol
@ -53,17 +55,17 @@ COVER_SET_COVER_TILT_POSITION_SCHEMA = COVER_SERVICE_SCHEMA.extend({
}) })
SERVICE_TO_METHOD = { SERVICE_TO_METHOD = {
SERVICE_OPEN_COVER: {'method': 'open_cover'}, SERVICE_OPEN_COVER: {'method': 'async_open_cover'},
SERVICE_CLOSE_COVER: {'method': 'close_cover'}, SERVICE_CLOSE_COVER: {'method': 'async_close_cover'},
SERVICE_SET_COVER_POSITION: { SERVICE_SET_COVER_POSITION: {
'method': 'set_cover_position', 'method': 'async_set_cover_position',
'schema': COVER_SET_COVER_POSITION_SCHEMA}, 'schema': COVER_SET_COVER_POSITION_SCHEMA},
SERVICE_STOP_COVER: {'method': 'stop_cover'}, SERVICE_STOP_COVER: {'method': 'async_stop_cover'},
SERVICE_OPEN_COVER_TILT: {'method': 'open_cover_tilt'}, SERVICE_OPEN_COVER_TILT: {'method': 'async_open_cover_tilt'},
SERVICE_CLOSE_COVER_TILT: {'method': 'close_cover_tilt'}, SERVICE_CLOSE_COVER_TILT: {'method': 'async_close_cover_tilt'},
SERVICE_STOP_COVER_TILT: {'method': 'stop_cover_tilt'}, SERVICE_STOP_COVER_TILT: {'method': 'async_stop_cover_tilt'},
SERVICE_SET_COVER_TILT_POSITION: { SERVICE_SET_COVER_TILT_POSITION: {
'method': 'set_cover_tilt_position', 'method': 'async_set_cover_tilt_position',
'schema': COVER_SET_COVER_TILT_POSITION_SCHEMA}, 'schema': COVER_SET_COVER_TILT_POSITION_SCHEMA},
} }
@ -124,40 +126,53 @@ def stop_cover_tilt(hass, entity_id=None):
hass.services.call(DOMAIN, SERVICE_STOP_COVER_TILT, data) hass.services.call(DOMAIN, SERVICE_STOP_COVER_TILT, data)
def setup(hass, config): @asyncio.coroutine
def async_setup(hass, config):
"""Track states and offer events for covers.""" """Track states and offer events for covers."""
component = EntityComponent( component = EntityComponent(
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_COVERS) _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_COVERS)
component.setup(config)
def handle_cover_service(service): yield from component.async_setup(config)
@asyncio.coroutine
def async_handle_cover_service(service):
"""Handle calls to the cover services.""" """Handle calls to the cover services."""
covers = component.async_extract_from_service(service)
method = SERVICE_TO_METHOD.get(service.service) method = SERVICE_TO_METHOD.get(service.service)
params = service.data.copy() params = service.data.copy()
params.pop(ATTR_ENTITY_ID, None) params.pop(ATTR_ENTITY_ID, None)
if not method: # call method
return
covers = component.extract_from_service(service)
for cover in covers: for cover in covers:
getattr(cover, method['method'])(**params) yield from getattr(cover, method['method'])(**params)
update_tasks = []
for cover in covers: for cover in covers:
if not cover.should_poll: if not cover.should_poll:
continue continue
cover.update_ha_state(True) update_coro = hass.loop.create_task(
cover.async_update_ha_state(True))
if hasattr(cover, 'async_update'):
update_tasks.append(update_coro)
else:
yield from update_coro
descriptions = load_yaml_config_file( if update_tasks:
os.path.join(os.path.dirname(__file__), 'services.yaml')) 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_name in SERVICE_TO_METHOD: for service_name in SERVICE_TO_METHOD:
schema = SERVICE_TO_METHOD[service_name].get( schema = SERVICE_TO_METHOD[service_name].get(
'schema', COVER_SERVICE_SCHEMA) 'schema', COVER_SERVICE_SCHEMA)
hass.services.register(DOMAIN, service_name, handle_cover_service, hass.services.async_register(
DOMAIN, service_name, async_handle_cover_service,
descriptions.get(service_name), schema=schema) descriptions.get(service_name), schema=schema)
return True return True
@ -215,30 +230,94 @@ class CoverDevice(Entity):
"""Open the cover.""" """Open the cover."""
raise NotImplementedError() raise NotImplementedError()
def async_open_cover(self, **kwargs):
"""Open the cover.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.open_cover, **kwargs))
def close_cover(self, **kwargs): def close_cover(self, **kwargs):
"""Close cover.""" """Close cover."""
raise NotImplementedError() raise NotImplementedError()
def async_close_cover(self, **kwargs):
"""Close cover.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.close_cover, **kwargs))
def set_cover_position(self, **kwargs): def set_cover_position(self, **kwargs):
"""Move the cover to a specific position.""" """Move the cover to a specific position."""
pass pass
def async_set_cover_position(self, **kwargs):
"""Move the cover to a specific position.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.set_cover_position, **kwargs))
def stop_cover(self, **kwargs): def stop_cover(self, **kwargs):
"""Stop the cover.""" """Stop the cover."""
pass pass
def async_stop_cover(self, **kwargs):
"""Stop the cover.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.stop_cover, **kwargs))
def open_cover_tilt(self, **kwargs): def open_cover_tilt(self, **kwargs):
"""Open the cover tilt.""" """Open the cover tilt."""
pass pass
def async_open_cover_tilt(self, **kwargs):
"""Open the cover tilt.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.open_cover_tilt, **kwargs))
def close_cover_tilt(self, **kwargs): def close_cover_tilt(self, **kwargs):
"""Close the cover tilt.""" """Close the cover tilt."""
pass pass
def async_close_cover_tilt(self, **kwargs):
"""Close the cover tilt.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.close_cover_tilt, **kwargs))
def set_cover_tilt_position(self, **kwargs): def set_cover_tilt_position(self, **kwargs):
"""Move the cover tilt to a specific position.""" """Move the cover tilt to a specific position."""
pass pass
def async_set_cover_tilt_position(self, **kwargs):
"""Move the cover tilt to a specific position.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.set_cover_tilt_position, **kwargs))
def stop_cover_tilt(self, **kwargs): def stop_cover_tilt(self, **kwargs):
"""Stop the cover.""" """Stop the cover."""
pass pass
def async_stop_cover_tilt(self, **kwargs):
"""Stop the cover.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, ft.partial(self.stop_cover_tilt, **kwargs))

View file

@ -149,7 +149,7 @@ class DemoCover(CoverDevice):
if self._position in (100, 0, self._set_position): if self._position in (100, 0, self._set_position):
self.stop_cover() self.stop_cover()
self.update_ha_state() self.schedule_update_ha_state()
def _listen_cover_tilt(self): def _listen_cover_tilt(self):
"""Listen for changes in cover tilt.""" """Listen for changes in cover tilt."""
@ -167,4 +167,4 @@ class DemoCover(CoverDevice):
if self._tilt_position in (100, 0, self._set_tilt_position): if self._tilt_position in (100, 0, self._set_tilt_position):
self.stop_cover_tilt() self.stop_cover_tilt()
self.update_ha_state() self.schedule_update_ha_state()

View file

@ -199,8 +199,7 @@ class GaradgetCover(CoverDevice):
def _check_state(self, now): def _check_state(self, now):
"""Check the state of the service during an operation.""" """Check the state of the service during an operation."""
self.update() self.schedule_update_ha_state(True)
self.update_ha_state()
def close_cover(self): def close_cover(self):
"""Close the cover.""" """Close the cover."""

View file

@ -151,7 +151,7 @@ class MqttCover(CoverDevice):
if self._optimistic: if self._optimistic:
# Optimistically assume that cover has changed state. # Optimistically assume that cover has changed state.
self._state = False self._state = False
self.update_ha_state() self.schedule_update_ha_state()
def close_cover(self, **kwargs): def close_cover(self, **kwargs):
"""Move the cover down.""" """Move the cover down."""
@ -160,7 +160,7 @@ class MqttCover(CoverDevice):
if self._optimistic: if self._optimistic:
# Optimistically assume that cover has changed state. # Optimistically assume that cover has changed state.
self._state = True self._state = True
self.update_ha_state() self.schedule_update_ha_state()
def stop_cover(self, **kwargs): def stop_cover(self, **kwargs):
"""Stop the device.""" """Stop the device."""

View file

@ -75,7 +75,7 @@ class MySensorsCover(mysensors.MySensorsDeviceEntity, CoverDevice):
self._values[set_req.V_DIMMER] = 100 self._values[set_req.V_DIMMER] = 100
else: else:
self._values[set_req.V_LIGHT] = STATE_ON self._values[set_req.V_LIGHT] = STATE_ON
self.update_ha_state() self.schedule_update_ha_state()
def close_cover(self, **kwargs): def close_cover(self, **kwargs):
"""Move the cover down.""" """Move the cover down."""
@ -88,7 +88,7 @@ class MySensorsCover(mysensors.MySensorsDeviceEntity, CoverDevice):
self._values[set_req.V_DIMMER] = 0 self._values[set_req.V_DIMMER] = 0
else: else:
self._values[set_req.V_LIGHT] = STATE_OFF self._values[set_req.V_LIGHT] = STATE_OFF
self.update_ha_state() self.schedule_update_ha_state()
def set_cover_position(self, **kwargs): def set_cover_position(self, **kwargs):
"""Move the cover to a specific position.""" """Move the cover to a specific position."""
@ -99,7 +99,7 @@ class MySensorsCover(mysensors.MySensorsDeviceEntity, CoverDevice):
if self.gateway.optimistic: if self.gateway.optimistic:
# Optimistically assume that cover has changed state. # Optimistically assume that cover has changed state.
self._values[set_req.V_DIMMER] = position self._values[set_req.V_DIMMER] = position
self.update_ha_state() self.schedule_update_ha_state()
def stop_cover(self, **kwargs): def stop_cover(self, **kwargs):
"""Stop the device.""" """Stop the device."""