1
mirror of https://github.com/home-assistant/core synced 2024-07-27 18:58:57 +02:00

More entity service (#15998)

* Camera use entity service

* Convert climate services

* Convert light

* Convert media player

* Migrate fan
This commit is contained in:
Paulus Schoutsen 2018-08-16 14:28:59 +02:00 committed by GitHub
parent e4d41fe313
commit 1ff1639cef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 252 additions and 442 deletions

View File

@ -189,74 +189,26 @@ async def async_setup(hass, config):
hass.helpers.event.async_track_time_interval(
update_tokens, TOKEN_CHANGE_INTERVAL)
async def async_handle_camera_service(service):
"""Handle calls to the camera services."""
target_cameras = component.async_extract_from_service(service)
update_tasks = []
for camera in target_cameras:
if service.service == SERVICE_ENABLE_MOTION:
await camera.async_enable_motion_detection()
elif service.service == SERVICE_DISABLE_MOTION:
await camera.async_disable_motion_detection()
elif service.service == SERVICE_TURN_OFF and \
camera.supported_features & SUPPORT_ON_OFF:
await camera.async_turn_off()
elif service.service == SERVICE_TURN_ON and \
camera.supported_features & SUPPORT_ON_OFF:
await camera.async_turn_on()
if not camera.should_poll:
continue
update_tasks.append(camera.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
async def async_handle_snapshot_service(service):
"""Handle snapshot services calls."""
target_cameras = component.async_extract_from_service(service)
filename = service.data[ATTR_FILENAME]
filename.hass = hass
for camera in target_cameras:
snapshot_file = filename.async_render(
variables={ATTR_ENTITY_ID: camera})
# check if we allow to access to that file
if not hass.config.is_allowed_path(snapshot_file):
_LOGGER.error(
"Can't write %s, no access to path!", snapshot_file)
continue
image = await camera.async_camera_image()
def _write_image(to_file, image_data):
"""Executor helper to write image."""
with open(to_file, 'wb') as img_file:
img_file.write(image_data)
try:
await hass.async_add_job(
_write_image, snapshot_file, image)
except OSError as err:
_LOGGER.error("Can't write image to file: %s", err)
hass.services.async_register(
DOMAIN, SERVICE_TURN_OFF, async_handle_camera_service,
schema=CAMERA_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_TURN_ON, async_handle_camera_service,
schema=CAMERA_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_ENABLE_MOTION, async_handle_camera_service,
schema=CAMERA_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_DISABLE_MOTION, async_handle_camera_service,
schema=CAMERA_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_SNAPSHOT, async_handle_snapshot_service,
schema=CAMERA_SERVICE_SNAPSHOT)
component.async_register_entity_service(
SERVICE_ENABLE_MOTION, CAMERA_SERVICE_SCHEMA,
'async_enable_motion_detection'
)
component.async_register_entity_service(
SERVICE_DISABLE_MOTION, CAMERA_SERVICE_SCHEMA,
'async_disable_motion_detection'
)
component.async_register_entity_service(
SERVICE_TURN_OFF, CAMERA_SERVICE_SCHEMA,
'async_turn_off'
)
component.async_register_entity_service(
SERVICE_TURN_ON, CAMERA_SERVICE_SCHEMA,
'async_turn_on'
)
component.async_register_entity_service(
SERVICE_SNAPSHOT, CAMERA_SERVICE_SNAPSHOT,
async_handle_snapshot_service
)
return True
@ -553,3 +505,32 @@ def websocket_camera_thumbnail(hass, connection, msg):
msg['id'], 'image_fetch_failed', 'Unable to fetch image'))
hass.async_add_job(send_camera_still())
async def async_handle_snapshot_service(camera, service):
"""Handle snapshot services calls."""
hass = camera.hass
filename = service.data[ATTR_FILENAME]
filename.hass = hass
snapshot_file = filename.async_render(
variables={ATTR_ENTITY_ID: camera})
# check if we allow to access to that file
if not hass.config.is_allowed_path(snapshot_file):
_LOGGER.error(
"Can't write %s, no access to path!", snapshot_file)
return
image = await camera.async_camera_image()
def _write_image(to_file, image_data):
"""Executor helper to write image."""
with open(to_file, 'wb') as img_file:
img_file.write(image_data)
try:
await hass.async_add_executor_job(
_write_image, snapshot_file, image)
except OSError as err:
_LOGGER.error("Can't write image to file: %s", err)

