Async input_*/zone migration (#4095)

* Async input_*

* Async zone component

* rename service callback
This commit is contained in:
Pascal Vizeli 2016-10-29 21:19:27 +02:00 committed by Paulus Schoutsen
parent d4b3f56d53
commit 08a65a3b31
5 changed files with 68 additions and 48 deletions

View file

@ -4,10 +4,12 @@ Component to keep track of user controlled booleans for within automation.
For more details about this component, please refer to the documentation For more details about this component, please refer to the documentation
at https://home-assistant.io/components/input_boolean/ at https://home-assistant.io/components/input_boolean/
""" """
import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, CONF_ICON, CONF_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, ATTR_ENTITY_ID, CONF_ICON, CONF_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON,
SERVICE_TOGGLE, STATE_ON) SERVICE_TOGGLE, STATE_ON)
@ -55,7 +57,8 @@ def toggle(hass, entity_id):
hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id}) hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id})
def setup(hass, config): @asyncio.coroutine
def async_setup(hass, config):
"""Set up input boolean.""" """Set up input boolean."""
component = EntityComponent(_LOGGER, DOMAIN, hass) component = EntityComponent(_LOGGER, DOMAIN, hass)
@ -74,9 +77,10 @@ def setup(hass, config):
if not entities: if not entities:
return False return False
def handler_service(service): @callback
def async_handler_service(service):
"""Handle a calls to the input boolean services.""" """Handle a calls to the input boolean services."""
target_inputs = component.extract_from_service(service) target_inputs = component.async_extract_from_service(service)
for input_b in target_inputs: for input_b in target_inputs:
if service.service == SERVICE_TURN_ON: if service.service == SERVICE_TURN_ON:
@ -86,15 +90,14 @@ def setup(hass, config):
else: else:
input_b.toggle() input_b.toggle()
hass.services.register(DOMAIN, SERVICE_TURN_OFF, handler_service, hass.services.async_register(
schema=SERVICE_SCHEMA) DOMAIN, SERVICE_TURN_OFF, async_handler_service, schema=SERVICE_SCHEMA)
hass.services.register(DOMAIN, SERVICE_TURN_ON, handler_service, hass.services.async_register(
schema=SERVICE_SCHEMA) DOMAIN, SERVICE_TURN_ON, async_handler_service, schema=SERVICE_SCHEMA)
hass.services.register(DOMAIN, SERVICE_TOGGLE, handler_service, hass.services.async_register(
schema=SERVICE_SCHEMA) DOMAIN, SERVICE_TOGGLE, async_handler_service, schema=SERVICE_SCHEMA)
component.add_entities(entities)
yield from component.async_add_entities(entities)
return True return True
@ -131,9 +134,9 @@ class InputBoolean(ToggleEntity):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the entity on.""" """Turn the entity on."""
self._state = True self._state = True
self.update_ha_state() self.hass.loop.create_task(self.async_update_ha_state())
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
"""Turn the entity off.""" """Turn the entity off."""
self._state = False self._state = False
self.update_ha_state() self.hass.loop.create_task(self.async_update_ha_state())

View file

@ -4,10 +4,12 @@ Component to offer a way to select an option from a list.
For more details about this component, please refer to the documentation For more details about this component, please refer to the documentation
at https://home-assistant.io/components/input_select/ at https://home-assistant.io/components/input_select/
""" """
import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import ATTR_ENTITY_ID, CONF_ICON, CONF_NAME from homeassistant.const import ATTR_ENTITY_ID, CONF_ICON, CONF_NAME
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
@ -86,7 +88,8 @@ def select_previous(hass, entity_id):
}) })
def setup(hass, config): @asyncio.coroutine
def async_setup(hass, config):
"""Setup input select.""" """Setup input select."""
component = EntityComponent(_LOGGER, DOMAIN, hass) component = EntityComponent(_LOGGER, DOMAIN, hass)
@ -102,41 +105,43 @@ def setup(hass, config):
if not entities: if not entities:
return False return False
def select_option_service(call): @callback
def async_select_option_service(call):
"""Handle a calls to the input select option service.""" """Handle a calls to the input select option service."""
target_inputs = component.extract_from_service(call) target_inputs = component.async_extract_from_service(call)
for input_select in target_inputs: for input_select in target_inputs:
input_select.select_option(call.data[ATTR_OPTION]) input_select.select_option(call.data[ATTR_OPTION])
hass.services.register(DOMAIN, SERVICE_SELECT_OPTION, hass.services.async_register(
select_option_service, DOMAIN, SERVICE_SELECT_OPTION, async_select_option_service,
schema=SERVICE_SELECT_OPTION_SCHEMA) schema=SERVICE_SELECT_OPTION_SCHEMA)
def select_next_service(call): @callback
def async_select_next_service(call):
"""Handle a calls to the input select next service.""" """Handle a calls to the input select next service."""
target_inputs = component.extract_from_service(call) target_inputs = component.async_extract_from_service(call)
for input_select in target_inputs: for input_select in target_inputs:
input_select.offset_index(1) input_select.offset_index(1)
hass.services.register(DOMAIN, SERVICE_SELECT_NEXT, hass.services.async_register(
select_next_service, DOMAIN, SERVICE_SELECT_NEXT, async_select_next_service,
schema=SERVICE_SELECT_NEXT_SCHEMA) schema=SERVICE_SELECT_NEXT_SCHEMA)
def select_previous_service(call): @callback
def async_select_previous_service(call):
"""Handle a calls to the input select previous service.""" """Handle a calls to the input select previous service."""
target_inputs = component.extract_from_service(call) target_inputs = component.async_extract_from_service(call)
for input_select in target_inputs: for input_select in target_inputs:
input_select.offset_index(-1) input_select.offset_index(-1)
hass.services.register(DOMAIN, SERVICE_SELECT_PREVIOUS, hass.services.async_register(
select_previous_service, DOMAIN, SERVICE_SELECT_PREVIOUS, async_select_previous_service,
schema=SERVICE_SELECT_PREVIOUS_SCHEMA) schema=SERVICE_SELECT_PREVIOUS_SCHEMA)
component.add_entities(entities)
yield from component.async_add_entities(entities)
return True return True
@ -186,11 +191,11 @@ class InputSelect(Entity):
option, ', '.join(self._options)) option, ', '.join(self._options))
return return
self._current_option = option self._current_option = option
self.update_ha_state() self.hass.loop.create_task(self.async_update_ha_state())
def offset_index(self, offset): def offset_index(self, offset):
"""Offset current index.""" """Offset current index."""
current_index = self._options.index(self._current_option) current_index = self._options.index(self._current_option)
new_index = (current_index + offset) % len(self._options) new_index = (current_index + offset) % len(self._options)
self._current_option = self._options[new_index] self._current_option = self._options[new_index]
self.update_ha_state() self.hass.loop.create_task(self.async_update_ha_state())

View file

@ -4,10 +4,12 @@ Component to offer a way to select a value from a slider.
For more details about this component, please refer to the documentation For more details about this component, please refer to the documentation
at https://home-assistant.io/components/input_slider/ at https://home-assistant.io/components/input_slider/
""" """
import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_UNIT_OF_MEASUREMENT, CONF_ICON, CONF_NAME) ATTR_ENTITY_ID, ATTR_UNIT_OF_MEASUREMENT, CONF_ICON, CONF_NAME)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -71,7 +73,8 @@ def select_value(hass, entity_id, value):
}) })
def setup(hass, config): @asyncio.coroutine
def async_setup(hass, config):
"""Set up input slider.""" """Set up input slider."""
component = EntityComponent(_LOGGER, DOMAIN, hass) component = EntityComponent(_LOGGER, DOMAIN, hass)
@ -92,19 +95,19 @@ def setup(hass, config):
if not entities: if not entities:
return False return False
def select_value_service(call): @callback
def async_select_value_service(call):
"""Handle a calls to the input slider services.""" """Handle a calls to the input slider services."""
target_inputs = component.extract_from_service(call) target_inputs = component.async_extract_from_service(call)
for input_slider in target_inputs: for input_slider in target_inputs:
input_slider.select_value(call.data[ATTR_VALUE]) input_slider.select_value(call.data[ATTR_VALUE])
hass.services.register(DOMAIN, SERVICE_SELECT_VALUE, hass.services.async_register(
select_value_service, DOMAIN, SERVICE_SELECT_VALUE, async_select_value_service,
schema=SERVICE_SELECT_VALUE_SCHEMA) schema=SERVICE_SELECT_VALUE_SCHEMA)
component.add_entities(entities)
yield from component.async_add_entities(entities)
return True return True
@ -166,4 +169,4 @@ class InputSlider(Entity):
num_value, self._minimum, self._maximum) num_value, self._minimum, self._maximum)
return return
self._current_value = num_value self._current_value = num_value
self.update_ha_state() self.hass.loop.create_task(self.async_update_ha_state())

View file

@ -4,6 +4,7 @@ Support for the definition of zones.
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/zone/ https://home-assistant.io/components/zone/
""" """
import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
@ -12,7 +13,7 @@ from homeassistant.const import (
ATTR_HIDDEN, ATTR_LATITUDE, ATTR_LONGITUDE, CONF_NAME, CONF_LATITUDE, ATTR_HIDDEN, ATTR_LATITUDE, ATTR_LONGITUDE, CONF_NAME, CONF_LATITUDE,
CONF_LONGITUDE, CONF_ICON) CONF_LONGITUDE, CONF_ICON)
from homeassistant.helpers import config_per_platform from homeassistant.helpers import config_per_platform
from homeassistant.helpers.entity import Entity, generate_entity_id from homeassistant.helpers.entity import Entity, async_generate_entity_id
from homeassistant.util.location import distance from homeassistant.util.location import distance
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -87,16 +88,19 @@ def in_zone(zone, latitude, longitude, radius=0):
return zone_dist - radius < zone.attributes[ATTR_RADIUS] return zone_dist - radius < zone.attributes[ATTR_RADIUS]
def setup(hass, config): @asyncio.coroutine
def async_setup(hass, config):
"""Setup zone.""" """Setup zone."""
entities = set() entities = set()
tasks = []
for _, entry in config_per_platform(config, DOMAIN): for _, entry in config_per_platform(config, DOMAIN):
name = entry.get(CONF_NAME) name = entry.get(CONF_NAME)
zone = Zone(hass, name, entry[CONF_LATITUDE], entry[CONF_LONGITUDE], zone = Zone(hass, name, entry[CONF_LATITUDE], entry[CONF_LONGITUDE],
entry.get(CONF_RADIUS), entry.get(CONF_ICON), entry.get(CONF_RADIUS), entry.get(CONF_ICON),
entry.get(CONF_PASSIVE)) entry.get(CONF_PASSIVE))
zone.entity_id = generate_entity_id(ENTITY_ID_FORMAT, name, entities) zone.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, name,
zone.update_ha_state() entities)
tasks.append(zone.async_update_ha_state())
entities.add(zone.entity_id) entities.add(zone.entity_id)
if ENTITY_ID_HOME not in entities: if ENTITY_ID_HOME not in entities:
@ -104,8 +108,9 @@ def setup(hass, config):
hass.config.latitude, hass.config.longitude, hass.config.latitude, hass.config.longitude,
DEFAULT_RADIUS, ICON_HOME, False) DEFAULT_RADIUS, ICON_HOME, False)
zone.entity_id = ENTITY_ID_HOME zone.entity_id = ENTITY_ID_HOME
zone.update_ha_state() tasks.append(zone.async_update_ha_state())
yield from asyncio.gather(*tasks, loop=hass.loop)
return True return True

View file

@ -19,6 +19,7 @@ def config_per_platform(config: ConfigType,
"""Generator to break a component config into different platforms. """Generator to break a component config into different platforms.
For example, will find 'switch', 'switch 2', 'switch 3', .. etc For example, will find 'switch', 'switch 2', 'switch 3', .. etc
Async friendly.
""" """
for config_key in extract_domain_configs(config, domain): for config_key in extract_domain_configs(config, domain):
platform_config = config[config_key] platform_config = config[config_key]
@ -38,6 +39,9 @@ def config_per_platform(config: ConfigType,
def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]: def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
"""Extract keys from config for given domain name.""" """Extract keys from config for given domain name.
Async friendly.
"""
pattern = re.compile(r'^{}(| .+)$'.format(domain)) pattern = re.compile(r'^{}(| .+)$'.format(domain))
return [key for key in config.keys() if pattern.match(key)] return [key for key in config.keys() if pattern.match(key)]