1
mirror of https://github.com/home-assistant/core synced 2024-10-04 07:58:43 +02:00

Merge pull request #1485 from MartinHjelmare/refactor-scene-reproduce_state

Refactor reproduce_state for scene component
This commit is contained in:
Paulus Schoutsen 2016-03-09 15:29:10 -08:00
commit 47c4f66886
10 changed files with 247 additions and 97 deletions

View File

@ -1,5 +1,5 @@
"""
Component to interface with a alarm control panel.
Component to interface with an alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel/
@ -9,7 +9,7 @@ import os
from homeassistant.components import verisure
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER,
ATTR_CODE, ATTR_CODE_FORMAT, ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER,
SERVICE_ALARM_DISARM, SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_ARM_AWAY)
from homeassistant.config import load_yaml_config_file
from homeassistant.helpers.entity import Entity
@ -32,9 +32,6 @@ SERVICE_TO_METHOD = {
SERVICE_ALARM_TRIGGER: 'alarm_trigger'
}
ATTR_CODE = 'code'
ATTR_CODE_FORMAT = 'code_format'
ATTR_TO_PROPERTY = [
ATTR_CODE,
ATTR_CODE_FORMAT
@ -149,5 +146,5 @@ class AlarmControlPanel(Entity):
"""Return the state attributes."""
state_attr = {
ATTR_CODE_FORMAT: self.code_format,
}
}
return state_attr

View File

@ -13,8 +13,8 @@ from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
STATE_LOCKED, STATE_UNLOCKED, STATE_UNKNOWN, SERVICE_LOCK, SERVICE_UNLOCK,
ATTR_ENTITY_ID)
ATTR_CODE, ATTR_CODE_FORMAT, ATTR_ENTITY_ID, STATE_LOCKED, STATE_UNLOCKED,
STATE_UNKNOWN, SERVICE_LOCK, SERVICE_UNLOCK)
from homeassistant.components import (group, verisure, wink)
DOMAIN = 'lock'
@ -25,10 +25,6 @@ ENTITY_ID_ALL_LOCKS = group.ENTITY_ID_FORMAT.format('all_locks')
ENTITY_ID_FORMAT = DOMAIN + '.{}'
ATTR_LOCKED = "locked"
ATTR_CODE = 'code'
ATTR_CODE_FORMAT = 'code_format'
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
# Maps discovered services to their platforms

View File

@ -8,10 +8,10 @@ import logging
from homeassistant.components.verisure import HUB as hub
from homeassistant.components.lock import LockDevice
from homeassistant.const import STATE_LOCKED, STATE_UNKNOWN, STATE_UNLOCKED
from homeassistant.const import (
ATTR_CODE, STATE_LOCKED, STATE_UNKNOWN, STATE_UNLOCKED)
_LOGGER = logging.getLogger(__name__)
ATTR_CODE = 'code'
def setup_platform(hass, config, add_devices, discovery_info=None):
@ -22,7 +22,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
locks.extend([
VerisureDoorlock(device_id)
for device_id in hub.lock_status.keys()
])
])
add_devices(locks)

View File

@ -108,9 +108,10 @@ ATTR_TO_PROPERTY = [
def is_on(hass, entity_id=None):
"""Return true if specified media player entity_id is on.
"""
Return true if specified media player entity_id is on.
Will check all media player if no entity_id specified.
Check all media player if no entity_id specified.
"""
entity_ids = [entity_id] if entity_id else hass.states.entity_ids(DOMAIN)
return any(not hass.states.is_state(entity_id, STATE_OFF)
@ -118,19 +119,19 @@ def is_on(hass, entity_id=None):
def turn_on(hass, entity_id=None):
"""Will turn on specified media player or all."""
"""Turn on specified media player or all."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_TURN_ON, data)
def turn_off(hass, entity_id=None):
"""Will turn off specified media player or all."""
"""Turn off specified media player or all."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_TURN_OFF, data)
def toggle(hass, entity_id=None):
"""Will toggle specified media player or all."""
"""Toggle specified media player or all."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_TOGGLE, data)
@ -148,7 +149,7 @@ def volume_down(hass, entity_id=None):
def mute_volume(hass, mute, entity_id=None):
"""Send the media player the command for volume down."""
"""Send the media player the command for muting the volume."""
data = {ATTR_MEDIA_VOLUME_MUTED: mute}
if entity_id:
@ -158,7 +159,7 @@ def mute_volume(hass, mute, entity_id=None):
def set_volume_level(hass, volume, entity_id=None):
"""Send the media player the command for volume down."""
"""Send the media player the command for setting the volume."""
data = {ATTR_MEDIA_VOLUME_LEVEL: volume}
if entity_id:
@ -180,7 +181,7 @@ def media_play(hass, entity_id=None):
def media_pause(hass, entity_id=None):
"""Send the media player the command for play/pause."""
"""Send the media player the command for pause."""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.services.call(DOMAIN, SERVICE_MEDIA_PAUSE, data)
@ -206,7 +207,8 @@ def media_seek(hass, position, entity_id=None):
def play_media(hass, media_type, media_id, entity_id=None):
"""Send the media player the command for playing media."""
data = {"media_type": media_type, "media_id": media_id}
data = {ATTR_MEDIA_CONTENT_TYPE: media_type,
ATTR_MEDIA_CONTENT_ID: media_id}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
@ -297,8 +299,8 @@ def setup(hass, config):
def play_media_service(service):
"""Play specified media_id on the media player."""
media_type = service.data.get('media_type')
media_id = service.data.get('media_id')
media_type = service.data.get(ATTR_MEDIA_CONTENT_TYPE)
media_id = service.data.get(ATTR_MEDIA_CONTENT_ID)
if media_type is None:
return
@ -320,10 +322,12 @@ def setup(hass, config):
class MediaPlayerDevice(Entity):
"""An abstract class for media player devices."""
"""ABC for media player devices."""
# pylint: disable=too-many-public-methods,no-self-use
# Implement these for your media player
@property
def state(self):
"""State of the player."""
@ -366,37 +370,37 @@ class MediaPlayerDevice(Entity):
@property
def media_artist(self):
"""Artist of current playing media (Music track only)."""
"""Artist of current playing media, music track only."""
return None
@property
def media_album_name(self):
"""Album name of current playing media (Music track only)."""
"""Album name of current playing media, music track only."""
return None
@property
def media_album_artist(self):
"""Album artist of current playing media (Music track only)."""
"""Album artist of current playing media, music track only."""
return None
@property
def media_track(self):
"""Track number of current playing media (Music track only)."""
"""Track number of current playing media, music track only."""
return None
@property
def media_series_title(self):
"""The title of the series of current playing media (TV Show only)."""
"""Title of series of current playing media, TV show only."""
return None
@property
def media_season(self):
"""Season of current playing media (TV Show only)."""
"""Season of current playing media, TV show only."""
return None
@property
def media_episode(self):
"""Episode of current playing media (TV Show only)."""
"""Episode of current playing media, TV show only."""
return None
@property
@ -421,7 +425,7 @@ class MediaPlayerDevice(Entity):
@property
def supported_media_commands(self):
"""Flag of media commands that are supported."""
"""Flag media commands that are supported."""
return 0
def turn_on(self):
@ -508,17 +512,17 @@ class MediaPlayerDevice(Entity):
self.turn_off()
def volume_up(self):
"""volume_up media player."""
"""Turn volume up for media player."""
if self.volume_level < 1:
self.set_volume_level(min(1, self.volume_level + .1))
def volume_down(self):
"""volume_down media player."""
"""Turn volume down for media player."""
if self.volume_level > 0:
self.set_volume_level(max(0, self.volume_level - .1))
def media_play_pause(self):
"""media_play_pause media player."""
"""Play or pause the media player."""
if self.state == STATE_PLAYING:
self.media_pause()
else:
@ -526,7 +530,7 @@ class MediaPlayerDevice(Entity):
@property
def entity_picture(self):
"""Return the image of the media playing."""
"""Return image of the media playing."""
return None if self.state == STATE_OFF else self.media_image_url
@property

View File

@ -43,7 +43,6 @@ REQUIREMENTS = []
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the universal media players."""
if not validate_config(config):
@ -200,7 +199,7 @@ class UniversalMediaPlayer(MediaPlayerDevice):
@property
def master_state(self):
"""Get the master state from entity or none."""
"""Return the master state for entity or None."""
if CONF_STATE in self._attrs:
master_state = self._entity_lkp(self._attrs[CONF_STATE][0],
self._attrs[CONF_STATE][1])
@ -324,7 +323,7 @@ class UniversalMediaPlayer(MediaPlayerDevice):
@property
def supported_media_commands(self):
"""Flag of media commands that are supported."""
"""Flag media commands that are supported."""
flags = self._child_attr(ATTR_SUPPORTED_MEDIA_COMMANDS) or 0
if SERVICE_TURN_ON in self._cmds:
@ -345,7 +344,7 @@ class UniversalMediaPlayer(MediaPlayerDevice):
@property
def device_state_attributes(self):
"""Extra attributes a device wants to expose."""
"""Return device specific state attributes."""
active_child = self._child_state
return {ATTR_ACTIVE_CHILD: active_child.entity_id} \
if active_child else {}
@ -391,23 +390,24 @@ class UniversalMediaPlayer(MediaPlayerDevice):
def play_media(self, media_type, media_id):
"""Play a piece of media."""
data = {'media_type': media_type, 'media_id': media_id}
data = {ATTR_MEDIA_CONTENT_TYPE: media_type,
ATTR_MEDIA_CONTENT_ID: media_id}
self._call_service(SERVICE_PLAY_MEDIA, data)
def volume_up(self):
"""Volume up media player."""
"""Turn volume up for media player."""
self._call_service(SERVICE_VOLUME_UP, allow_override=True)
def volume_down(self):
"""Volume down media player."""
"""Turn volume down for media player."""
self._call_service(SERVICE_VOLUME_DOWN, allow_override=True)
def media_play_pause(self):
"""Send play/pause command media player."""
"""Play or pause the media player."""
self._call_service(SERVICE_MEDIA_PLAY_PAUSE)
def update(self):
"""Event to trigger a state update."""
"""Update state in HA."""
for child_name in self._children:
child_state = self.hass.states.get(child_name)
if child_state and child_state.state not in OFF_STATES:

View File

@ -33,7 +33,7 @@ def activate(hass, entity_id=None):
def setup(hass, config):
"""Setup the scenes."""
"""Setup scenes."""
logger = logging.getLogger(__name__)
# You are not allowed to mutate the original config so make a copy
@ -76,9 +76,9 @@ class Scene(Entity):
@property
def state(self):
"""Return the state."""
"""Return the state of the scene."""
return STATE
def activate(self):
"""Activate scene. Tries to get entities into requested state."""
"""Activate scene. Try to get entities into requested state."""
raise NotImplementedError

View File

@ -1,5 +1,5 @@
"""
Allows users to set and activate scenes.
Allow users to set and activate scenes.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/scene/
@ -20,7 +20,6 @@ CONF_ENTITIES = "entities"
SceneConfig = namedtuple('SceneConfig', ['name', 'states'])
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup home assistant scene entries."""
scene_config = config.get("states")
@ -83,5 +82,5 @@ class HomeAssistantScene(Scene):
}
def activate(self):
"""Activate scene. Tries to get entities into requested state."""
"""Activate scene. Try to get entities into requested state."""
reproduce_state(self.hass, self.scene_config.states.values(), True)

