Async migrate climate (#5026)

* Async migrate climate

* Change update handling
This commit is contained in:
Pascal Vizeli 2016-12-26 14:09:15 +01:00 committed by Paulus Schoutsen
parent 43e5d28643
commit 22d1bf0acd

View File

@ -4,8 +4,10 @@ Provides functionality to interact with climate devices.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/climate/ https://home-assistant.io/components/climate/
""" """
import asyncio
import logging import logging
import os import os
import functools as ft
from numbers import Number from numbers import Number
import voluptuous as vol import voluptuous as vol
@ -185,17 +187,38 @@ def set_swing_mode(hass, swing_mode, entity_id=None):
hass.services.call(DOMAIN, SERVICE_SET_SWING_MODE, data) hass.services.call(DOMAIN, SERVICE_SET_SWING_MODE, data)
def setup(hass, config): @asyncio.coroutine
def async_setup(hass, config):
"""Setup climate devices.""" """Setup climate devices."""
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
component.setup(config) yield from component.async_setup(config)
descriptions = load_yaml_config_file( descriptions = yield from hass.loop.run_in_executor(
None, load_yaml_config_file,
os.path.join(os.path.dirname(__file__), 'services.yaml')) os.path.join(os.path.dirname(__file__), 'services.yaml'))
def away_mode_set_service(service): @asyncio.coroutine
def _async_update_climate(target_climate):
"""Update climate entity after service stuff."""
update_tasks = []
for climate in target_climate:
if not climate.should_poll:
continue
update_coro = hass.loop.create_task(
climate.async_update_ha_state(True))
if hasattr(climate, 'async_update'):
update_tasks.append(update_coro)
else:
yield from update_coro
if update_tasks:
yield from asyncio.wait(update_tasks, loop=hass.loop)
@asyncio.coroutine
def async_away_mode_set_service(service):
"""Set away mode on target climate devices.""" """Set away mode on target climate devices."""
target_climate = component.extract_from_service(service) target_climate = component.async_extract_from_service(service)
away_mode = service.data.get(ATTR_AWAY_MODE) away_mode = service.data.get(ATTR_AWAY_MODE)
@ -207,21 +230,21 @@ def setup(hass, config):
for climate in target_climate: for climate in target_climate:
if away_mode: if away_mode:
climate.turn_away_mode_on() yield from climate.async_turn_away_mode_on()
else: else:
climate.turn_away_mode_off() yield from climate.async_turn_away_mode_off()
if climate.should_poll: yield from _async_update_climate(target_climate)
climate.update_ha_state(True)
hass.services.register( hass.services.async_register(
DOMAIN, SERVICE_SET_AWAY_MODE, away_mode_set_service, DOMAIN, SERVICE_SET_AWAY_MODE, async_away_mode_set_service,
descriptions.get(SERVICE_SET_AWAY_MODE), descriptions.get(SERVICE_SET_AWAY_MODE),
schema=SET_AWAY_MODE_SCHEMA) schema=SET_AWAY_MODE_SCHEMA)
def aux_heat_set_service(service): @asyncio.coroutine
def async_aux_heat_set_service(service):
"""Set auxillary heater on target climate devices.""" """Set auxillary heater on target climate devices."""
target_climate = component.extract_from_service(service) target_climate = component.async_extract_from_service(service)
aux_heat = service.data.get(ATTR_AUX_HEAT) aux_heat = service.data.get(ATTR_AUX_HEAT)
@ -233,21 +256,21 @@ def setup(hass, config):
for climate in target_climate: for climate in target_climate:
if aux_heat: if aux_heat:
climate.turn_aux_heat_on() yield from climate.async_turn_aux_heat_on()
else: else:
climate.turn_aux_heat_off() yield from climate.async_turn_aux_heat_off()
if climate.should_poll: yield from _async_update_climate(target_climate)
climate.update_ha_state(True)
hass.services.register( hass.services.async_register(
DOMAIN, SERVICE_SET_AUX_HEAT, aux_heat_set_service, DOMAIN, SERVICE_SET_AUX_HEAT, async_aux_heat_set_service,
descriptions.get(SERVICE_SET_AUX_HEAT), descriptions.get(SERVICE_SET_AUX_HEAT),
schema=SET_AUX_HEAT_SCHEMA) schema=SET_AUX_HEAT_SCHEMA)
def temperature_set_service(service): @asyncio.coroutine
def async_temperature_set_service(service):
"""Set temperature on the target climate devices.""" """Set temperature on the target climate devices."""
target_climate = component.extract_from_service(service) target_climate = component.async_extract_from_service(service)
for climate in target_climate: for climate in target_climate:
kwargs = {} kwargs = {}
@ -261,18 +284,19 @@ def setup(hass, config):
else: else:
kwargs[value] = temp kwargs[value] = temp
climate.set_temperature(**kwargs) yield from climate.async_set_temperature(**kwargs)
if climate.should_poll:
climate.update_ha_state(True)
hass.services.register( yield from _async_update_climate(target_climate)
DOMAIN, SERVICE_SET_TEMPERATURE, temperature_set_service,
hass.services.async_register(
DOMAIN, SERVICE_SET_TEMPERATURE, async_temperature_set_service,
descriptions.get(SERVICE_SET_TEMPERATURE), descriptions.get(SERVICE_SET_TEMPERATURE),
schema=SET_TEMPERATURE_SCHEMA) schema=SET_TEMPERATURE_SCHEMA)
def humidity_set_service(service): @asyncio.coroutine
def async_humidity_set_service(service):
"""Set humidity on the target climate devices.""" """Set humidity on the target climate devices."""
target_climate = component.extract_from_service(service) target_climate = component.async_extract_from_service(service)
humidity = service.data.get(ATTR_HUMIDITY) humidity = service.data.get(ATTR_HUMIDITY)
@ -283,19 +307,19 @@ def setup(hass, config):
return return
for climate in target_climate: for climate in target_climate:
climate.set_humidity(humidity) yield from climate.async_set_humidity(humidity)
if climate.should_poll: yield from _async_update_climate(target_climate)
climate.update_ha_state(True)
hass.services.register( hass.services.async_register(
DOMAIN, SERVICE_SET_HUMIDITY, humidity_set_service, DOMAIN, SERVICE_SET_HUMIDITY, async_humidity_set_service,
descriptions.get(SERVICE_SET_HUMIDITY), descriptions.get(SERVICE_SET_HUMIDITY),
schema=SET_HUMIDITY_SCHEMA) schema=SET_HUMIDITY_SCHEMA)
def fan_mode_set_service(service): @asyncio.coroutine
def async_fan_mode_set_service(service):
"""Set fan mode on target climate devices.""" """Set fan mode on target climate devices."""
target_climate = component.extract_from_service(service) target_climate = component.async_extract_from_service(service)
fan = service.data.get(ATTR_FAN_MODE) fan = service.data.get(ATTR_FAN_MODE)
@ -306,19 +330,19 @@ def setup(hass, config):
return return
for climate in target_climate: for climate in target_climate:
climate.set_fan_mode(fan) yield from climate.async_set_fan_mode(fan)
if climate.should_poll: yield from _async_update_climate(target_climate)
climate.update_ha_state(True)
hass.services.register( hass.services.async_register(
DOMAIN, SERVICE_SET_FAN_MODE, fan_mode_set_service, DOMAIN, SERVICE_SET_FAN_MODE, async_fan_mode_set_service,
descriptions.get(SERVICE_SET_FAN_MODE), descriptions.get(SERVICE_SET_FAN_MODE),
schema=SET_FAN_MODE_SCHEMA) schema=SET_FAN_MODE_SCHEMA)
def operation_set_service(service): @asyncio.coroutine
def async_operation_set_service(service):
"""Set operating mode on the target climate devices.""" """Set operating mode on the target climate devices."""
target_climate = component.extract_from_service(service) target_climate = component.async_extract_from_service(service)
operation_mode = service.data.get(ATTR_OPERATION_MODE) operation_mode = service.data.get(ATTR_OPERATION_MODE)
@ -329,19 +353,19 @@ def setup(hass, config):
return return
for climate in target_climate: for climate in target_climate:
climate.set_operation_mode(operation_mode) yield from climate.async_set_operation_mode(operation_mode)
if climate.should_poll: yield from _async_update_climate(target_climate)
climate.update_ha_state(True)
hass.services.register( hass.services.async_register(
DOMAIN, SERVICE_SET_OPERATION_MODE, operation_set_service, DOMAIN, SERVICE_SET_OPERATION_MODE, async_operation_set_service,
descriptions.get(SERVICE_SET_OPERATION_MODE), descriptions.get(SERVICE_SET_OPERATION_MODE),
schema=SET_OPERATION_MODE_SCHEMA) schema=SET_OPERATION_MODE_SCHEMA)
def swing_set_service(service): @asyncio.coroutine
def async_swing_set_service(service):
"""Set swing mode on the target climate devices.""" """Set swing mode on the target climate devices."""
target_climate = component.extract_from_service(service) target_climate = component.async_extract_from_service(service)
swing_mode = service.data.get(ATTR_SWING_MODE) swing_mode = service.data.get(ATTR_SWING_MODE)
@ -352,15 +376,15 @@ def setup(hass, config):
return return
for climate in target_climate: for climate in target_climate:
climate.set_swing_mode(swing_mode) yield from climate.async_set_swing_mode(swing_mode)
if climate.should_poll: yield from _async_update_climate(target_climate)
climate.update_ha_state(True)
hass.services.register( hass.services.async_register(
DOMAIN, SERVICE_SET_SWING_MODE, swing_set_service, DOMAIN, SERVICE_SET_SWING_MODE, async_swing_set_service,
descriptions.get(SERVICE_SET_SWING_MODE), descriptions.get(SERVICE_SET_SWING_MODE),
schema=SET_SWING_MODE_SCHEMA) schema=SET_SWING_MODE_SCHEMA)
return True return True
@ -521,38 +545,110 @@ class ClimateDevice(Entity):
"""Set new target temperature.""" """Set new target temperature."""
raise NotImplementedError() raise NotImplementedError()
def async_set_temperature(self, **kwargs):
"""Set new target temperature.
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_temperature, **kwargs))
def set_humidity(self, humidity): def set_humidity(self, humidity):
"""Set new target humidity.""" """Set new target humidity."""
raise NotImplementedError() raise NotImplementedError()
def async_set_humidity(self, humidity):
"""Set new target humidity.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.set_humidity, humidity)
def set_fan_mode(self, fan): def set_fan_mode(self, fan):
"""Set new target fan mode.""" """Set new target fan mode."""
raise NotImplementedError() raise NotImplementedError()
def async_set_fan_mode(self, fan):
"""Set new target fan mode.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.set_fan_mode, fan)
def set_operation_mode(self, operation_mode): def set_operation_mode(self, operation_mode):
"""Set new target operation mode.""" """Set new target operation mode."""
raise NotImplementedError() raise NotImplementedError()
def async_set_operation_mode(self, operation_mode):
"""Set new target operation mode.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.set_operation_mode, operation_mode)
def set_swing_mode(self, swing_mode): def set_swing_mode(self, swing_mode):
"""Set new target swing operation.""" """Set new target swing operation."""
raise NotImplementedError() raise NotImplementedError()
def async_set_swing_mode(self, swing_mode):
"""Set new target swing operation.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.set_swing_mode, swing_mode)
def turn_away_mode_on(self): def turn_away_mode_on(self):
"""Turn away mode on.""" """Turn away mode on."""
raise NotImplementedError() raise NotImplementedError()
def async_turn_away_mode_on(self):
"""Turn away mode on.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.turn_away_mode_on)
def turn_away_mode_off(self): def turn_away_mode_off(self):
"""Turn away mode off.""" """Turn away mode off."""
raise NotImplementedError() raise NotImplementedError()
def async_turn_away_mode_off(self):
"""Turn away mode off.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.turn_away_mode_off)
def turn_aux_heat_on(self): def turn_aux_heat_on(self):
"""Turn auxillary heater on.""" """Turn auxillary heater on."""
raise NotImplementedError() raise NotImplementedError()
def async_turn_aux_heat_on(self):
"""Turn auxillary heater on.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.turn_aux_heat_on)
def turn_aux_heat_off(self): def turn_aux_heat_off(self):
"""Turn auxillary heater off.""" """Turn auxillary heater off."""
raise NotImplementedError() raise NotImplementedError()
def async_turn_aux_heat_off(self):
"""Turn auxillary heater off.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(
None, self.turn_aux_heat_off)
@property @property
def min_temp(self): def min_temp(self):
"""Return the minimum temperature.""" """Return the minimum temperature."""