From 0fc2f0da0ae30ab204acd5a181f4336104edf60d Mon Sep 17 00:00:00 2001 From: Markus Nigbur Date: Thu, 1 Nov 2018 09:09:03 +0100 Subject: [PATCH] Updated example component (#6772) --- .../python_component_automation.markdown | 163 ++++++++++-------- 1 file changed, 87 insertions(+), 76 deletions(-) diff --git a/source/_cookbook/python_component_automation.markdown b/source/_cookbook/python_component_automation.markdown index b098278555c..f04b37ed002 100644 --- a/source/_cookbook/python_component_automation.markdown +++ b/source/_cookbook/python_component_automation.markdown @@ -26,28 +26,33 @@ example: target: TARGET_ENTITY ``` -Configuration variables: - -- **target** (*Required*): TARGET_ENTITY should be one of your devices that can be turned on and off, e.g., a light or a switch. Example value could be light.Ceiling or switch.AC (if you have these devices with those names). +{% configuration %} +target: + description: TARGET_ENTITY should be one of your devices that can be turned on and off, e.g., a light or a switch. Example value could be light.Ceiling or switch.AC (if you have these devices with those names). + required: true + type: string +{% endconfiguration %} Create the file `/custom_components/example.py` and copy paste the content below: - ```python """ Example of a custom component. """ -import time import logging +import time + +import voluptuous as vol -from homeassistant.const import STATE_HOME, STATE_NOT_HOME, STATE_ON, STATE_OFF -from homeassistant.helpers import validate_config -from homeassistant.helpers.event_decorators import \ - track_state_change, track_time_change -from homeassistant.helpers.service import service import homeassistant.components as core -from homeassistant.components import device_tracker -from homeassistant.components import light +import homeassistant.helpers.config_validation as cv +from homeassistant.components import device_tracker, light +from homeassistant.const import (ATTR_ENTITY_ID, SERVICE_TURN_OFF, + SERVICE_TURN_ON, STATE_HOME, STATE_NOT_HOME, + STATE_OFF, STATE_ON) +from homeassistant.core import split_entity_id +from homeassistant.helpers.event import (async_track_state_change, + async_track_time_change) # The domain of your component. Should be equal to the name of your component. DOMAIN = "example" @@ -69,17 +74,20 @@ SERVICE_FLASH = 'flash' # Shortcut for the logger _LOGGER = logging.getLogger(__name__) +# Validate that all required config options are given. +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_TARGET): cv.entity_id + }) +}, extra=vol.ALLOW_EXTRA) -def setup(hass, config): +async def async_setup(hass, config): """Setup example component.""" - global TARGET_ID - - # Validate that all required config options are given. - if not validate_config(config, {DOMAIN: [CONF_TARGET]}, _LOGGER): - return False - TARGET_ID = config[DOMAIN][CONF_TARGET] + domain = split_entity_id(TARGET_ID)[0] + data = {ATTR_ENTITY_ID: TARGET_ID} + # Validate that the target entity id exists. if hass.states.get(TARGET_ID) is None: _LOGGER.error("Target entity id %s does not exist", @@ -90,70 +98,73 @@ def setup(hass, config): TARGET_ID = None return False - # Tell the bootstrapper that we initialized successfully. - return True + async def async_switch_on(entity_id, old_state, new_state): + """Callback to turn on our target entity""" + # If the target id is not set, return + if not TARGET_ID: + return + if not core.is_on(hass, TARGET_ID): + await hass.services.async_call(domain, SERVICE_TURN_ON, data) -@track_state_change(device_tracker.ENTITY_ID_ALL_DEVICES) -def track_devices(hass, entity_id, old_state, new_state): - """Called when the group.all devices change state.""" - # If the target id is not set, return - if not TARGET_ID: - return + async def async_switch_off(entity_id, old_state, new_state): + """Callback to turn off our target entity""" + # If the target id is not set, return + if not TARGET_ID: + return - # If anyone comes home and the entity is not on, turn it on. - if new_state.state == STATE_HOME and not core.is_on(hass, TARGET_ID): + if core.is_on(hass, TARGET_ID): + await hass.services.async_call(domain, SERVICE_TURN_OFF, data) - core.turn_on(hass, TARGET_ID) + async def async_wake_up(service): + """Turn light on in the morning. + + Turn the light on when called, but only if there are people home + and it is not already on. + """ + if not TARGET_ID: + return + + if device_tracker.is_on(hass) and not core.is_on(hass, TARGET_ID): + _LOGGER.info('People home at 7AM, turning target on') + await hass.services.async_call(domain, SERVICE_TURN_ON, data) + + async def async_flash_service(service): + """Service callback that will toggle the target. + + Set the light to off for 10 seconds if on and vice versa. + """ + if not TARGET_ID: + return + + if core.is_on(hass, TARGET_ID): + # We need this call to run blocking, as we want to wait 10s after it finished + await hass.services.async_call(domain, SERVICE_TURN_OFF, data, blocking=True) + time.sleep(10) + await hass.services.async_call(domain, SERVICE_TURN_ON, data) + else: + await hass.services.async_call(domain, SERVICE_TURN_ON, data, blocking=True) + time.sleep(10) + await hass.services.async_call(domain, SERVICE_TURN_OFF, data) + + # register the example.flash service + hass.services.async_register(DOMAIN, SERVICE_FLASH, async_flash_service) + + # If all lights turn off, turn off. + async_track_state_change( + hass, light.ENTITY_ID_ALL_LIGHTS, async_switch_off, STATE_ON, STATE_OFF) # If all people leave the house and the entity is on, turn it off. - elif new_state.state == STATE_NOT_HOME and core.is_on(hass, TARGET_ID): + async_track_state_change( + hass, device_tracker.ENTITY_ID_ALL_DEVICES, async_switch_off, STATE_HOME, STATE_NOT_HOME) - core.turn_off(hass, TARGET_ID) + # If anyone comes home and the entity is not on, turn it on. + async_track_state_change( + hass, device_tracker.ENTITY_ID_ALL_DEVICES, async_switch_on, STATE_NOT_HOME, STATE_HOME) + # Call wakeup callback at 7 AM + async_track_time_change(hass, async_wake_up, hour=7, minute=00, second=00) -@track_time_change(hour=7, minute=0, second=0) -def wake_up(hass, now): - """Turn light on in the morning. - - Turn the light on at 7 AM if there are people home and it is not already - on. - """ - if not TARGET_ID: - return - - if device_tracker.is_on(hass) and not core.is_on(hass, TARGET_ID): - _LOGGER.info('People home at 7AM, turning it on') - core.turn_on(hass, TARGET_ID) - - -@track_state_change(light.ENTITY_ID_ALL_LIGHTS, STATE_ON, STATE_OFF) -def all_lights_off(hass, entity_id, old_state, new_state): - """If all lights turn off, turn off.""" - if not TARGET_ID: - return - - if core.is_on(hass, TARGET_ID): - _LOGGER.info('All lights have been turned off, turning it off') - core.turn_off(hass, TARGET_ID) - - -@service(DOMAIN, SERVICE_FLASH) -def flash_service(hass, call): - """Service that will toggle the target. - - Set the light to off for 10 seconds if on and vice versa. - """ - if not TARGET_ID: - return - - if core.is_on(hass, TARGET_ID): - core.turn_off(hass, TARGET_ID) - time.sleep(10) - core.turn_on(hass, TARGET_ID) - - else: - core.turn_on(hass, TARGET_ID) - time.sleep(10) - core.turn_off(hass, TARGET_ID) + # Tell the bootstrapper that we initialized successfully. + return True ```