View File

@ -102,6 +102,10 @@ ATTR_LOCATION = "location"
ATTR_BATTERY_LEVEL = "battery_level"
# For devices which support a code attribute
ATTR_CODE = 'code'
ATTR_CODE_FORMAT = 'code_format'
# For devices which support an armed state
ATTR_ARMED = "device_armed"

View File

@ -4,24 +4,73 @@ import logging
from collections import defaultdict
import homeassistant.util.dt as dt_util
from homeassistant.components.media_player import SERVICE_PLAY_MEDIA
from homeassistant.components.media_player import (
ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_CONTENT_TYPE, ATTR_MEDIA_SEEK_POSITION,
ATTR_MEDIA_VOLUME_LEVEL, ATTR_MEDIA_VOLUME_MUTED, SERVICE_PLAY_MEDIA)
from homeassistant.components.notify import (
ATTR_MESSAGE, SERVICE_NOTIFY)
from homeassistant.components.sun import (
STATE_ABOVE_HORIZON, STATE_BELOW_HORIZON)
from homeassistant.components.thermostat import (
ATTR_AWAY_MODE, ATTR_FAN, SERVICE_SET_AWAY_MODE, SERVICE_SET_FAN_MODE,
SERVICE_SET_TEMPERATURE)
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_TURN_OFF,
SERVICE_TURN_ON, STATE_CLOSED, STATE_LOCKED, STATE_OFF, STATE_ON,
STATE_OPEN, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_UNLOCKED)
ATTR_ENTITY_ID, ATTR_TEMPERATURE, SERVICE_ALARM_ARM_AWAY,
SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_DISARM, SERVICE_ALARM_TRIGGER,
SERVICE_CLOSE, SERVICE_LOCK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY,
SERVICE_MEDIA_SEEK, SERVICE_MOVE_DOWN, SERVICE_MOVE_UP, SERVICE_OPEN,
SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_VOLUME_MUTE,
SERVICE_VOLUME_SET, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED,
STATE_OFF, STATE_ON, STATE_OPEN, STATE_PAUSED, STATE_PLAYING,
STATE_UNKNOWN, STATE_UNLOCKED)
from homeassistant.core import State
_LOGGER = logging.getLogger(__name__)
GROUP_DOMAIN = 'group'
HASS_DOMAIN = 'homeassistant'
# Update this dict of lists when new services are added to HA.
# Each item is a service with a list of required attributes.
SERVICE_ATTRIBUTES = {
SERVICE_PLAY_MEDIA: [ATTR_MEDIA_CONTENT_TYPE, ATTR_MEDIA_CONTENT_ID],
SERVICE_MEDIA_SEEK: [ATTR_MEDIA_SEEK_POSITION],
SERVICE_VOLUME_MUTE: [ATTR_MEDIA_VOLUME_MUTED],
SERVICE_VOLUME_SET: [ATTR_MEDIA_VOLUME_LEVEL],
SERVICE_NOTIFY: [ATTR_MESSAGE],
SERVICE_SET_AWAY_MODE: [ATTR_AWAY_MODE],
SERVICE_SET_FAN_MODE: [ATTR_FAN],
SERVICE_SET_TEMPERATURE: [ATTR_TEMPERATURE],
}
# Update this dict when new services are added to HA.
# Each item is a service with a corresponding state.
SERVICE_TO_STATE = {
SERVICE_TURN_ON: STATE_ON,
SERVICE_TURN_OFF: STATE_OFF,
SERVICE_MEDIA_PLAY: STATE_PLAYING,
SERVICE_MEDIA_PAUSE: STATE_PAUSED,
SERVICE_ALARM_ARM_AWAY: STATE_ALARM_ARMED_AWAY,
SERVICE_ALARM_ARM_HOME: STATE_ALARM_ARMED_HOME,
SERVICE_ALARM_DISARM: STATE_ALARM_DISARMED,
SERVICE_ALARM_TRIGGER: STATE_ALARM_TRIGGERED,
SERVICE_LOCK: STATE_LOCKED,
SERVICE_UNLOCK: STATE_UNLOCKED,
SERVICE_CLOSE: STATE_CLOSED,
SERVICE_OPEN: STATE_OPEN,
SERVICE_MOVE_UP: STATE_OPEN,
SERVICE_MOVE_DOWN: STATE_CLOSED,
}
# pylint: disable=too-few-public-methods, attribute-defined-outside-init
class TrackStates(object):
"""Record the time when the with-block is entered.
"""
Record the time when the with-block is entered.
Will add all states that have changed since the start time to the return
list when with-block is exited.
Add all states that have changed since the start time to the return list
when with-block is exited.
"""
def __init__(self, hass):
@ -40,7 +89,7 @@ class TrackStates(object):
def get_changed_since(states, utc_point_in_time):
"""List of states that have been changed since utc_point_in_time."""
"""Return list of states that have been changed since utc_point_in_time."""
point_in_time = dt_util.strip_microseconds(utc_point_in_time)
return [state for state in states if state.last_updated >= point_in_time]
@ -54,35 +103,36 @@ def reproduce_state(hass, states, blocking=False):
to_call = defaultdict(list)
for state in states:
current_state = hass.states.get(state.entity_id)
if current_state is None:
if hass.states.get(state.entity_id) is None:
_LOGGER.warning('reproduce_state: Unable to find entity %s',
state.entity_id)
continue
if state.domain == 'media_player' and state.attributes and \
'media_type' in state.attributes and \
'media_id' in state.attributes:
service = SERVICE_PLAY_MEDIA
elif state.domain == 'media_player' and state.state == STATE_PAUSED:
service = SERVICE_MEDIA_PAUSE
elif state.domain == 'media_player' and state.state == STATE_PLAYING:
service = SERVICE_MEDIA_PLAY
elif state.state == STATE_ON:
service = SERVICE_TURN_ON
elif state.state == STATE_OFF:
service = SERVICE_TURN_OFF
if state.domain == GROUP_DOMAIN:
service_domain = HASS_DOMAIN
else:
service_domain = state.domain
domain_services = hass.services.services[service_domain]
service = None
for _service in domain_services.keys():
if (_service in SERVICE_ATTRIBUTES and
all(attr in state.attributes
for attr in SERVICE_ATTRIBUTES[_service]) or
_service in SERVICE_TO_STATE and
SERVICE_TO_STATE[_service] == state.state):
service = _service
if (_service in SERVICE_TO_STATE and
SERVICE_TO_STATE[_service] == state.state):
break
if not service:
_LOGGER.warning("reproduce_state: Unable to reproduce state %s",
state)
continue
if state.domain == 'group':
service_domain = 'homeassistant'
else:
service_domain = state.domain
# We group service calls for entities by service call
# json used to create a hashable version of dict with maybe lists in it
key = (service_domain, service,
@ -96,7 +146,8 @@ def reproduce_state(hass, states, blocking=False):
def state_as_number(state):
"""Try to coerce our state to a number.
"""
Try to coerce our state to a number.
Raises ValueError if this is not possible.
"""