View File

@ -4,7 +4,6 @@ Provides functionality to interact with climate devices.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/climate/
"""
import asyncio
from datetime import timedelta
import logging
import functools as ft
@ -250,209 +249,46 @@ async def async_setup(hass, config):
EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
await component.async_setup(config)
async def async_away_mode_set_service(service):
"""Set away mode on target climate devices."""
target_climate = component.async_extract_from_service(service)
away_mode = service.data.get(ATTR_AWAY_MODE)
update_tasks = []
for climate in target_climate:
if away_mode:
await climate.async_turn_away_mode_on()
else:
await climate.async_turn_away_mode_off()
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_AWAY_MODE, async_away_mode_set_service,
schema=SET_AWAY_MODE_SCHEMA)
async def async_hold_mode_set_service(service):
"""Set hold mode on target climate devices."""
target_climate = component.async_extract_from_service(service)
hold_mode = service.data.get(ATTR_HOLD_MODE)
update_tasks = []
for climate in target_climate:
await climate.async_set_hold_mode(hold_mode)
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_HOLD_MODE, async_hold_mode_set_service,
schema=SET_HOLD_MODE_SCHEMA)
async def async_aux_heat_set_service(service):
"""Set auxiliary heater on target climate devices."""
target_climate = component.async_extract_from_service(service)
aux_heat = service.data.get(ATTR_AUX_HEAT)
update_tasks = []
for climate in target_climate:
if aux_heat:
await climate.async_turn_aux_heat_on()
else:
await climate.async_turn_aux_heat_off()
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_AUX_HEAT, async_aux_heat_set_service,
schema=SET_AUX_HEAT_SCHEMA)
async def async_temperature_set_service(service):
"""Set temperature on the target climate devices."""
target_climate = component.async_extract_from_service(service)
update_tasks = []
for climate in target_climate:
kwargs = {}
for value, temp in service.data.items():
if value in CONVERTIBLE_ATTRIBUTE:
kwargs[value] = convert_temperature(
temp,
hass.config.units.temperature_unit,
climate.temperature_unit
)
else:
kwargs[value] = temp
await climate.async_set_temperature(**kwargs)
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_TEMPERATURE, async_temperature_set_service,
schema=SET_TEMPERATURE_SCHEMA)
async def async_humidity_set_service(service):
"""Set humidity on the target climate devices."""
target_climate = component.async_extract_from_service(service)
humidity = service.data.get(ATTR_HUMIDITY)
update_tasks = []
for climate in target_climate:
await climate.async_set_humidity(humidity)
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_HUMIDITY, async_humidity_set_service,
schema=SET_HUMIDITY_SCHEMA)
async def async_fan_mode_set_service(service):
"""Set fan mode on target climate devices."""
target_climate = component.async_extract_from_service(service)
fan = service.data.get(ATTR_FAN_MODE)
update_tasks = []
for climate in target_climate:
await climate.async_set_fan_mode(fan)
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_FAN_MODE, async_fan_mode_set_service,
schema=SET_FAN_MODE_SCHEMA)
async def async_operation_set_service(service):
"""Set operating mode on the target climate devices."""
target_climate = component.async_extract_from_service(service)
operation_mode = service.data.get(ATTR_OPERATION_MODE)
update_tasks = []
for climate in target_climate:
await climate.async_set_operation_mode(operation_mode)
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_OPERATION_MODE, async_operation_set_service,
schema=SET_OPERATION_MODE_SCHEMA)
async def async_swing_set_service(service):
"""Set swing mode on the target climate devices."""
target_climate = component.async_extract_from_service(service)
swing_mode = service.data.get(ATTR_SWING_MODE)
update_tasks = []
for climate in target_climate:
await climate.async_set_swing_mode(swing_mode)
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_SET_SWING_MODE, async_swing_set_service,
schema=SET_SWING_MODE_SCHEMA)
async def async_on_off_service(service):
"""Handle on/off calls."""
target_climate = component.async_extract_from_service(service)
update_tasks = []
for climate in target_climate:
if service.service == SERVICE_TURN_ON:
await climate.async_turn_on()
elif service.service == SERVICE_TURN_OFF:
await climate.async_turn_off()
if not climate.should_poll:
continue
update_tasks.append(climate.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
hass.services.async_register(
DOMAIN, SERVICE_TURN_OFF, async_on_off_service,
schema=ON_OFF_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_TURN_ON, async_on_off_service,
schema=ON_OFF_SERVICE_SCHEMA)
component.async_register_entity_service(
SERVICE_SET_AWAY_MODE, SET_AWAY_MODE_SCHEMA,
async_service_away_mode
)
component.async_register_entity_service(
SERVICE_SET_HOLD_MODE, SET_HOLD_MODE_SCHEMA,
'async_set_hold_mode'
)
component.async_register_entity_service(
SERVICE_SET_AUX_HEAT, SET_AUX_HEAT_SCHEMA,
async_service_aux_heat
)
component.async_register_entity_service(
SERVICE_SET_TEMPERATURE, SET_TEMPERATURE_SCHEMA,
async_service_temperature_set
)
component.async_register_entity_service(
SERVICE_SET_HUMIDITY, SET_HUMIDITY_SCHEMA,
'async_set_humidity'
)
component.async_register_entity_service(
SERVICE_SET_FAN_MODE, SET_FAN_MODE_SCHEMA,
'async_set_fan_mode'
)
component.async_register_entity_service(
SERVICE_SET_OPERATION_MODE, SET_OPERATION_MODE_SCHEMA,
'async_set_operation_mode'
)
component.async_register_entity_service(
SERVICE_SET_SWING_MODE, SET_SWING_MODE_SCHEMA,
'async_set_swing_mode'
)
component.async_register_entity_service(
SERVICE_TURN_OFF, ON_OFF_SERVICE_SCHEMA,
'async_turn_off'
)
component.async_register_entity_service(
SERVICE_TURN_ON, ON_OFF_SERVICE_SCHEMA,
'async_turn_on'
)
return True
@ -812,3 +648,37 @@ class ClimateDevice(Entity):
def max_humidity(self):
"""Return the maximum humidity."""
return DEFAULT_MAX_HUMIDITY
async def async_service_away_mode(entity, service):
"""Handle away mode service."""
if service.data[ATTR_AWAY_MODE]:
await entity.async_turn_away_mode_on()
else:
await entity.async_turn_away_mode_off()
async def async_service_aux_heat(entity, service):
"""Handle aux heat service."""
if service.data[ATTR_AUX_HEAT]:
await entity.async_turn_aux_heat_on()
else:
await entity.async_turn_aux_heat_off()
async def async_service_temperature_set(entity, service):
"""Handle set temperature service."""
hass = entity.hass
kwargs = {}
for value, temp in service.data.items():
if value in CONVERTIBLE_ATTRIBUTE:
kwargs[value] = convert_temperature(
temp,
hass.config.units.temperature_unit,
entity.temperature_unit
)
else:
kwargs[value] = temp
await entity.async_set_temperature(**kwargs)

View File

@ -89,33 +89,6 @@ FAN_SET_DIRECTION_SCHEMA = vol.Schema({
vol.Optional(ATTR_DIRECTION): cv.string
}) # type: dict
SERVICE_TO_METHOD = {
SERVICE_TURN_ON: {
'method': 'async_turn_on',
'schema': FAN_TURN_ON_SCHEMA,
},
SERVICE_TURN_OFF: {
'method': 'async_turn_off',
'schema': FAN_TURN_OFF_SCHEMA,
},
SERVICE_TOGGLE: {
'method': 'async_toggle',
'schema': FAN_TOGGLE_SCHEMA,
},
SERVICE_SET_SPEED: {
'method': 'async_set_speed',
'schema': FAN_SET_SPEED_SCHEMA,
},
SERVICE_OSCILLATE: {
'method': 'async_oscillate',
'schema': FAN_OSCILLATE_SCHEMA,
},
SERVICE_SET_DIRECTION: {
'method': 'async_set_direction',
'schema': FAN_SET_DIRECTION_SCHEMA,
},
}
@bind_hass
def is_on(hass, entity_id: str = None) -> bool:
@ -204,30 +177,30 @@ def async_setup(hass, config: dict):
yield from component.async_setup(config)
@asyncio.coroutine
def async_handle_fan_service(service):
"""Handle service call for fans."""
method = SERVICE_TO_METHOD.get(service.service)
params = service.data.copy()
# Convert the entity ids to valid fan ids
target_fans = component.async_extract_from_service(service)
params.pop(ATTR_ENTITY_ID, None)
update_tasks = []
for fan in target_fans:
yield from getattr(fan, method['method'])(**params)
if not fan.should_poll:
continue
update_tasks.append(fan.async_update_ha_state(True))
if update_tasks:
yield from asyncio.wait(update_tasks, loop=hass.loop)
for service_name in SERVICE_TO_METHOD:
schema = SERVICE_TO_METHOD[service_name].get('schema')
hass.services.async_register(
DOMAIN, service_name, async_handle_fan_service, schema=schema)
component.async_register_entity_service(
SERVICE_TURN_ON, FAN_TURN_ON_SCHEMA,
'async_turn_on'
)
component.async_register_entity_service(
SERVICE_TURN_OFF, FAN_TURN_OFF_SCHEMA,
'async_turn_off'
)
component.async_register_entity_service(
SERVICE_TOGGLE, FAN_TOGGLE_SCHEMA,
'async_toggle'
)
component.async_register_entity_service(
SERVICE_SET_SPEED, FAN_SET_SPEED_SCHEMA,
'async_set_speed'
)
component.async_register_entity_service(
SERVICE_OSCILLATE, FAN_OSCILLATE_SCHEMA,
'async_oscillate'
)
component.async_register_entity_service(
SERVICE_SET_DIRECTION, FAN_SET_DIRECTION_SCHEMA,
'async_set_direction'
)
return True

View File

@ -332,8 +332,8 @@ async def async_setup(hass, config):
if not profiles_valid:
return False
async def async_handle_light_service(service):
"""Handle a turn light on or off service call."""
async def async_handle_light_on_service(service):
"""Handle a turn light on service call."""
# Get the validated data
params = service.data.copy()
@ -345,17 +345,12 @@ async def async_setup(hass, config):
update_tasks = []
for light in target_lights:
if service.service == SERVICE_TURN_ON:
pars = params
if not pars:
pars = params.copy()
pars[ATTR_PROFILE] = Profiles.get_default(light.entity_id)
preprocess_turn_on_alternatives(pars)
await light.async_turn_on(**pars)
elif service.service == SERVICE_TURN_OFF:
await light.async_turn_off(**params)
else:
await light.async_toggle(**params)
pars = params
if not pars:
pars = params.copy()
pars[ATTR_PROFILE] = Profiles.get_default(light.entity_id)
preprocess_turn_on_alternatives(pars)
await light.async_turn_on(**pars)
if not light.should_poll:
continue
@ -368,16 +363,18 @@ async def async_setup(hass, config):
# Listen for light on and light off service calls.
hass.services.async_register(
DOMAIN, SERVICE_TURN_ON, async_handle_light_service,
DOMAIN, SERVICE_TURN_ON, async_handle_light_on_service,
schema=LIGHT_TURN_ON_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_TURN_OFF, async_handle_light_service,
schema=LIGHT_TURN_OFF_SCHEMA)
component.async_register_entity_service(
SERVICE_TURN_OFF, LIGHT_TURN_OFF_SCHEMA,
'async_turn_off'
)
hass.services.async_register(
DOMAIN, SERVICE_TOGGLE, async_handle_light_service,
schema=LIGHT_TOGGLE_SCHEMA)
component.async_register_entity_service(
SERVICE_TOGGLE, LIGHT_TOGGLE_SCHEMA,
'async_toggle'
)
hass.helpers.intent.async_register(SetIntentHandler())

View File

@ -151,42 +151,6 @@ MEDIA_PLAYER_SET_SHUFFLE_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Required(ATTR_MEDIA_SHUFFLE): cv.boolean,
})
SERVICE_TO_METHOD = {
SERVICE_TURN_ON: {'method': 'async_turn_on'},
SERVICE_TURN_OFF: {'method': 'async_turn_off'},
SERVICE_TOGGLE: {'method': 'async_toggle'},
SERVICE_VOLUME_UP: {'method': 'async_volume_up'},
SERVICE_VOLUME_DOWN: {'method': 'async_volume_down'},
SERVICE_MEDIA_PLAY_PAUSE: {'method': 'async_media_play_pause'},
SERVICE_MEDIA_PLAY: {'method': 'async_media_play'},
SERVICE_MEDIA_PAUSE: {'method': 'async_media_pause'},
SERVICE_MEDIA_STOP: {'method': 'async_media_stop'},
SERVICE_MEDIA_NEXT_TRACK: {'method': 'async_media_next_track'},
SERVICE_MEDIA_PREVIOUS_TRACK: {'method': 'async_media_previous_track'},
SERVICE_CLEAR_PLAYLIST: {'method': 'async_clear_playlist'},
SERVICE_VOLUME_SET: {
'method': 'async_set_volume_level',
'schema': MEDIA_PLAYER_SET_VOLUME_SCHEMA},
SERVICE_VOLUME_MUTE: {
'method': 'async_mute_volume',
'schema': MEDIA_PLAYER_MUTE_VOLUME_SCHEMA},
SERVICE_MEDIA_SEEK: {
'method': 'async_media_seek',
'schema': MEDIA_PLAYER_MEDIA_SEEK_SCHEMA},
SERVICE_SELECT_SOURCE: {
'method': 'async_select_source',
'schema': MEDIA_PLAYER_SELECT_SOURCE_SCHEMA},
SERVICE_SELECT_SOUND_MODE: {
'method': 'async_select_sound_mode',
'schema': MEDIA_PLAYER_SELECT_SOUND_MODE_SCHEMA},
SERVICE_PLAY_MEDIA: {
'method': 'async_play_media',
'schema': MEDIA_PLAYER_PLAY_MEDIA_SCHEMA},
SERVICE_SHUFFLE_SET: {
'method': 'async_set_shuffle',
'schema': MEDIA_PLAYER_SET_SHUFFLE_SCHEMA},
}
ATTR_TO_PROPERTY = [
ATTR_MEDIA_VOLUME_LEVEL,
ATTR_MEDIA_VOLUME_MUTED,
@ -409,50 +373,89 @@ async def async_setup(hass, config):
await component.async_setup(config)
async def async_service_handler(service):
"""Map services to methods on MediaPlayerDevice."""
method = SERVICE_TO_METHOD.get(service.service)
if not method:
return
params = {}
if service.service == SERVICE_VOLUME_SET:
params['volume'] = service.data.get(ATTR_MEDIA_VOLUME_LEVEL)
elif service.service == SERVICE_VOLUME_MUTE:
params['mute'] = service.data.get(ATTR_MEDIA_VOLUME_MUTED)
elif service.service == SERVICE_MEDIA_SEEK:
params['position'] = service.data.get(ATTR_MEDIA_SEEK_POSITION)
elif service.service == SERVICE_SELECT_SOURCE:
params['source'] = service.data.get(ATTR_INPUT_SOURCE)
elif service.service == SERVICE_SELECT_SOUND_MODE:
params['sound_mode'] = service.data.get(ATTR_SOUND_MODE)
elif service.service == SERVICE_PLAY_MEDIA:
params['media_type'] = \
service.data.get(ATTR_MEDIA_CONTENT_TYPE)
params['media_id'] = service.data.get(ATTR_MEDIA_CONTENT_ID)
params[ATTR_MEDIA_ENQUEUE] = \
service.data.get(ATTR_MEDIA_ENQUEUE)
elif service.service == SERVICE_SHUFFLE_SET:
params[ATTR_MEDIA_SHUFFLE] = \
service.data.get(ATTR_MEDIA_SHUFFLE)
target_players = component.async_extract_from_service(service)
update_tasks = []
for player in target_players:
await getattr(player, method['method'])(**params)
if not player.should_poll:
continue
update_tasks.append(player.async_update_ha_state(True))
if update_tasks:
await asyncio.wait(update_tasks, loop=hass.loop)
for service in SERVICE_TO_METHOD:
schema = SERVICE_TO_METHOD[service].get(
'schema', MEDIA_PLAYER_SCHEMA)
hass.services.async_register(
DOMAIN, service, async_service_handler,
schema=schema)
component.async_register_entity_service(
SERVICE_TURN_ON, MEDIA_PLAYER_SCHEMA,
'async_turn_on'
)
component.async_register_entity_service(
SERVICE_TURN_OFF, MEDIA_PLAYER_SCHEMA,
'async_turn_off'
)
component.async_register_entity_service(
SERVICE_TOGGLE, MEDIA_PLAYER_SCHEMA,
'async_toggle'
)
component.async_register_entity_service(
SERVICE_VOLUME_UP, MEDIA_PLAYER_SCHEMA,
'async_volume_up'
)
component.async_register_entity_service(
SERVICE_VOLUME_DOWN, MEDIA_PLAYER_SCHEMA,
'async_volume_down'
)
component.async_register_entity_service(
SERVICE_MEDIA_PLAY_PAUSE, MEDIA_PLAYER_SCHEMA,
'async_media_play_pause'
)
component.async_register_entity_service(
SERVICE_MEDIA_PLAY, MEDIA_PLAYER_SCHEMA,
'async_media_play'
)
component.async_register_entity_service(
SERVICE_MEDIA_PAUSE, MEDIA_PLAYER_SCHEMA,
'async_media_pause'
)
component.async_register_entity_service(
SERVICE_MEDIA_STOP, MEDIA_PLAYER_SCHEMA,
'async_media_stop'
)
component.async_register_entity_service(
SERVICE_MEDIA_NEXT_TRACK, MEDIA_PLAYER_SCHEMA,
'async_media_next_track'
)
component.async_register_entity_service(
SERVICE_MEDIA_PREVIOUS_TRACK, MEDIA_PLAYER_SCHEMA,
'async_media_previous_track'
)
component.async_register_entity_service(
SERVICE_CLEAR_PLAYLIST, MEDIA_PLAYER_SCHEMA,
'async_clear_playlist'
)
component.async_register_entity_service(
SERVICE_VOLUME_SET, MEDIA_PLAYER_SET_VOLUME_SCHEMA,
lambda entity, call: entity.async_set_volume_level(
volume=call.data[ATTR_MEDIA_VOLUME_LEVEL])
)
component.async_register_entity_service(
SERVICE_VOLUME_MUTE, MEDIA_PLAYER_MUTE_VOLUME_SCHEMA,
lambda entity, call: entity.async_mute_volume(
mute=call.data[ATTR_MEDIA_VOLUME_MUTED])
)
component.async_register_entity_service(
SERVICE_MEDIA_SEEK, MEDIA_PLAYER_MEDIA_SEEK_SCHEMA,
lambda entity, call: entity.async_media_seek(
position=call.data[ATTR_MEDIA_SEEK_POSITION])
)
component.async_register_entity_service(
SERVICE_SELECT_SOURCE, MEDIA_PLAYER_SELECT_SOURCE_SCHEMA,
'async_select_source'
)
component.async_register_entity_service(
SERVICE_SELECT_SOUND_MODE, MEDIA_PLAYER_SELECT_SOUND_MODE_SCHEMA,
'async_select_sound_mode'
)
component.async_register_entity_service(
SERVICE_PLAY_MEDIA, MEDIA_PLAYER_PLAY_MEDIA_SCHEMA,
lambda entity, call: entity.async_play_media(
media_type=call.data[ATTR_MEDIA_CONTENT_TYPE],
media_id=call.data[ATTR_MEDIA_CONTENT_ID],
enqueue=call.data.get(ATTR_MEDIA_ENQUEUE)
)
)
component.async_register_entity_service(
SERVICE_SHUFFLE_SET, MEDIA_PLAYER_SET_SHUFFLE_SCHEMA,
'async_set_shuffle'
)
return True

View File

@ -1,5 +1,5 @@
"""The tests for local file camera component."""
from unittest.mock import mock_open, patch, PropertyMock
from unittest.mock import mock_open, patch
import pytest
@ -67,19 +67,6 @@ async def test_turn_off_invalid_camera(hass, demo_camera):
assert demo_camera.state == STATE_STREAMING
async def test_turn_off_unsupport_camera(hass, demo_camera):
"""Turn off unsupported camera should quietly fail."""
assert demo_camera.state == STATE_STREAMING
with patch('homeassistant.components.camera.demo.DemoCamera'
'.supported_features', new_callable=PropertyMock) as m:
m.return_value = 0
await camera.async_turn_off(hass, demo_camera.entity_id)
await hass.async_block_till_done()
assert demo_camera.state == STATE_STREAMING
async def test_motion_detection(hass):
"""Test motion detection services."""
# Setup platform

View File

@ -356,11 +356,10 @@ def test_signal_repetitions_cancelling(hass, monkeypatch):
yield from hass.async_block_till_done()
print(protocol.send_command_ack.call_args_list)
assert protocol.send_command_ack.call_args_list[0][0][1] == 'off'
assert protocol.send_command_ack.call_args_list[1][0][1] == 'on'
assert protocol.send_command_ack.call_args_list[2][0][1] == 'on'
assert protocol.send_command_ack.call_args_list[3][0][1] == 'on'
assert protocol.send_command_ack.call_args_list[0][0][1] == 'on'
assert protocol.send_command_ack.call_args_list[1][0][1] == 'off'
assert protocol.send_command_ack.call_args_list[2][0][1] == 'off'
assert protocol.send_command_ack.call_args_list[3][0][1] == 'off'
@asyncio.coroutine