Entity service (#15991)
* Add entity service helper * Use entity service helper * Context
This commit is contained in:
parent
e52ba87af1
commit
b682e48e12
14 changed files with 276 additions and 387 deletions
|
@ -26,20 +26,6 @@ ATTR_CHANGED_BY = 'changed_by'
|
|||
|
||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
|
||||
SERVICE_TO_METHOD = {
|
||||
SERVICE_ALARM_DISARM: 'alarm_disarm',
|
||||
SERVICE_ALARM_ARM_HOME: 'alarm_arm_home',
|
||||
SERVICE_ALARM_ARM_AWAY: 'alarm_arm_away',
|
||||
SERVICE_ALARM_ARM_NIGHT: 'alarm_arm_night',
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS: 'alarm_arm_custom_bypass',
|
||||
SERVICE_ALARM_TRIGGER: 'alarm_trigger'
|
||||
}
|
||||
|
||||
ATTR_TO_PROPERTY = [
|
||||
ATTR_CODE,
|
||||
ATTR_CODE_FORMAT
|
||||
]
|
||||
|
||||
ALARM_SERVICE_SCHEMA = vol.Schema({
|
||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
||||
vol.Optional(ATTR_CODE): cv.string,
|
||||
|
@ -126,30 +112,30 @@ def async_setup(hass, config):
|
|||
|
||||
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])
|
||||
|
||||
update_tasks = []
|
||||
for alarm in target_alarms:
|
||||
yield from getattr(alarm, method)(code)
|
||||
|
||||
if not alarm.should_poll:
|
||||
continue
|
||||
update_tasks.append(alarm.async_update_ha_state(True))
|
||||
|
||||
if update_tasks:
|
||||
yield from asyncio.wait(update_tasks, loop=hass.loop)
|
||||
|
||||
for service in SERVICE_TO_METHOD:
|
||||
hass.services.async_register(
|
||||
DOMAIN, service, async_alarm_service_handler,
|
||||
schema=ALARM_SERVICE_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_DISARM, ALARM_SERVICE_SCHEMA,
|
||||
'async_alarm_disarm'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_ARM_HOME, ALARM_SERVICE_SCHEMA,
|
||||
'async_alarm_arm_home'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_ARM_AWAY, ALARM_SERVICE_SCHEMA,
|
||||
'async_alarm_arm_away'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_ARM_NIGHT, ALARM_SERVICE_SCHEMA,
|
||||
'async_alarm_arm_night'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS, ALARM_SERVICE_SCHEMA,
|
||||
'async_alarm_arm_custom_bypass'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_TRIGGER, ALARM_SERVICE_SCHEMA,
|
||||
'async_alarm_trigger'
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ Component to count within automations.
|
|||
For more details about this component, please refer to the documentation
|
||||
at https://home-assistant.io/components/counter/
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
@ -114,27 +113,15 @@ async def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
async def async_handler_service(service):
|
||||
"""Handle a call to the counter services."""
|
||||
target_counters = component.async_extract_from_service(service)
|
||||
|
||||
if service.service == SERVICE_INCREMENT:
|
||||
attr = 'async_increment'
|
||||
elif service.service == SERVICE_DECREMENT:
|
||||
attr = 'async_decrement'
|
||||
elif service.service == SERVICE_RESET:
|
||||
attr = 'async_reset'
|
||||
|
||||
tasks = [getattr(counter, attr)() for counter in target_counters]
|
||||
if tasks:
|
||||
await asyncio.wait(tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_INCREMENT, async_handler_service)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_DECREMENT, async_handler_service)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_RESET, async_handler_service)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_INCREMENT, SERVICE_SCHEMA,
|
||||
'async_increment')
|
||||
component.async_register_entity_service(
|
||||
SERVICE_DECREMENT, SERVICE_SCHEMA,
|
||||
'async_decrement')
|
||||
component.async_register_entity_service(
|
||||
SERVICE_RESET, SERVICE_SCHEMA,
|
||||
'async_reset')
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -4,7 +4,6 @@ Support for Cover devices.
|
|||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/cover/
|
||||
"""
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import functools as ft
|
||||
import logging
|
||||
|
@ -73,21 +72,6 @@ COVER_SET_COVER_TILT_POSITION_SCHEMA = COVER_SERVICE_SCHEMA.extend({
|
|||
vol.All(vol.Coerce(int), vol.Range(min=0, max=100)),
|
||||
})
|
||||
|
||||
SERVICE_TO_METHOD = {
|
||||
SERVICE_OPEN_COVER: {'method': 'async_open_cover'},
|
||||
SERVICE_CLOSE_COVER: {'method': 'async_close_cover'},
|
||||
SERVICE_SET_COVER_POSITION: {
|
||||
'method': 'async_set_cover_position',
|
||||
'schema': COVER_SET_COVER_POSITION_SCHEMA},
|
||||
SERVICE_STOP_COVER: {'method': 'async_stop_cover'},
|
||||
SERVICE_OPEN_COVER_TILT: {'method': 'async_open_cover_tilt'},
|
||||
SERVICE_CLOSE_COVER_TILT: {'method': 'async_close_cover_tilt'},
|
||||
SERVICE_STOP_COVER_TILT: {'method': 'async_stop_cover_tilt'},
|
||||
SERVICE_SET_COVER_TILT_POSITION: {
|
||||
'method': 'async_set_cover_tilt_position',
|
||||
'schema': COVER_SET_COVER_TILT_POSITION_SCHEMA},
|
||||
}
|
||||
|
||||
|
||||
@bind_hass
|
||||
def is_closed(hass, entity_id=None):
|
||||
|
@ -161,30 +145,46 @@ async def async_setup(hass, config):
|
|||
|
||||
await component.async_setup(config)
|
||||
|
||||
async def async_handle_cover_service(service):
|
||||
"""Handle calls to the cover services."""
|
||||
covers = component.async_extract_from_service(service)
|
||||
method = SERVICE_TO_METHOD.get(service.service)
|
||||
params = service.data.copy()
|
||||
params.pop(ATTR_ENTITY_ID, None)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_OPEN_COVER, COVER_SERVICE_SCHEMA,
|
||||
'async_open_cover'
|
||||
)
|
||||
|
||||
# call method
|
||||
update_tasks = []
|
||||
for cover in covers:
|
||||
await getattr(cover, method['method'])(**params)
|
||||
if not cover.should_poll:
|
||||
continue
|
||||
update_tasks.append(cover.async_update_ha_state(True))
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CLOSE_COVER, COVER_SERVICE_SCHEMA,
|
||||
'async_close_cover'
|
||||
)
|
||||
|
||||
if update_tasks:
|
||||
await asyncio.wait(update_tasks, loop=hass.loop)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_COVER_POSITION, COVER_SET_COVER_POSITION_SCHEMA,
|
||||
'async_set_cover_position'
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_STOP_COVER, COVER_SERVICE_SCHEMA,
|
||||
'async_stop_cover'
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_OPEN_COVER_TILT, COVER_SERVICE_SCHEMA,
|
||||
'async_open_cover_tilt'
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CLOSE_COVER_TILT, COVER_SERVICE_SCHEMA,
|
||||
'async_close_cover_tilt'
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_STOP_COVER_TILT, COVER_SERVICE_SCHEMA,
|
||||
'async_stop_cover_tilt'
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_COVER_TILT_POSITION, COVER_SET_COVER_TILT_POSITION_SCHEMA,
|
||||
'async_set_cover_tilt_position'
|
||||
)
|
||||
|
||||
for service_name in SERVICE_TO_METHOD:
|
||||
schema = SERVICE_TO_METHOD[service_name].get(
|
||||
'schema', COVER_SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, service_name, async_handle_cover_service,
|
||||
schema=schema)
|
||||
hass.helpers.intent.async_register(intent.ServiceIntentHandler(
|
||||
INTENT_OPEN_COVER, DOMAIN, SERVICE_OPEN_COVER,
|
||||
"Opened {}"))
|
||||
|
|
|
@ -4,7 +4,6 @@ Component to keep track of user controlled booleans for within automation.
|
|||
For more details about this component, please refer to the documentation
|
||||
at https://home-assistant.io/components/input_boolean/
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
@ -84,30 +83,20 @@ async def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
async def async_handler_service(service):
|
||||
"""Handle a calls to the input boolean services."""
|
||||
target_inputs = component.async_extract_from_service(service)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, SERVICE_SCHEMA,
|
||||
'async_turn_on'
|
||||
)
|
||||
|
||||
if service.service == SERVICE_TURN_ON:
|
||||
attr = 'async_turn_on'
|
||||
elif service.service == SERVICE_TURN_OFF:
|
||||
attr = 'async_turn_off'
|
||||
else:
|
||||
attr = 'async_toggle'
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, SERVICE_SCHEMA,
|
||||
'async_turn_off'
|
||||
)
|
||||
|
||||
tasks = [getattr(input_b, attr)() for input_b in target_inputs]
|
||||
if tasks:
|
||||
await asyncio.wait(tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TURN_OFF, async_handler_service,
|
||||
schema=SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TURN_ON, async_handler_service,
|
||||
schema=SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TOGGLE, async_handler_service,
|
||||
schema=SERVICE_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, SERVICE_SCHEMA,
|
||||
'async_toggle'
|
||||
)
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -82,19 +82,6 @@ CONFIG_SCHEMA = vol.Schema({
|
|||
}, required=True, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
SERVICE_TO_METHOD = {
|
||||
SERVICE_SET_VALUE: {
|
||||
'method': 'async_set_value',
|
||||
'schema': SERVICE_SET_VALUE_SCHEMA},
|
||||
SERVICE_INCREMENT: {
|
||||
'method': 'async_increment',
|
||||
'schema': SERVICE_DEFAULT_SCHEMA},
|
||||
SERVICE_DECREMENT: {
|
||||
'method': 'async_decrement',
|
||||
'schema': SERVICE_DEFAULT_SCHEMA},
|
||||
}
|
||||
|
||||
|
||||
@bind_hass
|
||||
def set_value(hass, entity_id, value):
|
||||
"""Set input_number to value."""
|
||||
|
@ -144,28 +131,20 @@ def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_handle_service(service):
|
||||
"""Handle calls to input_number services."""
|
||||
target_inputs = component.async_extract_from_service(service)
|
||||
method = SERVICE_TO_METHOD.get(service.service)
|
||||
params = service.data.copy()
|
||||
params.pop(ATTR_ENTITY_ID, None)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_VALUE, SERVICE_SET_VALUE_SCHEMA,
|
||||
'async_set_value'
|
||||
)
|
||||
|
||||
# call method
|
||||
update_tasks = []
|
||||
for target_input in target_inputs:
|
||||
yield from getattr(target_input, method['method'])(**params)
|
||||
if not target_input.should_poll:
|
||||
continue
|
||||
update_tasks.append(target_input.async_update_ha_state(True))
|
||||
component.async_register_entity_service(
|
||||
SERVICE_INCREMENT, SERVICE_DEFAULT_SCHEMA,
|
||||
'async_increment'
|
||||
)
|
||||
|
||||
if update_tasks:
|
||||
yield from asyncio.wait(update_tasks, loop=hass.loop)
|
||||
|
||||
for service, data in SERVICE_TO_METHOD.items():
|
||||
hass.services.async_register(
|
||||
DOMAIN, service, async_handle_service, schema=data['schema'])
|
||||
component.async_register_entity_service(
|
||||
SERVICE_DECREMENT, SERVICE_DEFAULT_SCHEMA,
|
||||
'async_decrement'
|
||||
)
|
||||
|
||||
yield from component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -129,61 +129,25 @@ def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_select_option_service(call):
|
||||
"""Handle a calls to the input select option service."""
|
||||
target_inputs = component.async_extract_from_service(call)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_OPTION, SERVICE_SELECT_OPTION_SCHEMA,
|
||||
'async_select_option'
|
||||
)
|
||||
|
||||
tasks = [input_select.async_select_option(call.data[ATTR_OPTION])
|
||||
for input_select in target_inputs]
|
||||
if tasks:
|
||||
yield from asyncio.wait(tasks, loop=hass.loop)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_NEXT, SERVICE_SELECT_NEXT_SCHEMA,
|
||||
lambda entity, call: entity.async_offset_index(1)
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SELECT_OPTION, async_select_option_service,
|
||||
schema=SERVICE_SELECT_OPTION_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_PREVIOUS, SERVICE_SELECT_PREVIOUS_SCHEMA,
|
||||
lambda entity, call: entity.async_offset_index(-1)
|
||||
)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_select_next_service(call):
|
||||
"""Handle a calls to the input select next service."""
|
||||
target_inputs = component.async_extract_from_service(call)
|
||||
|
||||
tasks = [input_select.async_offset_index(1)
|
||||
for input_select in target_inputs]
|
||||
if tasks:
|
||||
yield from asyncio.wait(tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SELECT_NEXT, async_select_next_service,
|
||||
schema=SERVICE_SELECT_NEXT_SCHEMA)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_select_previous_service(call):
|
||||
"""Handle a calls to the input select previous service."""
|
||||
target_inputs = component.async_extract_from_service(call)
|
||||
|
||||
tasks = [input_select.async_offset_index(-1)
|
||||
for input_select in target_inputs]
|
||||
if tasks:
|
||||
yield from asyncio.wait(tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SELECT_PREVIOUS, async_select_previous_service,
|
||||
schema=SERVICE_SELECT_PREVIOUS_SCHEMA)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_set_options_service(call):
|
||||
"""Handle a calls to the set options service."""
|
||||
target_inputs = component.async_extract_from_service(call)
|
||||
|
||||
tasks = [input_select.async_set_options(call.data[ATTR_OPTIONS])
|
||||
for input_select in target_inputs]
|
||||
if tasks:
|
||||
yield from asyncio.wait(tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SET_OPTIONS, async_set_options_service,
|
||||
schema=SERVICE_SET_OPTIONS_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_OPTIONS, SERVICE_SET_OPTIONS_SCHEMA,
|
||||
'async_set_options'
|
||||
)
|
||||
|
||||
yield from component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -107,19 +107,10 @@ def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_set_value_service(call):
|
||||
"""Handle a calls to the input box services."""
|
||||
target_inputs = component.async_extract_from_service(call)
|
||||
|
||||
tasks = [input_text.async_set_value(call.data[ATTR_VALUE])
|
||||
for input_text in target_inputs]
|
||||
if tasks:
|
||||
yield from asyncio.wait(tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SET_VALUE, async_set_value_service,
|
||||
schema=SERVICE_SET_VALUE_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_VALUE, SERVICE_SET_VALUE_SCHEMA,
|
||||
'async_set_value'
|
||||
)
|
||||
|
||||
yield from component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -101,38 +101,18 @@ def async_setup(hass, config):
|
|||
|
||||
yield from component.async_setup(config)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_handle_lock_service(service):
|
||||
"""Handle calls to the lock services."""
|
||||
target_locks = component.async_extract_from_service(service)
|
||||
|
||||
code = service.data.get(ATTR_CODE)
|
||||
|
||||
update_tasks = []
|
||||
for entity in target_locks:
|
||||
if service.service == SERVICE_LOCK:
|
||||
yield from entity.async_lock(code=code)
|
||||
elif service.service == SERVICE_OPEN:
|
||||
yield from entity.async_open(code=code)
|
||||
else:
|
||||
yield from entity.async_unlock(code=code)
|
||||
|
||||
if not entity.should_poll:
|
||||
continue
|
||||
update_tasks.append(entity.async_update_ha_state(True))
|
||||
|
||||
if update_tasks:
|
||||
yield from asyncio.wait(update_tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_UNLOCK, async_handle_lock_service,
|
||||
schema=LOCK_SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_LOCK, async_handle_lock_service,
|
||||
schema=LOCK_SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_OPEN, async_handle_lock_service,
|
||||
schema=LOCK_SERVICE_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_UNLOCK, LOCK_SERVICE_SCHEMA,
|
||||
'async_unlock'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_LOCK, LOCK_SERVICE_SCHEMA,
|
||||
'async_lock'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_OPEN, LOCK_SERVICE_SCHEMA,
|
||||
'async_open'
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -134,42 +134,25 @@ def async_setup(hass, config):
|
|||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_REMOTES)
|
||||
yield from component.async_setup(config)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_handle_remote_service(service):
|
||||
"""Handle calls to the remote services."""
|
||||
target_remotes = component.async_extract_from_service(service)
|
||||
kwargs = service.data.copy()
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, REMOTE_SERVICE_ACTIVITY_SCHEMA,
|
||||
'async_turn_off'
|
||||
)
|
||||
|
||||
update_tasks = []
|
||||
for remote in target_remotes:
|
||||
if service.service == SERVICE_TURN_ON:
|
||||
yield from remote.async_turn_on(**kwargs)
|
||||
elif service.service == SERVICE_TOGGLE:
|
||||
yield from remote.async_toggle(**kwargs)
|
||||
elif service.service == SERVICE_SEND_COMMAND:
|
||||
yield from remote.async_send_command(**kwargs)
|
||||
else:
|
||||
yield from remote.async_turn_off(**kwargs)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, REMOTE_SERVICE_ACTIVITY_SCHEMA,
|
||||
'async_turn_on'
|
||||
)
|
||||
|
||||
if not remote.should_poll:
|
||||
continue
|
||||
update_tasks.append(remote.async_update_ha_state(True))
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, REMOTE_SERVICE_ACTIVITY_SCHEMA,
|
||||
'async_toggle'
|
||||
)
|
||||
|
||||
if update_tasks:
|
||||
yield from asyncio.wait(update_tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TURN_OFF, async_handle_remote_service,
|
||||
schema=REMOTE_SERVICE_ACTIVITY_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TURN_ON, async_handle_remote_service,
|
||||
schema=REMOTE_SERVICE_ACTIVITY_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TOGGLE, async_handle_remote_service,
|
||||
schema=REMOTE_SERVICE_ACTIVITY_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SEND_COMMAND, async_handle_remote_service,
|
||||
schema=REMOTE_SERVICE_SEND_COMMAND_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SEND_COMMAND, REMOTE_SERVICE_SEND_COMMAND_SCHEMA,
|
||||
'async_send_command'
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ Component to interface with various switches that can be controlled remotely.
|
|||
For more details about this component, please refer to the documentation
|
||||
at https://home-assistant.io/components/switch/
|
||||
"""
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
|
@ -99,36 +98,20 @@ async def async_setup(hass, config):
|
|||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_SWITCHES)
|
||||
await component.async_setup(config)
|
||||
|
||||
async def async_handle_switch_service(service):
|
||||
"""Handle calls to the switch services."""
|
||||
target_switches = component.async_extract_from_service(service)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, SWITCH_SERVICE_SCHEMA,
|
||||
'async_turn_off'
|
||||
)
|
||||
|
||||
update_tasks = []
|
||||
for switch in target_switches:
|
||||
if service.service == SERVICE_TURN_ON:
|
||||
await switch.async_turn_on()
|
||||
elif service.service == SERVICE_TOGGLE:
|
||||
await switch.async_toggle()
|
||||
else:
|
||||
await switch.async_turn_off()
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, SWITCH_SERVICE_SCHEMA,
|
||||
'async_turn_on'
|
||||
)
|
||||
|
||||
if not switch.should_poll:
|
||||
continue
|
||||
update_tasks.append(
|
||||
switch.async_update_ha_state(True, service.context))
|
||||
|
||||
if update_tasks:
|
||||
await asyncio.wait(update_tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TURN_OFF, async_handle_switch_service,
|
||||
schema=SWITCH_SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TURN_ON, async_handle_switch_service,
|
||||
schema=SWITCH_SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TOGGLE, async_handle_switch_service,
|
||||
schema=SWITCH_SERVICE_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, SWITCH_SERVICE_SCHEMA,
|
||||
'async_toggle'
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ Timer component.
|
|||
For more details about this component, please refer to the documentation
|
||||
at https://home-assistant.io/components/timer/
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
|
@ -141,39 +140,18 @@ async def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
async def async_handler_service(service):
|
||||
"""Handle a call to the timer services."""
|
||||
target_timers = component.async_extract_from_service(service)
|
||||
|
||||
attr = None
|
||||
if service.service == SERVICE_PAUSE:
|
||||
attr = 'async_pause'
|
||||
elif service.service == SERVICE_CANCEL:
|
||||
attr = 'async_cancel'
|
||||
elif service.service == SERVICE_FINISH:
|
||||
attr = 'async_finish'
|
||||
|
||||
tasks = [getattr(timer, attr)() for timer in target_timers if attr]
|
||||
if service.service == SERVICE_START:
|
||||
for timer in target_timers:
|
||||
tasks.append(
|
||||
timer.async_start(service.data.get(ATTR_DURATION))
|
||||
)
|
||||
if tasks:
|
||||
await asyncio.wait(tasks, loop=hass.loop)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_START, async_handler_service,
|
||||
schema=SERVICE_SCHEMA_DURATION)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_PAUSE, async_handler_service,
|
||||
schema=SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_CANCEL, async_handler_service,
|
||||
schema=SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_FINISH, async_handler_service,
|
||||
schema=SERVICE_SCHEMA)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_START, SERVICE_SCHEMA_DURATION,
|
||||
'async_start')
|
||||
component.async_register_entity_service(
|
||||
SERVICE_PAUSE, SERVICE_SCHEMA,
|
||||
'async_pause')
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CANCEL, SERVICE_SCHEMA,
|
||||
'async_cancel')
|
||||
component.async_register_entity_service(
|
||||
SERVICE_FINISH, SERVICE_SCHEMA,
|
||||
'async_finish')
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -62,23 +62,6 @@ VACUUM_SEND_COMMAND_SERVICE_SCHEMA = VACUUM_SERVICE_SCHEMA.extend({
|
|||
vol.Optional(ATTR_PARAMS): vol.Any(dict, cv.ensure_list),
|
||||
})
|
||||
|
||||
SERVICE_TO_METHOD = {
|
||||
SERVICE_TURN_ON: {'method': 'async_turn_on'},
|
||||
SERVICE_TURN_OFF: {'method': 'async_turn_off'},
|
||||
SERVICE_TOGGLE: {'method': 'async_toggle'},
|
||||
SERVICE_START_PAUSE: {'method': 'async_start_pause'},
|
||||
SERVICE_START: {'method': 'async_start'},
|
||||
SERVICE_PAUSE: {'method': 'async_pause'},
|
||||
SERVICE_RETURN_TO_BASE: {'method': 'async_return_to_base'},
|
||||
SERVICE_CLEAN_SPOT: {'method': 'async_clean_spot'},
|
||||
SERVICE_LOCATE: {'method': 'async_locate'},
|
||||
SERVICE_STOP: {'method': 'async_stop'},
|
||||
SERVICE_SET_FAN_SPEED: {'method': 'async_set_fan_speed',
|
||||
'schema': VACUUM_SET_FAN_SPEED_SERVICE_SCHEMA},
|
||||
SERVICE_SEND_COMMAND: {'method': 'async_send_command',
|
||||
'schema': VACUUM_SEND_COMMAND_SERVICE_SCHEMA},
|
||||
}
|
||||
|
||||
STATE_CLEANING = 'cleaning'
|
||||
STATE_DOCKED = 'docked'
|
||||
STATE_IDLE = STATE_IDLE
|
||||
|
@ -207,30 +190,54 @@ def async_setup(hass, config):
|
|||
|
||||
yield from component.async_setup(config)
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_handle_vacuum_service(service):
|
||||
"""Map services to methods on VacuumDevice."""
|
||||
method = SERVICE_TO_METHOD.get(service.service)
|
||||
target_vacuums = component.async_extract_from_service(service)
|
||||
params = service.data.copy()
|
||||
params.pop(ATTR_ENTITY_ID, None)
|
||||
|
||||
update_tasks = []
|
||||
for vacuum in target_vacuums:
|
||||
yield from getattr(vacuum, method['method'])(**params)
|
||||
if not vacuum.should_poll:
|
||||
continue
|
||||
update_tasks.append(vacuum.async_update_ha_state(True))
|
||||
|
||||
if update_tasks:
|
||||
yield from asyncio.wait(update_tasks, loop=hass.loop)
|
||||
|
||||
for service in SERVICE_TO_METHOD:
|
||||
schema = SERVICE_TO_METHOD[service].get(
|
||||
'schema', VACUUM_SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, service, async_handle_vacuum_service,
|
||||
schema=schema)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, VACUUM_SERVICE_SCHEMA,
|
||||
'async_turn_on'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, VACUUM_SERVICE_SCHEMA,
|
||||
'async_turn_off'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, VACUUM_SERVICE_SCHEMA,
|
||||
'async_toggle'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_START_PAUSE, VACUUM_SERVICE_SCHEMA,
|
||||
'async_start_pause'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_START, VACUUM_SERVICE_SCHEMA,
|
||||
'async_start'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_PAUSE, VACUUM_SERVICE_SCHEMA,
|
||||
'async_pause'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_RETURN_TO_BASE, VACUUM_SERVICE_SCHEMA,
|
||||
'async_return_to_base'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CLEAN_SPOT, VACUUM_SERVICE_SCHEMA,
|
||||
'async_clean_spot'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_LOCATE, VACUUM_SERVICE_SCHEMA,
|
||||
'async_locate'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_STOP, VACUUM_SERVICE_SCHEMA,
|
||||
'async_stop'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_FAN_SPEED, VACUUM_SET_FAN_SPEED_SERVICE_SCHEMA,
|
||||
'async_set_fan_speed'
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SEND_COMMAND, VACUUM_SEND_COMMAND_SERVICE_SCHEMA,
|
||||
'async_send_command'
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -142,6 +142,18 @@ class EntityComponent:
|
|||
return [entity for entity in self.entities
|
||||
if entity.available and entity.entity_id in entity_ids]
|
||||
|
||||
@callback
|
||||
def async_register_entity_service(self, name, schema, func):
|
||||
"""Register an entity service."""
|
||||
async def handle_service(call):
|
||||
"""Handle the service."""
|
||||
await self.hass.helpers.service.entity_service_call(
|
||||
self._platforms.values(), func, call
|
||||
)
|
||||
|
||||
self.hass.services.async_register(
|
||||
self.domain, name, handle_service, schema)
|
||||
|
||||
async def _async_setup_platform(self, platform_type, platform_config,
|
||||
discovery_info=None):
|
||||
"""Set up a platform for this component."""
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Service calling related helpers."""
|
||||
import asyncio
|
||||
import logging
|
||||
from os import path
|
||||
|
||||
|
@ -178,3 +179,52 @@ async def async_get_all_descriptions(hass):
|
|||
descriptions[domain][service] = description
|
||||
|
||||
return descriptions
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def entity_service_call(hass, platforms, func, call):
|
||||
"""Handle an entity service call.
|
||||
|
||||
Calls all platforms simultaneously.
|
||||
"""
|
||||
tasks = []
|
||||
all_entities = ATTR_ENTITY_ID not in call.data
|
||||
if not all_entities:
|
||||
entity_ids = set(
|
||||
extract_entity_ids(hass, call, True))
|
||||
|
||||
if isinstance(func, str):
|
||||
data = {key: val for key, val in call.data.items()
|
||||
if key != ATTR_ENTITY_ID}
|
||||
else:
|
||||
data = call
|
||||
|
||||
tasks = [
|
||||
_handle_service_platform_call(func, data, [
|
||||
entity for entity in platform.entities.values()
|
||||
if all_entities or entity.entity_id in entity_ids
|
||||
], call.context) for platform in platforms
|
||||
]
|
||||
|
||||
if tasks:
|
||||
await asyncio.wait(tasks)
|
||||
|
||||
|
||||
async def _handle_service_platform_call(func, data, entities, context):
|
||||
"""Handle a function call."""
|
||||
tasks = []
|
||||
|
||||
for entity in entities:
|
||||
if not entity.available:
|
||||
continue
|
||||
|
||||
if isinstance(func, str):
|
||||
await getattr(entity, func)(**data)
|
||||
else:
|
||||
await func(entity, data)
|
||||
|
||||
if entity.should_poll:
|
||||
tasks.append(entity.async_update_ha_state(True, context))
|
||||
|
||||
if tasks:
|
||||
await asyncio.wait(tasks)
|
||||
|
|
Loading…
Add table
Reference in a new issue