View File

@ -5,13 +5,15 @@ from unittest.mock import patch
import homeassistant.core as ha
import homeassistant.components as core_components
from homeassistant.const import SERVICE_TURN_ON
from homeassistant.const import (SERVICE_TURN_ON, SERVICE_TURN_OFF)
from homeassistant.util import dt as dt_util
from homeassistant.helpers import state
from homeassistant.const import (
STATE_OPEN, STATE_CLOSED,
STATE_LOCKED, STATE_UNLOCKED,
STATE_ON, STATE_OFF)
from homeassistant.components.media_player import (
SERVICE_PLAY_MEDIA, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PAUSE)
from homeassistant.components.sun import (STATE_ABOVE_HORIZON,
STATE_BELOW_HORIZON)
@ -22,16 +24,16 @@ class TestStateHelpers(unittest.TestCase):
"""Test the Home Assistant event helpers."""
def setUp(self): # pylint: disable=invalid-name
"""Setup things to be run when tests are started."""
"""Run when tests are started."""
self.hass = get_test_home_assistant()
core_components.setup(self.hass, {})
def tearDown(self): # pylint: disable=invalid-name
"""Stop down everything that was started."""
"""Stop when tests are finished."""
self.hass.stop()
def test_get_changed_since(self):
"""Test for changes since."""
"""Test get_changed_since."""
point1 = dt_util.utcnow()
point2 = point1 + timedelta(seconds=5)
point3 = point2 + timedelta(seconds=5)
@ -77,8 +79,19 @@ class TestStateHelpers(unittest.TestCase):
sorted([state2, state3], key=lambda state: state.entity_id),
sorted(states, key=lambda state: state.entity_id))
def test_reproduce_state_with_turn_on(self):
"""Test reproduction of state with turn_on."""
def test_reproduce_with_no_entity(self):
"""Test reproduce_state with no entity."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
state.reproduce_state(self.hass, ha.State('light.test', 'on'))
self.hass.pool.block_till_done()
self.assertTrue(len(calls) == 0)
self.assertEqual(None, self.hass.states.get('light.test'))
def test_reproduce_turn_on(self):
"""Test reproduce_state with SERVICE_TURN_ON."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
self.hass.states.set('light.test', 'off')
@ -93,8 +106,24 @@ class TestStateHelpers(unittest.TestCase):
self.assertEqual(SERVICE_TURN_ON, last_call.service)
self.assertEqual(['light.test'], last_call.data.get('entity_id'))
def test_reproduce_state_with_complex_service_data(self):
"""Test reproduction of state with complex service data."""
def test_reproduce_turn_off(self):
"""Test reproduce_state with SERVICE_TURN_OFF."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_OFF)
self.hass.states.set('light.test', 'on')
state.reproduce_state(self.hass, ha.State('light.test', 'off'))
self.hass.pool.block_till_done()
self.assertTrue(len(calls) > 0)
last_call = calls[-1]
self.assertEqual('light', last_call.domain)
self.assertEqual(SERVICE_TURN_OFF, last_call.service)
self.assertEqual(['light.test'], last_call.data.get('entity_id'))
def test_reproduce_complex_data(self):
"""Test reproduce_state with complex service data."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
self.hass.states.set('light.test', 'off')
@ -113,8 +142,78 @@ class TestStateHelpers(unittest.TestCase):
self.assertEqual(SERVICE_TURN_ON, last_call.service)
self.assertEqual(complex_data, last_call.data.get('complex'))
def test_reproduce_state_with_group(self):
"""Test reproduction of state with group."""
def test_reproduce_media_data(self):
"""Test reproduce_state with SERVICE_PLAY_MEDIA."""
calls = mock_service(self.hass, 'media_player', SERVICE_PLAY_MEDIA)
self.hass.states.set('media_player.test', 'off')
media_attributes = {'media_content_type': 'movie',
'media_content_id': 'batman'}
state.reproduce_state(self.hass, ha.State('media_player.test', 'None',
media_attributes))
self.hass.pool.block_till_done()
self.assertTrue(len(calls) > 0)
last_call = calls[-1]
self.assertEqual('media_player', last_call.domain)
self.assertEqual(SERVICE_PLAY_MEDIA, last_call.service)
self.assertEqual('movie', last_call.data.get('media_content_type'))
self.assertEqual('batman', last_call.data.get('media_content_id'))
def test_reproduce_media_play(self):
"""Test reproduce_state with SERVICE_MEDIA_PLAY."""
calls = mock_service(self.hass, 'media_player', SERVICE_MEDIA_PLAY)
self.hass.states.set('media_player.test', 'off')
state.reproduce_state(
self.hass, ha.State('media_player.test', 'playing'))
self.hass.pool.block_till_done()
self.assertTrue(len(calls) > 0)
last_call = calls[-1]
self.assertEqual('media_player', last_call.domain)
self.assertEqual(SERVICE_MEDIA_PLAY, last_call.service)
self.assertEqual(['media_player.test'],
last_call.data.get('entity_id'))
def test_reproduce_media_pause(self):
"""Test reproduce_state with SERVICE_MEDIA_PAUSE."""
calls = mock_service(self.hass, 'media_player', SERVICE_MEDIA_PAUSE)
self.hass.states.set('media_player.test', 'playing')
state.reproduce_state(
self.hass, ha.State('media_player.test', 'paused'))
self.hass.pool.block_till_done()
self.assertTrue(len(calls) > 0)
last_call = calls[-1]
self.assertEqual('media_player', last_call.domain)
self.assertEqual(SERVICE_MEDIA_PAUSE, last_call.service)
self.assertEqual(['media_player.test'],
last_call.data.get('entity_id'))
def test_reproduce_bad_state(self):
"""Test reproduce_state with bad state."""
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
self.hass.states.set('light.test', 'off')
state.reproduce_state(self.hass, ha.State('light.test', 'bad'))
self.hass.pool.block_till_done()
self.assertTrue(len(calls) == 0)
self.assertEqual('off', self.hass.states.get('light.test').state)
def test_reproduce_group(self):
"""Test reproduce_state with group."""
light_calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
self.hass.states.set('group.test', 'off', {
@ -131,8 +230,8 @@ class TestStateHelpers(unittest.TestCase):
self.assertEqual(['light.test1', 'light.test2'],
last_call.data.get('entity_id'))
def test_reproduce_state_group_states_with_same_domain_and_data(self):
"""Test reproduction of state with the dame domain."""
def test_reproduce_group_same_data(self):
"""Test reproduce_state with group with same domain and data."""
light_calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
self.hass.states.set('light.test1', 'off')
@ -153,7 +252,7 @@ class TestStateHelpers(unittest.TestCase):
self.assertEqual(95, last_call.data.get('brightness'))
def test_as_number_states(self):
"""Test number as states."""
"""Test state_as_number with states."""
zero_states = (STATE_OFF, STATE_CLOSED, STATE_UNLOCKED,
STATE_BELOW_HORIZON)
one_states = (STATE_ON, STATE_OPEN, STATE_LOCKED, STATE_ABOVE_HORIZON)
@ -165,7 +264,7 @@ class TestStateHelpers(unittest.TestCase):
ha.State('domain.test', _state, {})))
def test_as_number_coercion(self):
"""Test numbers."""
"""Test state_as_number with number."""
for _state in ('0', '0.0', 0, 0.0):
self.assertEqual(
0.0, state.state_as_number(
@ -176,7 +275,7 @@ class TestStateHelpers(unittest.TestCase):
ha.State('domain.test', _state, {})))
def test_as_number_invalid_cases(self):
"""."""
"""Test state_as_number with invalid cases."""
for _state in ('', 'foo', 'foo.bar', None, False, True, object,
object()):
self.assertRaises(ValueError,