From 58029a18450cf1777fa0ca280800fe34b3a025ca Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 1 Apr 2019 23:23:27 -0400 Subject: [PATCH 01/77] added tv from media player --- homeassistant/components/homekit/__init__.py | 2 +- homeassistant/components/homekit/const.py | 20 ++- .../components/homekit/type_media_players.py | 133 +++++++++++++++++- homeassistant/components/homekit/util.py | 14 +- 4 files changed, 157 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 01979f03b9a5f1..1fff49da07f04e 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -22,7 +22,7 @@ CONF_FILTER, CONF_SAFE_MODE, DEFAULT_AUTO_START, DEFAULT_PORT, DEFAULT_SAFE_MODE, DEVICE_CLASS_CO, DEVICE_CLASS_CO2, DEVICE_CLASS_PM25, DOMAIN, HOMEKIT_FILE, SERVICE_HOMEKIT_START, TYPE_FAUCET, TYPE_OUTLET, - TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) + TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_TELEVISION, TYPE_VALVE) from .util import ( show_setup_message, validate_entity_config, validate_media_player_features) diff --git a/homeassistant/components/homekit/const.py b/homeassistant/components/homekit/const.py index 1b2a4dbf05d2a9..2cfca5c99e3305 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -27,6 +27,8 @@ FEATURE_PLAY_PAUSE = 'play_pause' FEATURE_PLAY_STOP = 'play_stop' FEATURE_TOGGLE_MUTE = 'toggle_mute' +FEATURE_VOLUME_STEP = 'volume_step' +FEATURE_SELECT_SOURCE = 'select_source' # #### HomeKit Component Event #### EVENT_HOMEKIT_CHANGED = 'homekit_state_change' @@ -46,6 +48,7 @@ TYPE_SHOWER = 'shower' TYPE_SPRINKLER = 'sprinkler' TYPE_SWITCH = 'switch' +TYPE_TELEVISION = 'television' TYPE_VALVE = 'valve' # #### Services #### @@ -58,6 +61,7 @@ SERV_FANV2 = 'Fanv2' SERV_GARAGE_DOOR_OPENER = 'GarageDoorOpener' SERV_HUMIDITY_SENSOR = 'HumiditySensor' +SERV_INPUT_SOURCE = 'InputSource' SERV_LEAK_SENSOR = 'LeakSensor' SERV_LIGHT_SENSOR = 'LightSensor' SERV_LIGHTBULB = 'Lightbulb' @@ -68,6 +72,8 @@ SERV_SECURITY_SYSTEM = 'SecuritySystem' SERV_SMOKE_SENSOR = 'SmokeSensor' SERV_SWITCH = 'Switch' +SERV_TELEVISION = 'Television' +SERV_TELEVISION_SPEAKER = 'TelevisionSpeaker' SERV_TEMPERATURE_SENSOR = 'TemperatureSensor' SERV_THERMOSTAT = 'Thermostat' SERV_VALVE = 'Valve' @@ -75,6 +81,7 @@ # #### Characteristics #### CHAR_ACTIVE = 'Active' +CHAR_ACTIVE_IDENTIFIER = 'ActiveIdentifier' CHAR_AIR_PARTICULATE_DENSITY = 'AirParticulateDensity' CHAR_AIR_QUALITY = 'AirQuality' CHAR_BATTERY_LEVEL = 'BatteryLevel' @@ -87,6 +94,7 @@ CHAR_CARBON_MONOXIDE_PEAK_LEVEL = 'CarbonMonoxidePeakLevel' CHAR_CHARGING_STATE = 'ChargingState' CHAR_COLOR_TEMPERATURE = 'ColorTemperature' +CHAR_CONFIGURED_NAME = 'ConfiguredName' CHAR_CONTACT_SENSOR_STATE = 'ContactSensorState' CHAR_COOLING_THRESHOLD_TEMPERATURE = 'CoolingThresholdTemperature' CHAR_CURRENT_AMBIENT_LIGHT_LEVEL = 'CurrentAmbientLightLevel' @@ -96,10 +104,14 @@ CHAR_CURRENT_HUMIDITY = 'CurrentRelativeHumidity' CHAR_CURRENT_SECURITY_STATE = 'SecuritySystemCurrentState' CHAR_CURRENT_TEMPERATURE = 'CurrentTemperature' +CHAR_CURRENT_VISIBILITY_STATE = 'CurrentVisibilityState' CHAR_FIRMWARE_REVISION = 'FirmwareRevision' CHAR_HEATING_THRESHOLD_TEMPERATURE = 'HeatingThresholdTemperature' CHAR_HUE = 'Hue' +CHAR_IDENTIFIER = 'Identifier' CHAR_IN_USE = 'InUse' +CHAR_INPUT_SOURCE_TYPE = 'InputSourceType' +CHAR_IS_CONFIGURED = 'IsConfigured' CHAR_LEAK_DETECTED = 'LeakDetected' CHAR_LOCK_CURRENT_STATE = 'LockCurrentState' CHAR_LOCK_TARGET_STATE = 'LockTargetState' @@ -107,15 +119,17 @@ CHAR_MANUFACTURER = 'Manufacturer' CHAR_MODEL = 'Model' CHAR_MOTION_DETECTED = 'MotionDetected' +CHAR_MUTE = 'Mute' CHAR_NAME = 'Name' CHAR_OCCUPANCY_DETECTED = 'OccupancyDetected' -CHAR_OUTLET_IN_USE = 'OutletInUse' CHAR_ON = 'On' +CHAR_OUTLET_IN_USE = 'OutletInUse' CHAR_POSITION_STATE = 'PositionState' CHAR_ROTATION_DIRECTION = 'RotationDirection' CHAR_ROTATION_SPEED = 'RotationSpeed' CHAR_SATURATION = 'Saturation' CHAR_SERIAL_NUMBER = 'SerialNumber' +CHAR_SLEEP_DISCOVER_MODE = 'SleepDiscoveryMode' CHAR_SMOKE_DETECTED = 'SmokeDetected' CHAR_STATUS_LOW_BATTERY = 'StatusLowBattery' CHAR_SWING_MODE = 'SwingMode' @@ -126,6 +140,10 @@ CHAR_TARGET_TEMPERATURE = 'TargetTemperature' CHAR_TEMP_DISPLAY_UNITS = 'TemperatureDisplayUnits' CHAR_VALVE_TYPE = 'ValveType' +CHAR_VOLUME = 'Volume' +CHAR_VOLUME_SELECTOR = 'VolumeSelector' +CHAR_VOLUME_CONTROL_TYPE = 'VolumeControlType' + # #### Properties #### PROP_MAX_VALUE = 'maxValue' diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index f8f4ef96992475..58c47f79748054 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -1,20 +1,29 @@ """Class to hold all media player accessories.""" import logging -from pyhap.const import CATEGORY_SWITCH +from pyhap.const import CATEGORY_SWITCH, CATEGORY_TELEVISION from homeassistant.components.media_player import ( - ATTR_MEDIA_VOLUME_MUTED, DOMAIN) + ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, + ATTR_MEDIA_VOLUME_MUTED, ATTR_MEDIA_VOLUME_LEVEL, + SERVICE_SELECT_SOURCE, DOMAIN) from homeassistant.const import ( - ATTR_ENTITY_ID, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, + ATTR_ENTITY_ID, CONF_TYPE, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, + SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN, SERVICE_VOLUME_SET, STATE_OFF, STATE_PLAYING, STATE_UNKNOWN) from . import TYPES from .accessories import HomeAccessory from .const import ( - CHAR_NAME, CHAR_ON, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, SERV_SWITCH) + CHAR_ACTIVE, CHAR_ACTIVE_IDENTIFIER, CHAR_CONFIGURED_NAME, + CHAR_CURRENT_VISIBILITY_STATE, CHAR_IDENTIFIER, CHAR_INPUT_SOURCE_TYPE, + CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_ON, CHAR_SLEEP_DISCOVER_MODE, + CHAR_MUTE, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, CHAR_VOLUME, + CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, + FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, + FEATURE_VOLUME_STEP, SERV_SWITCH, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, + SERV_INPUT_SOURCE, TYPE_SWITCH, TYPE_TELEVISION) _LOGGER = logging.getLogger(__name__) @@ -34,11 +43,88 @@ def __init__(self, *args): """Initialize a Switch accessory object.""" super().__init__(*args, category=CATEGORY_SWITCH) self._flag = {FEATURE_ON_OFF: False, FEATURE_PLAY_PAUSE: False, - FEATURE_PLAY_STOP: False, FEATURE_TOGGLE_MUTE: False} + FEATURE_PLAY_STOP: False, FEATURE_TOGGLE_MUTE: False, + FEATURE_SELECT_SOURCE: False} self.chars = {FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, - FEATURE_PLAY_STOP: None, FEATURE_TOGGLE_MUTE: None} + FEATURE_PLAY_STOP: None, FEATURE_TOGGLE_MUTE: None, + FEATURE_SELECT_SOURCE: None} feature_list = self.config[CONF_FEATURE_LIST] + self.sources = [] + + a_type = self.config.get(CONF_TYPE, TYPE_SWITCH) + + if a_type == TYPE_TELEVISION and FEATURE_ON_OFF in feature_list: + + self.category = CATEGORY_TELEVISION + television = self.add_preload_service(SERV_TELEVISION, + CHAR_CONFIGURED_NAME) + television.configure_char(CHAR_CONFIGURED_NAME, + value=self.display_name) + television.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) + self.chars[FEATURE_ON_OFF] = television.configure_char( + CHAR_ACTIVE, value=False, setter_callback=self.set_on_off) + + if FEATURE_TOGGLE_MUTE in feature_list: + + television_speaker = self.add_preload_service( + SERV_TELEVISION_SPEAKER, + [ + CHAR_NAME, CHAR_ACTIVE, + CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR, + CHAR_VOLUME + ]) + television.add_linked_service(television_speaker) + + name = '{} {}'.format(self.display_name, 'Volume') + television_speaker.configure_char(CHAR_NAME, value=name) + television_speaker.configure_char(CHAR_ACTIVE, value=1) + + self.chars[FEATURE_TOGGLE_MUTE] \ + = television_speaker.configure_char( + CHAR_MUTE, value=False, + setter_callback=self.set_toggle_mute) + + if FEATURE_VOLUME_STEP in feature_list: + television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, + value=1) + television_speaker.configure_char( + CHAR_VOLUME_SELECTOR, + setter_callback=self.set_volume_step) + + if FEATURE_SELECT_SOURCE in feature_list: + + self.chars[FEATURE_SELECT_SOURCE] \ + = television.configure_char( + CHAR_ACTIVE_IDENTIFIER, + setter_callback=self.set_input_source_set) + _LOGGER.error('%s: Sources to %s', + self.entity_id, repr(self.hass.states.get(self.entity_id))) + return + self.sources = self.hass.states.get(self.entity_id).attributes.get('source_list') + for index, source in enumerate(self.sources): + input_service = self.add_preload_service( + SERV_INPUT_SOURCE, + [ + CHAR_IDENTIFIER, + ]) + television.add_linked_service(input_service) + + input_service.configure_char(CHAR_CONFIGURED_NAME, + value=source) + input_service.configure_char(CHAR_IDENTIFIER, value=index) + input_service.configure_char(CHAR_IS_CONFIGURED, + value=True) + inputType = 3 if "hdmi" in source.lower() else 0 + input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, + value=inputType) + input_service.configure_char(CHAR_CURRENT_VISIBILITY_STATE, + value=False) + + self.set_primary_service(television) + return + if FEATURE_ON_OFF in feature_list: name = self.generate_service_name(FEATURE_ON_OFF) serv_on_off = self.add_preload_service(SERV_SWITCH, CHAR_NAME) @@ -107,6 +193,26 @@ def set_toggle_mute(self, value): ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) + def set_volume_step(self, value): + """Send volume step value if call came from HomeKit.""" + _LOGGER.debug('%s: Step tv_volume for "tv_volume" to %s', + self.entity_id, value) + + service = SERVICE_VOLUME_DOWN if value else SERVICE_VOLUME_UP + params = {ATTR_ENTITY_ID: self.entity_id} + self.call_service(DOMAIN, service, params) + + def set_input_source_set(self, value): + """Send input set value if call came from HomeKit.""" + _LOGGER.debug('%s: Set tv_select_source for "tv_select_source" to %s', + self.entity_id, value) + + source = self.sources[value] + self._flag[FEATURE_SELECT_SOURCE] = True + params = {ATTR_ENTITY_ID: self.entity_id, + ATTR_INPUT_SOURCE: source} + self.call_service(DOMAIN, SERVICE_SELECT_SOURCE, params) + def update_state(self, new_state): """Update switch state after state changed.""" current_state = new_state.state @@ -142,3 +248,16 @@ def update_state(self, new_state): self.entity_id, current_state) self.chars[FEATURE_TOGGLE_MUTE].set_value(current_state) self._flag[FEATURE_TOGGLE_MUTE] = False + + if self.chars[FEATURE_SELECT_SOURCE]: + sourceName = new_state.attributes.get(ATTR_INPUT_SOURCE) + if not self._flag[FEATURE_SELECT_SOURCE]: + _LOGGER.debug( + '%s: Set current state for "select_source" to %s', + self.entity_id, sourceName) + if sourceName in self.sources: + index = self.sources.index(sourceName) + self.chars[FEATURE_SELECT_SOURCE].set_value(index) + else: + self.chars[FEATURE_SELECT_SOURCE].set_value(-1) + self._flag[FEATURE_SELECT_SOURCE] = False diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index 2ba5819a202d49..bdd40b493d79c2 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -13,8 +13,9 @@ from .const import ( CONF_FEATURE, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, HOMEKIT_NOTIFY_ID, TYPE_FAUCET, - TYPE_OUTLET, TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) + FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP, + FEATURE_SELECT_SOURCE, HOMEKIT_NOTIFY_ID, TYPE_FAUCET, TYPE_OUTLET, + TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_TELEVISION, TYPE_VALVE) _LOGGER = logging.getLogger(__name__) @@ -25,6 +26,8 @@ FEATURE_SCHEMA = BASIC_INFO_SCHEMA.extend({ vol.Optional(CONF_FEATURE_LIST, default=None): cv.ensure_list, + vol.Optional(CONF_TYPE, default=TYPE_SWITCH): vol.All( + cv.string, vol.In((TYPE_TELEVISION))), }) @@ -35,7 +38,8 @@ MEDIA_PLAYER_SCHEMA = vol.Schema({ vol.Required(CONF_FEATURE): vol.All( cv.string, vol.In((FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE))), + FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, + FEATURE_SELECT_SOURCE, FEATURE_VOLUME_STEP))), }) SWITCH_TYPE_SCHEMA = BASIC_INFO_SCHEMA.extend({ @@ -101,6 +105,10 @@ def validate_media_player_features(state, feature_list): supported_modes.append(FEATURE_PLAY_STOP) if features & media_player.const.SUPPORT_VOLUME_MUTE: supported_modes.append(FEATURE_TOGGLE_MUTE) + if features & media_player.const.SUPPORT_VOLUME_STEP: + supported_modes.append(FEATURE_VOLUME_STEP) + if features & media_player.const.SUPPORT_SELECT_SOURCE: + supported_modes.append(FEATURE_SELECT_SOURCE) error_list = [] for feature in feature_list: From 6b02d97650c649a678f1d5881ceacb8685086533 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 3 Apr 2019 23:22:04 -0400 Subject: [PATCH 02/77] added play_pause for homekit tv --- homeassistant/components/homekit/const.py | 1 + .../components/homekit/type_media_players.py | 53 ++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/homekit/const.py b/homeassistant/components/homekit/const.py index 2cfca5c99e3305..7e6380a0c527cf 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -125,6 +125,7 @@ CHAR_ON = 'On' CHAR_OUTLET_IN_USE = 'OutletInUse' CHAR_POSITION_STATE = 'PositionState' +CHAR_REMOTE_KEY = 'RemoteKey' CHAR_ROTATION_DIRECTION = 'RotationDirection' CHAR_ROTATION_SPEED = 'RotationSpeed' CHAR_SATURATION = 'Saturation' diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 131e97a85f6f92..0d19b5a3ba661a 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -9,9 +9,10 @@ SERVICE_SELECT_SOURCE, DOMAIN) from homeassistant.const import ( ATTR_ENTITY_ID, CONF_TYPE, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, - SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, - SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN, SERVICE_VOLUME_SET, - STATE_OFF, STATE_PLAYING, STATE_UNKNOWN) + SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, + SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, + SERVICE_VOLUME_DOWN, SERVICE_VOLUME_SET, STATE_OFF, STATE_PLAYING, + STATE_UNKNOWN) from . import TYPES from .accessories import HomeAccessory @@ -19,8 +20,8 @@ CHAR_ACTIVE, CHAR_ACTIVE_IDENTIFIER, CHAR_CONFIGURED_NAME, CHAR_CURRENT_VISIBILITY_STATE, CHAR_IDENTIFIER, CHAR_INPUT_SOURCE_TYPE, CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_ON, CHAR_SLEEP_DISCOVER_MODE, - CHAR_MUTE, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, CHAR_VOLUME, - CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, + CHAR_MUTE, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, + CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP, SERV_SWITCH, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, SERV_INPUT_SOURCE, TYPE_SWITCH, TYPE_TELEVISION) @@ -34,6 +35,25 @@ FEATURE_TOGGLE_MUTE: 'Mute', } +REMOTE_KEYS = { + 0: "Rewind", + 1: "FastForward", + 2: "NextTrack", + 3: "PreviousTrack", + 4: "ArrowUp", + 5: "ArrowDown", + 6: "ArrowLeft", + 7: "ArrowRight", + 8: "Select", + 9: "Back", + 10: "Exit", + 15: "Information" +} + +MEDIA_PLAYER_KEYS = { + 11: SERVICE_MEDIA_PLAY_PAUSE, +} + @TYPES.register('MediaPlayer') class MediaPlayer(HomeAccessory): @@ -58,13 +78,22 @@ def __init__(self, *args): self.category = CATEGORY_TELEVISION television = self.add_preload_service(SERV_TELEVISION, - CHAR_CONFIGURED_NAME) + [ + CHAR_CONFIGURED_NAME, + CHAR_REMOTE_KEY + ]) television.configure_char(CHAR_CONFIGURED_NAME, value=self.display_name) television.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) self.chars[FEATURE_ON_OFF] = television.configure_char( CHAR_ACTIVE, value=False, setter_callback=self.set_on_off) + if FEATURE_PLAY_PAUSE in feature_list: + self.chars[FEATURE_PLAY_PAUSE] \ + = television.configure_char( + CHAR_REMOTE_KEY, + setter_callback=self.set_remote_key) + if FEATURE_TOGGLE_MUTE in feature_list: television_speaker = self.add_preload_service( @@ -204,7 +233,7 @@ def set_volume_step(self, value): def set_input_source(self, value): """Send input set value if call came from HomeKit.""" - _LOGGER.debug('%s: Set tv_select_source for "tv_select_source" to %s', + _LOGGER.debug('%s: Set select_source for "select_source" to %s', self.entity_id, value) source = self.sources[value] @@ -213,6 +242,16 @@ def set_input_source(self, value): ATTR_INPUT_SOURCE: source} self.call_service(DOMAIN, SERVICE_SELECT_SOURCE, params) + def set_remote_key(self, value): + """Send remote key value if call came from HomeKit.""" + _LOGGER.debug('%s: Set remote key for "play_pause" to %s', + self.entity_id, value) + + if value in MEDIA_PLAYER_KEYS: + service = MEDIA_PLAYER_KEYS[value] + params = {ATTR_ENTITY_ID: self.entity_id} + self.call_service(DOMAIN, service, params) + def update_state(self, new_state): """Update switch state after state changed.""" current_state = new_state.state From 9be596309eb53743148658c3809f8505c96ba752 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 7 Apr 2019 23:06:45 -0400 Subject: [PATCH 03/77] added warning and checks on None for sources --- .../components/homekit/type_media_players.py | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 0d19b5a3ba661a..5542955eaf4ad3 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -86,7 +86,7 @@ def __init__(self, *args): value=self.display_name) television.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) self.chars[FEATURE_ON_OFF] = television.configure_char( - CHAR_ACTIVE, value=False, setter_callback=self.set_on_off) + CHAR_ACTIVE, setter_callback=self.set_on_off) if FEATURE_PLAY_PAUSE in feature_list: self.chars[FEATURE_PLAY_PAUSE] \ @@ -129,27 +129,36 @@ def __init__(self, *args): CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) - self.sources = self.hass.states.get(self.entity_id).attributes.get('source_list') - for index, source in enumerate(self.sources): - input_service = self.add_preload_service( - SERV_INPUT_SOURCE, - [ - CHAR_IDENTIFIER, - CHAR_NAME - ]) - - input_service.configure_char(CHAR_CONFIGURED_NAME, - value=source) - input_service.configure_char(CHAR_NAME, value=source) - input_service.configure_char(CHAR_IDENTIFIER, value=index) - input_service.configure_char(CHAR_IS_CONFIGURED, - value=True) - input_type = 3 if "hdmi" in source.lower() else 0 - input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, - value=input_type) - input_service.configure_char(CHAR_CURRENT_VISIBILITY_STATE, - value=False) - television.add_linked_service(input_service) + self.sources = self.hass.states.get( + self.entity_id).attributes.get('source_list') + if self.sources: + for index, source in enumerate(self.sources): + input_service = self.add_preload_service( + SERV_INPUT_SOURCE, + [ + CHAR_IDENTIFIER, + CHAR_NAME + ]) + + input_service.configure_char( + CHAR_CONFIGURED_NAME, value=source) + input_service.configure_char(CHAR_NAME, value=source) + input_service.configure_char( + CHAR_IDENTIFIER, value=index) + input_service.configure_char( + CHAR_IS_CONFIGURED, value=True) + input_type = 3 if "hdmi" in source.lower() else 0 + input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, + value=input_type) + input_service.configure_char( + CHAR_CURRENT_VISIBILITY_STATE, value=False) + television.add_linked_service(input_service) + _LOGGER.debug('%s: Added source %s.', self.entity_id, + source) + else: + _LOGGER.warn('%s: Source list empty when setting up sources. Please check \ + to make sure your media_player is turned on.', + self.entity_id) self.set_primary_service(television) return @@ -290,7 +299,7 @@ def update_state(self, new_state): if self.chars[FEATURE_SELECT_SOURCE]: sourceName = new_state.attributes.get(ATTR_INPUT_SOURCE) - if not self._flag[FEATURE_SELECT_SOURCE]: + if self.sources and not self._flag[FEATURE_SELECT_SOURCE]: _LOGGER.debug( '%s: Set current state for "select_source" to %s', self.entity_id, sourceName) From 1b20c85e7b12d5a4553f9f6eb4e2dd592245ea6e Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 7 Apr 2019 23:21:57 -0400 Subject: [PATCH 04/77] removed initial value for on_off --- homeassistant/components/homekit/type_media_players.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 5542955eaf4ad3..f5445ad66a73a5 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -168,7 +168,7 @@ def __init__(self, *args): serv_on_off = self.add_preload_service(SERV_SWITCH, CHAR_NAME) serv_on_off.configure_char(CHAR_NAME, value=name) self.chars[FEATURE_ON_OFF] = serv_on_off.configure_char( - CHAR_ON, value=False, setter_callback=self.set_on_off) + CHAR_ON, setter_callback=self.set_on_off) if FEATURE_PLAY_PAUSE in feature_list: name = self.generate_service_name(FEATURE_PLAY_PAUSE) From 54f341bfe64ec1f85196f28309ea6f60f482304e Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 01:43:02 -0400 Subject: [PATCH 05/77] added type validation --- homeassistant/components/homekit/util.py | 2 +- tests/components/homekit/test_util.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index bdd40b493d79c2..42163496902399 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -27,7 +27,7 @@ FEATURE_SCHEMA = BASIC_INFO_SCHEMA.extend({ vol.Optional(CONF_FEATURE_LIST, default=None): cv.ensure_list, vol.Optional(CONF_TYPE, default=TYPE_SWITCH): vol.All( - cv.string, vol.In((TYPE_TELEVISION))), + cv.string, vol.In((TYPE_SWITCH, TYPE_TELEVISION))), }) diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index c86b1353c48936..639d4d9294ccc4 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -5,7 +5,7 @@ from homeassistant.components.homekit.const import ( CONF_FEATURE, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, HOMEKIT_NOTIFY_ID, TYPE_FAUCET, TYPE_OUTLET, TYPE_SHOWER, TYPE_SPRINKLER, - TYPE_SWITCH, TYPE_VALVE) + TYPE_SWITCH, TYPE_TELEVISION, TYPE_VALVE) from homeassistant.components.homekit.util import ( HomeKitSpeedMapping, SpeedRange, convert_to_float, density_to_air_quality, dismiss_setup_message, show_setup_message, temperature_to_homekit, @@ -32,6 +32,7 @@ def test_validate_entity_config(): {'media_player.test': {CONF_FEATURE_LIST: [ {CONF_FEATURE: FEATURE_ON_OFF}, {CONF_FEATURE: FEATURE_ON_OFF}]}}, + {'media_player.test': {CONF_TYPE: 'invalid_type'}}, {'switch.test': {CONF_TYPE: 'invalid_type'}}] for conf in configs: @@ -59,6 +60,13 @@ def test_validate_entity_config(): {'media_player.demo': {CONF_FEATURE_LIST: {FEATURE_ON_OFF: {}, FEATURE_PLAY_PAUSE: {}}}} + assert vec({'media_player.demo': {}}) == \ + {'media_player.demo': {CONF_TYPE: TYPE_SWITCH}} + assert vec({'media_player.demo': {}}) == \ + {'media_player.demo': {CONF_TYPE: TYPE_SWITCH}} + assert vec({'media_player.demo': {CONF_TYPE: TYPE_TELEVISION}}) == \ + {'media_player.demo': {CONF_TYPE: TYPE_TELEVISION}} + assert vec({'switch.demo': {CONF_TYPE: TYPE_FAUCET}}) == \ {'switch.demo': {CONF_TYPE: TYPE_FAUCET}} assert vec({'switch.demo': {CONF_TYPE: TYPE_OUTLET}}) == \ From c4d4a9e66173ab031e9de5e67264260b2bac60fa Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 01:45:21 -0400 Subject: [PATCH 06/77] added television test --- .../homekit/test_type_media_players.py | 142 +++++++++++++++++- 1 file changed, 139 insertions(+), 3 deletions(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 065d1845fdb5e6..2c7eddcbc02a13 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -2,13 +2,16 @@ from homeassistant.components.homekit.const import ( ATTR_VALUE, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE) + FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, + FEATURE_VOLUME_STEP, TYPE_TELEVISION) from homeassistant.components.homekit.type_media_players import MediaPlayer from homeassistant.components.media_player.const import ( + ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, DOMAIN) from homeassistant.const import ( - ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, STATE_IDLE, STATE_OFF, STATE_ON, - STATE_PAUSED, STATE_PLAYING) + ATTR_ENTITY_ID, ATTR_STATE, ATTR_SUPPORTED_FEATURES, CONF_TYPE, STATE_IDLE, + STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) + from tests.common import async_mock_service @@ -129,3 +132,136 @@ async def test_media_player_set_state(hass, hk_driver, events): assert call_toggle_mute[1].data[ATTR_MEDIA_VOLUME_MUTED] is False assert len(events) == 8 assert events[-1].data[ATTR_VALUE] is None + + +async def test_media_player_television_set_state(hass, hk_driver, events): + """Test if television accessory and HA are updated accordingly.""" + config = {CONF_TYPE: TYPE_TELEVISION, CONF_FEATURE_LIST: { + FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, + FEATURE_SELECT_SOURCE: None, FEATURE_TOGGLE_MUTE: None, + FEATURE_VOLUME_STEP: None}} + entity_id = 'media_player.television' + + hass.states.async_set(entity_id, None, {ATTR_SUPPORTED_FEATURES: 20873, + ATTR_MEDIA_VOLUME_MUTED: False, + ATTR_INPUT_SOURCE_LIST: + ['HDMI 1', 'HDMI 2', 'HDMI 3', + 'HDMI 4'] + }) + await hass.async_block_till_done() + acc = MediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, config) + await hass.async_add_job(acc.run) + + assert acc.aid == 2 + assert acc.category == 31 # Television + + assert acc.chars[FEATURE_ON_OFF].value is 0 + assert acc.chars[FEATURE_PLAY_PAUSE].value is 0 + assert acc.chars[FEATURE_SELECT_SOURCE].value is 0 + assert acc.chars[FEATURE_TOGGLE_MUTE].value is False + + hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True}) + await hass.async_block_till_done() + assert acc.chars[FEATURE_ON_OFF].value is 1 + assert acc.chars[FEATURE_TOGGLE_MUTE].value is True + + hass.states.async_set(entity_id, STATE_OFF) + await hass.async_block_till_done() + assert acc.chars[FEATURE_ON_OFF].value is 0 + + hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 2'}) + await hass.async_block_till_done() + assert acc.chars[FEATURE_SELECT_SOURCE].value is 1 + + hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 3'}) + await hass.async_block_till_done() + assert acc.chars[FEATURE_SELECT_SOURCE].value is 2 + + # Set from HomeKit + call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on') + call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off') + call_media_play = async_mock_service(hass, DOMAIN, 'media_play') + call_media_pause = async_mock_service(hass, DOMAIN, 'media_pause') + call_toggle_mute = async_mock_service(hass, DOMAIN, 'volume_mute') + call_select_source = async_mock_service(hass, DOMAIN, 'select_source') + call_volume_up = async_mock_service(hass, DOMAIN, 'volume_up') + call_volume_down = async_mock_service(hass, DOMAIN, 'volume_down') + + await hass.async_add_job(acc.chars[FEATURE_ON_OFF] + .client_update_value, 1) + await hass.async_block_till_done() + assert call_turn_on + assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 1 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.chars[FEATURE_ON_OFF] + .client_update_value, 0) + await hass.async_block_till_done() + assert call_turn_off + assert call_turn_off[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 2 + assert events[-1].data[ATTR_VALUE] is None + + hass.states.async_set(entity_id, STATE_PAUSED) + await hass.async_block_till_done() + await hass.async_add_job(acc.chars[FEATURE_PLAY_PAUSE] + .client_update_value, 11) + await hass.async_block_till_done() + assert call_media_play + assert call_media_play[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 3 + assert events[-1].data[ATTR_VALUE] is None + + hass.states.async_set(entity_id, STATE_PLAYING) + await hass.async_block_till_done() + await hass.async_add_job(acc.chars[FEATURE_PLAY_PAUSE] + .client_update_value, 11) + await hass.async_block_till_done() + assert call_media_pause + assert call_media_pause[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 4 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.chars[FEATURE_TOGGLE_MUTE] + .client_update_value, True) + await hass.async_block_till_done() + assert call_toggle_mute + assert call_toggle_mute[0].data[ATTR_ENTITY_ID] == entity_id + assert call_toggle_mute[0].data[ATTR_MEDIA_VOLUME_MUTED] is True + assert len(events) == 5 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.chars[FEATURE_TOGGLE_MUTE] + .client_update_value, False) + await hass.async_block_till_done() + assert call_toggle_mute + assert call_toggle_mute[1].data[ATTR_ENTITY_ID] == entity_id + assert call_toggle_mute[1].data[ATTR_MEDIA_VOLUME_MUTED] is False + assert len(events) == 6 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.chars[FEATURE_SELECT_SOURCE] + .client_update_value, 1) + await hass.async_block_till_done() + assert call_select_source + assert call_select_source[0].data[ATTR_ENTITY_ID] == entity_id + assert call_select_source[0].data[ATTR_INPUT_SOURCE] is 'HDMI 2' + assert len(events) == 7 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.chars[FEATURE_VOLUME_STEP] + .client_update_value, 0) + await hass.async_block_till_done() + assert call_volume_up + assert call_volume_up[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 8 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.chars[FEATURE_VOLUME_STEP] + .client_update_value, 1) + await hass.async_block_till_done() + assert call_volume_down + assert call_volume_down[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 9 + assert events[-1].data[ATTR_VALUE] is None From a5ce8e5745f65cf198a3ab6117665612ae96f626 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 01:46:06 -0400 Subject: [PATCH 07/77] send specific command if known --- homeassistant/components/homekit/type_media_players.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index f5445ad66a73a5..a671659deb39e9 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -258,6 +258,11 @@ def set_remote_key(self, value): if value in MEDIA_PLAYER_KEYS: service = MEDIA_PLAYER_KEYS[value] + if service == SERVICE_MEDIA_PLAY_PAUSE: + state = self.hass.states.get(self.entity_id).state + if state in (STATE_PLAYING, STATE_PAUSED): + self.set_play_pause(state == STATE_PAUSED) + return; params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) From babf1e1a4e9ead19b7b386aa21a796eb03dcff9a Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 01:46:43 -0400 Subject: [PATCH 08/77] do not save play state to remotekey char --- homeassistant/components/homekit/type_media_players.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index a671659deb39e9..7af301166f3248 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -280,7 +280,8 @@ def update_state(self, new_state): if self.chars[FEATURE_PLAY_PAUSE]: hk_state = current_state == STATE_PLAYING - if not self._flag[FEATURE_PLAY_PAUSE]: + if not self._flag[FEATURE_PLAY_PAUSE] and \ + not self.category == CATEGORY_TELEVISION: _LOGGER.debug('%s: Set current state for "play_pause" to %s', self.entity_id, hk_state) self.chars[FEATURE_PLAY_PAUSE].set_value(hk_state) From 290c457e61b985afe1714631483f9a21e906519a Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 01:47:02 -0400 Subject: [PATCH 09/77] fixed values --- homeassistant/components/homekit/type_media_players.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 7af301166f3248..da41c679f2f996 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -12,7 +12,7 @@ SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN, SERVICE_VOLUME_SET, STATE_OFF, STATE_PLAYING, - STATE_UNKNOWN) + STATE_PAUSED, STATE_UNKNOWN) from . import TYPES from .accessories import HomeAccessory @@ -273,6 +273,8 @@ def update_state(self, new_state): if self.chars[FEATURE_ON_OFF]: hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') if not self._flag[FEATURE_ON_OFF]: + if self.category is CATEGORY_TELEVISION: + hk_state = 1 if hk_state else 0 _LOGGER.debug('%s: Set current state for "on_off" to %s', self.entity_id, hk_state) self.chars[FEATURE_ON_OFF].set_value(hk_state) @@ -311,7 +313,7 @@ def update_state(self, new_state): self.entity_id, sourceName) if sourceName in self.sources: index = self.sources.index(sourceName) - self.chars[FEATURE_SELECT_SOURCE].set_value(index+1) + self.chars[FEATURE_SELECT_SOURCE].set_value(index) else: self.chars[FEATURE_SELECT_SOURCE].set_value(0) self._flag[FEATURE_SELECT_SOURCE] = False From 9aa806a77f92f470a5ab2e49b6a25ab06fa76031 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 01:53:57 -0400 Subject: [PATCH 10/77] fixed volume step to be testable --- homeassistant/components/homekit/type_media_players.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index da41c679f2f996..3bd8756b4ee9ed 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -67,7 +67,7 @@ def __init__(self, *args): FEATURE_SELECT_SOURCE: False} self.chars = {FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, FEATURE_PLAY_STOP: None, FEATURE_TOGGLE_MUTE: None, - FEATURE_SELECT_SOURCE: None} + FEATURE_SELECT_SOURCE: None, FEATURE_VOLUME_STEP: None} feature_list = self.config[CONF_FEATURE_LIST] self.sources = [] @@ -118,7 +118,8 @@ def __init__(self, *args): if FEATURE_VOLUME_STEP in feature_list: television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) - television_speaker.configure_char( + self.chars[FEATURE_VOLUME_STEP] = television_speaker.\ + configure_char( CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) From 00f1841194cc41edc3936449e094fdcf71b2d555 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 08:51:50 -0400 Subject: [PATCH 11/77] bump HAP-python --- homeassistant/components/homekit/__init__.py | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 1fff49da07f04e..638321825abed9 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -26,7 +26,7 @@ from .util import ( show_setup_message, validate_entity_config, validate_media_player_features) -REQUIREMENTS = ['HAP-python==2.4.2'] +REQUIREMENTS = ['HAP-python==2.5.0'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 8ed77fdfb3e89a..be59c86a9e4c53 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -33,7 +33,7 @@ Adafruit-SHT31==1.0.2 # Adafruit_BBIO==1.0.0 # homeassistant.components.homekit -HAP-python==2.4.2 +HAP-python==2.5.0 # homeassistant.components.mastodon.notify Mastodon.py==1.3.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e08255c246d7fd..b772950033df98 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -20,7 +20,7 @@ requests_mock==1.5.2 # homeassistant.components.homekit -HAP-python==2.4.2 +HAP-python==2.5.0 # homeassistant.components.mobile_app # homeassistant.components.owntracks From 7adb4cc86263e23556d2f2273de730e0e75b9e92 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 21:24:12 -0400 Subject: [PATCH 12/77] remove unused service --- homeassistant/components/homekit/type_media_players.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 3bd8756b4ee9ed..a5b7b8e2059bdd 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -11,8 +11,8 @@ ATTR_ENTITY_ID, CONF_TYPE, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, - SERVICE_VOLUME_DOWN, SERVICE_VOLUME_SET, STATE_OFF, STATE_PLAYING, - STATE_PAUSED, STATE_UNKNOWN) + SERVICE_VOLUME_DOWN, STATE_OFF, STATE_PLAYING, STATE_PAUSED, + STATE_UNKNOWN) from . import TYPES from .accessories import HomeAccessory From a89248be08264fd21a7dd1939536fc7b92d2b0b9 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 21:33:38 -0400 Subject: [PATCH 13/77] remove unused imports --- homeassistant/components/homekit/__init__.py | 2 +- homeassistant/components/homekit/type_media_players.py | 4 +--- tests/components/homekit/test_type_media_players.py | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 638321825abed9..9d7de58be4bc5a 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -22,7 +22,7 @@ CONF_FILTER, CONF_SAFE_MODE, DEFAULT_AUTO_START, DEFAULT_PORT, DEFAULT_SAFE_MODE, DEVICE_CLASS_CO, DEVICE_CLASS_CO2, DEVICE_CLASS_PM25, DOMAIN, HOMEKIT_FILE, SERVICE_HOMEKIT_START, TYPE_FAUCET, TYPE_OUTLET, - TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_TELEVISION, TYPE_VALVE) + TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) from .util import ( show_setup_message, validate_entity_config, validate_media_player_features) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index a5b7b8e2059bdd..f9ede24fcf8e00 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -4,9 +4,7 @@ from pyhap.const import CATEGORY_SWITCH, CATEGORY_TELEVISION from homeassistant.components.media_player import ( - ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, - ATTR_MEDIA_VOLUME_MUTED, ATTR_MEDIA_VOLUME_LEVEL, - SERVICE_SELECT_SOURCE, DOMAIN) + ATTR_INPUT_SOURCE, ATTR_MEDIA_VOLUME_MUTED, SERVICE_SELECT_SOURCE, DOMAIN) from homeassistant.const import ( ATTR_ENTITY_ID, CONF_TYPE, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 2c7eddcbc02a13..ca03c74191e124 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -9,8 +9,8 @@ ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, DOMAIN) from homeassistant.const import ( - ATTR_ENTITY_ID, ATTR_STATE, ATTR_SUPPORTED_FEATURES, CONF_TYPE, STATE_IDLE, - STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) + ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_TYPE, STATE_IDLE, STATE_OFF, + STATE_ON, STATE_PAUSED, STATE_PLAYING) from tests.common import async_mock_service From 874979acf8c2d21ba4a6de118e8a42e79b514f7f Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 21:33:50 -0400 Subject: [PATCH 14/77] lint issues --- .../components/homekit/type_media_players.py | 2 +- .../homekit/test_type_media_players.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index f9ede24fcf8e00..06b4f6aabbb34f 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -261,7 +261,7 @@ def set_remote_key(self, value): state = self.hass.states.get(self.entity_id).state if state in (STATE_PLAYING, STATE_PAUSED): self.set_play_pause(state == STATE_PAUSED) - return; + return params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index ca03c74191e124..00a95140014f41 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -155,27 +155,27 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert acc.aid == 2 assert acc.category == 31 # Television - assert acc.chars[FEATURE_ON_OFF].value is 0 - assert acc.chars[FEATURE_PLAY_PAUSE].value is 0 - assert acc.chars[FEATURE_SELECT_SOURCE].value is 0 + assert acc.chars[FEATURE_ON_OFF].value == 0 + assert acc.chars[FEATURE_PLAY_PAUSE].value == 0 + assert acc.chars[FEATURE_SELECT_SOURCE].value == 0 assert acc.chars[FEATURE_TOGGLE_MUTE].value is False hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True}) await hass.async_block_till_done() - assert acc.chars[FEATURE_ON_OFF].value is 1 + assert acc.chars[FEATURE_ON_OFF].value == 1 assert acc.chars[FEATURE_TOGGLE_MUTE].value is True hass.states.async_set(entity_id, STATE_OFF) await hass.async_block_till_done() - assert acc.chars[FEATURE_ON_OFF].value is 0 + assert acc.chars[FEATURE_ON_OFF].value == 0 hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 2'}) await hass.async_block_till_done() - assert acc.chars[FEATURE_SELECT_SOURCE].value is 1 + assert acc.chars[FEATURE_SELECT_SOURCE].value == 1 hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 3'}) await hass.async_block_till_done() - assert acc.chars[FEATURE_SELECT_SOURCE].value is 2 + assert acc.chars[FEATURE_SELECT_SOURCE].value == 2 # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on') @@ -246,7 +246,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): await hass.async_block_till_done() assert call_select_source assert call_select_source[0].data[ATTR_ENTITY_ID] == entity_id - assert call_select_source[0].data[ATTR_INPUT_SOURCE] is 'HDMI 2' + assert call_select_source[0].data[ATTR_INPUT_SOURCE] == 'HDMI 2' assert len(events) == 7 assert events[-1].data[ATTR_VALUE] is None From 36e3adc71b3fe50c1c6fcf32fa481790f6153532 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 21:41:12 -0400 Subject: [PATCH 15/77] more lint issues --- .../components/homekit/type_media_players.py | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 06b4f6aabbb34f..f359bf99b85c61 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -89,19 +89,18 @@ def __init__(self, *args): if FEATURE_PLAY_PAUSE in feature_list: self.chars[FEATURE_PLAY_PAUSE] \ = television.configure_char( - CHAR_REMOTE_KEY, - setter_callback=self.set_remote_key) + CHAR_REMOTE_KEY, + setter_callback=self.set_remote_key) if FEATURE_TOGGLE_MUTE in feature_list: television_speaker = self.add_preload_service( - SERV_TELEVISION_SPEAKER, - [ - CHAR_NAME, CHAR_ACTIVE, - CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR, - CHAR_VOLUME - ]) + SERV_TELEVISION_SPEAKER, [ + CHAR_NAME, CHAR_ACTIVE, + CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR, + CHAR_VOLUME + ]) television.add_linked_service(television_speaker) name = '{} {}'.format(self.display_name, 'Volume') @@ -110,34 +109,33 @@ def __init__(self, *args): self.chars[FEATURE_TOGGLE_MUTE] \ = television_speaker.configure_char( - CHAR_MUTE, value=False, - setter_callback=self.set_toggle_mute) + CHAR_MUTE, value=False, + setter_callback=self.set_toggle_mute) if FEATURE_VOLUME_STEP in feature_list: television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) self.chars[FEATURE_VOLUME_STEP] = television_speaker.\ configure_char( - CHAR_VOLUME_SELECTOR, - setter_callback=self.set_volume_step) + CHAR_VOLUME_SELECTOR, + setter_callback=self.set_volume_step) if FEATURE_SELECT_SOURCE in feature_list: self.chars[FEATURE_SELECT_SOURCE] \ = television.configure_char( - CHAR_ACTIVE_IDENTIFIER, - setter_callback=self.set_input_source) + CHAR_ACTIVE_IDENTIFIER, + setter_callback=self.set_input_source) self.sources = self.hass.states.get( self.entity_id).attributes.get('source_list') if self.sources: for index, source in enumerate(self.sources): input_service = self.add_preload_service( - SERV_INPUT_SOURCE, - [ - CHAR_IDENTIFIER, - CHAR_NAME - ]) + SERV_INPUT_SOURCE, [ + CHAR_IDENTIFIER, + CHAR_NAME + ]) input_service.configure_char( CHAR_CONFIGURED_NAME, value=source) @@ -155,9 +153,9 @@ def __init__(self, *args): _LOGGER.debug('%s: Added source %s.', self.entity_id, source) else: - _LOGGER.warn('%s: Source list empty when setting up sources. Please check \ + _LOGGER.warning('%s: Source list empty when setting up sources. Please check \ to make sure your media_player is turned on.', - self.entity_id) + self.entity_id) self.set_primary_service(television) return @@ -305,13 +303,13 @@ def update_state(self, new_state): self._flag[FEATURE_TOGGLE_MUTE] = False if self.chars[FEATURE_SELECT_SOURCE]: - sourceName = new_state.attributes.get(ATTR_INPUT_SOURCE) + source_name = new_state.attributes.get(ATTR_INPUT_SOURCE) if self.sources and not self._flag[FEATURE_SELECT_SOURCE]: _LOGGER.debug( - '%s: Set current state for "select_source" to %s', - self.entity_id, sourceName) - if sourceName in self.sources: - index = self.sources.index(sourceName) + '%s: Set current state for "select_source" to %s', + self.entity_id, source_name) + if source_name in self.sources: + index = self.sources.index(source_name) self.chars[FEATURE_SELECT_SOURCE].set_value(index) else: self.chars[FEATURE_SELECT_SOURCE].set_value(0) From d75782e7e15d6cc53c91a50da5a46ee4e5a04758 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 10 Apr 2019 23:42:08 -0400 Subject: [PATCH 16/77] updated missing dep location --- homeassistant/components/homekit/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/manifest.json b/homeassistant/components/homekit/manifest.json index fd781f206d1609..e4aabfeb6cd958 100644 --- a/homeassistant/components/homekit/manifest.json +++ b/homeassistant/components/homekit/manifest.json @@ -3,7 +3,7 @@ "name": "Homekit", "documentation": "https://www.home-assistant.io/components/homekit", "requirements": [ - "HAP-python==2.4.2" + "HAP-python==2.5.0" ], "dependencies": [], "codeowners": [ From abf3bbbdaeb6a0e6754a8a4bddc11e2318212ee8 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Thu, 11 Apr 2019 01:05:30 -0400 Subject: [PATCH 17/77] fixed a test --- tests/components/homekit/test_util.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index dc661fc309d97f..e718470c7d72d9 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -69,9 +69,7 @@ def test_validate_entity_config(): {'media_player.demo': {CONF_FEATURE_LIST: {FEATURE_ON_OFF: {}, FEATURE_PLAY_PAUSE: {}}}} - assert vec({'media_player.demo': {}}) == \ - {'media_player.demo': {CONF_TYPE: TYPE_SWITCH}} - assert vec({'media_player.demo': {}}) == \ + assert vec({'media_player.demo': {CONF_TYPE: TYPE_SWITCH}}) == \ {'media_player.demo': {CONF_TYPE: TYPE_SWITCH}} assert vec({'media_player.demo': {CONF_TYPE: TYPE_TELEVISION}}) == \ {'media_player.demo': {CONF_TYPE: TYPE_TELEVISION}} From fe0348603ab88f7111dc12782ec6dbc0ef014e36 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 17 Apr 2019 00:30:55 -0400 Subject: [PATCH 18/77] fixed lint & tests --- .../homekit/test_type_media_players.py | 6 +++--- tests/components/homekit/test_util.py | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 00a95140014f41..fbab23643403f6 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -137,9 +137,9 @@ async def test_media_player_set_state(hass, hk_driver, events): async def test_media_player_television_set_state(hass, hk_driver, events): """Test if television accessory and HA are updated accordingly.""" config = {CONF_TYPE: TYPE_TELEVISION, CONF_FEATURE_LIST: { - FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, - FEATURE_SELECT_SOURCE: None, FEATURE_TOGGLE_MUTE: None, - FEATURE_VOLUME_STEP: None}} + FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, + FEATURE_SELECT_SOURCE: None, FEATURE_TOGGLE_MUTE: None, + FEATURE_VOLUME_STEP: None}} entity_id = 'media_player.television' hass.states.async_set(entity_id, None, {ATTR_SUPPORTED_FEATURES: 20873, diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index e718470c7d72d9..f4b680638d86e7 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -32,10 +32,10 @@ def test_validate_entity_config(): {'demo.test': 'test'}, {'demo.test': [1, 2]}, {'demo.test': None}, {'demo.test': {CONF_NAME: None}}, {'media_player.test': {CONF_FEATURE_LIST: [ - {CONF_FEATURE: 'invalid_feature'}]}}, + {CONF_FEATURE: 'invalid_feature'}]}}, {'media_player.test': {CONF_FEATURE_LIST: [ - {CONF_FEATURE: FEATURE_ON_OFF}, - {CONF_FEATURE: FEATURE_ON_OFF}]}}, + {CONF_FEATURE: FEATURE_ON_OFF}, + {CONF_FEATURE: FEATURE_ON_OFF}]}}, {'media_player.test': {CONF_TYPE: 'invalid_type'}}, {'switch.test': {CONF_TYPE: 'invalid_type'}}] @@ -62,17 +62,17 @@ def test_validate_entity_config(): {'lock.demo': {ATTR_CODE: '1234'}} assert vec({'media_player.demo': {}}) == \ - {'media_player.demo': {CONF_FEATURE_LIST: {}}} + {'media_player.demo': {CONF_TYPE: TYPE_SWITCH, CONF_FEATURE_LIST: {}}} config = {CONF_FEATURE_LIST: [{CONF_FEATURE: FEATURE_ON_OFF}, {CONF_FEATURE: FEATURE_PLAY_PAUSE}]} assert vec({'media_player.demo': config}) == \ - {'media_player.demo': {CONF_FEATURE_LIST: + {'media_player.demo': {CONF_TYPE: TYPE_SWITCH, CONF_FEATURE_LIST: {FEATURE_ON_OFF: {}, FEATURE_PLAY_PAUSE: {}}}} - - assert vec({'media_player.demo': {CONF_TYPE: TYPE_SWITCH}}) == \ - {'media_player.demo': {CONF_TYPE: TYPE_SWITCH}} + assert vec({'media_player.demo': {}}) == \ + {'media_player.demo': {CONF_TYPE: TYPE_SWITCH, CONF_FEATURE_LIST: {}}} assert vec({'media_player.demo': {CONF_TYPE: TYPE_TELEVISION}}) == \ - {'media_player.demo': {CONF_TYPE: TYPE_TELEVISION}} + {'media_player.demo': {CONF_TYPE: TYPE_TELEVISION, + CONF_FEATURE_LIST: {}}} assert vec({'switch.demo': {CONF_TYPE: TYPE_FAUCET}}) == \ {'switch.demo': {CONF_TYPE: TYPE_FAUCET}} From 3f43ebe50aa4b74c1d07a4e368e4da06a6de8dbf Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 09:49:49 -0400 Subject: [PATCH 19/77] fix typo --- homeassistant/components/homekit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index f524455fedeaf6..fb7ecc074a269f 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -99,7 +99,7 @@ def handle_homekit_service_start(service): def get_accessory(hass, driver, state, aid, config): """Take state and return an accessory object if supported.""" if not aid: - _LOGGER.warning('The entitiy "%s" is not supported, since it ' + _LOGGER.warning('The entity "%s" is not supported, since it ' 'generates an invalid aid, please change it.', state.entity_id) return None From 66bea25b85142e845deda0236eccb560ecc0d445 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 09:55:24 -0400 Subject: [PATCH 20/77] moved telvisionmediaplayer to own accessory type --- .../components/homekit/type_media_players.py | 300 +++++++++++------- 1 file changed, 182 insertions(+), 118 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index f359bf99b85c61..8f96383cd82025 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -6,8 +6,8 @@ from homeassistant.components.media_player import ( ATTR_INPUT_SOURCE, ATTR_MEDIA_VOLUME_MUTED, SERVICE_SELECT_SOURCE, DOMAIN) from homeassistant.const import ( - ATTR_ENTITY_ID, CONF_TYPE, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, - SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, + ATTR_ENTITY_ID, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, + SERVICE_MEDIA_PLAY_PAUSE, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN, STATE_OFF, STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN) @@ -17,22 +17,15 @@ from .const import ( CHAR_ACTIVE, CHAR_ACTIVE_IDENTIFIER, CHAR_CONFIGURED_NAME, CHAR_CURRENT_VISIBILITY_STATE, CHAR_IDENTIFIER, CHAR_INPUT_SOURCE_TYPE, - CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_ON, CHAR_SLEEP_DISCOVER_MODE, + CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_SLEEP_DISCOVER_MODE, CHAR_MUTE, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, - FEATURE_VOLUME_STEP, SERV_SWITCH, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, - SERV_INPUT_SOURCE, TYPE_SWITCH, TYPE_TELEVISION) + FEATURE_PLAY_STOP FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, + FEATURE_VOLUME_STEP, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, + SERV_INPUT_SOURCE) _LOGGER = logging.getLogger(__name__) -MODE_FRIENDLY_NAME = { - FEATURE_ON_OFF: 'Power', - FEATURE_PLAY_PAUSE: 'Play/Pause', - FEATURE_PLAY_STOP: 'Play/Stop', - FEATURE_TOGGLE_MUTE: 'Mute', -} - REMOTE_KEYS = { 0: "Rewind", 1: "FastForward", @@ -53,6 +46,14 @@ } +MODE_FRIENDLY_NAME = { + FEATURE_ON_OFF: 'Power', + FEATURE_PLAY_PAUSE: 'Play/Pause', + FEATURE_PLAY_STOP: 'Play/Stop', + FEATURE_TOGGLE_MUTE: 'Mute', +} + + @TYPES.register('MediaPlayer') class MediaPlayer(HomeAccessory): """Generate a Media Player accessory.""" @@ -61,111 +62,17 @@ def __init__(self, *args): """Initialize a Switch accessory object.""" super().__init__(*args, category=CATEGORY_SWITCH) self._flag = {FEATURE_ON_OFF: False, FEATURE_PLAY_PAUSE: False, - FEATURE_PLAY_STOP: False, FEATURE_TOGGLE_MUTE: False, - FEATURE_SELECT_SOURCE: False} + FEATURE_PLAY_STOP: False, FEATURE_TOGGLE_MUTE: False} self.chars = {FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, - FEATURE_PLAY_STOP: None, FEATURE_TOGGLE_MUTE: None, - FEATURE_SELECT_SOURCE: None, FEATURE_VOLUME_STEP: None} + FEATURE_PLAY_STOP: None, FEATURE_TOGGLE_MUTE: None} feature_list = self.config[CONF_FEATURE_LIST] - self.sources = [] - - a_type = self.config.get(CONF_TYPE, TYPE_SWITCH) - - if a_type == TYPE_TELEVISION and FEATURE_ON_OFF in feature_list: - - self.category = CATEGORY_TELEVISION - television = self.add_preload_service(SERV_TELEVISION, - [ - CHAR_CONFIGURED_NAME, - CHAR_REMOTE_KEY - ]) - television.configure_char(CHAR_CONFIGURED_NAME, - value=self.display_name) - television.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) - self.chars[FEATURE_ON_OFF] = television.configure_char( - CHAR_ACTIVE, setter_callback=self.set_on_off) - - if FEATURE_PLAY_PAUSE in feature_list: - self.chars[FEATURE_PLAY_PAUSE] \ - = television.configure_char( - CHAR_REMOTE_KEY, - setter_callback=self.set_remote_key) - - if FEATURE_TOGGLE_MUTE in feature_list: - - television_speaker = self.add_preload_service( - SERV_TELEVISION_SPEAKER, [ - CHAR_NAME, CHAR_ACTIVE, - CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR, - CHAR_VOLUME - ]) - television.add_linked_service(television_speaker) - - name = '{} {}'.format(self.display_name, 'Volume') - television_speaker.configure_char(CHAR_NAME, value=name) - television_speaker.configure_char(CHAR_ACTIVE, value=1) - - self.chars[FEATURE_TOGGLE_MUTE] \ - = television_speaker.configure_char( - CHAR_MUTE, value=False, - setter_callback=self.set_toggle_mute) - - if FEATURE_VOLUME_STEP in feature_list: - television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, - value=1) - self.chars[FEATURE_VOLUME_STEP] = television_speaker.\ - configure_char( - CHAR_VOLUME_SELECTOR, - setter_callback=self.set_volume_step) - - if FEATURE_SELECT_SOURCE in feature_list: - - self.chars[FEATURE_SELECT_SOURCE] \ - = television.configure_char( - CHAR_ACTIVE_IDENTIFIER, - setter_callback=self.set_input_source) - - self.sources = self.hass.states.get( - self.entity_id).attributes.get('source_list') - if self.sources: - for index, source in enumerate(self.sources): - input_service = self.add_preload_service( - SERV_INPUT_SOURCE, [ - CHAR_IDENTIFIER, - CHAR_NAME - ]) - - input_service.configure_char( - CHAR_CONFIGURED_NAME, value=source) - input_service.configure_char(CHAR_NAME, value=source) - input_service.configure_char( - CHAR_IDENTIFIER, value=index) - input_service.configure_char( - CHAR_IS_CONFIGURED, value=True) - input_type = 3 if "hdmi" in source.lower() else 0 - input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, - value=input_type) - input_service.configure_char( - CHAR_CURRENT_VISIBILITY_STATE, value=False) - television.add_linked_service(input_service) - _LOGGER.debug('%s: Added source %s.', self.entity_id, - source) - else: - _LOGGER.warning('%s: Source list empty when setting up sources. Please check \ - to make sure your media_player is turned on.', - self.entity_id) - - self.set_primary_service(television) - return - if FEATURE_ON_OFF in feature_list: name = self.generate_service_name(FEATURE_ON_OFF) serv_on_off = self.add_preload_service(SERV_SWITCH, CHAR_NAME) serv_on_off.configure_char(CHAR_NAME, value=name) self.chars[FEATURE_ON_OFF] = serv_on_off.configure_char( - CHAR_ON, setter_callback=self.set_on_off) + CHAR_ON, value=False, setter_callback=self.set_on_off) if FEATURE_PLAY_PAUSE in feature_list: name = self.generate_service_name(FEATURE_PLAY_PAUSE) @@ -228,6 +135,171 @@ def set_toggle_mute(self, value): ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) + def update_state(self, new_state): + """Update switch state after state changed.""" + current_state = new_state.state + + if self.chars[FEATURE_ON_OFF]: + hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') + if not self._flag[FEATURE_ON_OFF]: + _LOGGER.debug('%s: Set current state for "on_off" to %s', + self.entity_id, hk_state) + self.chars[FEATURE_ON_OFF].set_value(hk_state) + self._flag[FEATURE_ON_OFF] = False + + if self.chars[FEATURE_PLAY_PAUSE]: + hk_state = current_state == STATE_PLAYING + if not self._flag[FEATURE_PLAY_PAUSE]: + _LOGGER.debug('%s: Set current state for "play_pause" to %s', + self.entity_id, hk_state) + self.chars[FEATURE_PLAY_PAUSE].set_value(hk_state) + self._flag[FEATURE_PLAY_PAUSE] = False + + if self.chars[FEATURE_PLAY_STOP]: + hk_state = current_state == STATE_PLAYING + if not self._flag[FEATURE_PLAY_STOP]: + _LOGGER.debug('%s: Set current state for "play_stop" to %s', + self.entity_id, hk_state) + self.chars[FEATURE_PLAY_STOP].set_value(hk_state) + self._flag[FEATURE_PLAY_STOP] = False + + if self.chars[FEATURE_TOGGLE_MUTE]: + current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) + if not self._flag[FEATURE_TOGGLE_MUTE]: + _LOGGER.debug('%s: Set current state for "toggle_mute" to %s', + self.entity_id, current_state) + self.chars[FEATURE_TOGGLE_MUTE].set_value(current_state) + self._flag[FEATURE_TOGGLE_MUTE] = False + + +@TYPES.register('TelevisionMediaPlayer') +class TelevisionMediaPlayer(HomeAccessory): + """Generate a Television Media Player accessory.""" + + def __init__(self, *args): + """Initialize a Switch accessory object.""" + super().__init__(*args, category=CATEGORY_SWITCH) + self._flag = {FEATURE_ON_OFF: False, FEATURE_PLAY_PAUSE: False, + FEATURE_TOGGLE_MUTE: False, FEATURE_SELECT_SOURCE: False} + self.chars = {FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, + FEATURE_TOGGLE_MUTE: None, FEATURE_SELECT_SOURCE: None, + FEATURE_VOLUME_STEP: None} + feature_list = self.config[CONF_FEATURE_LIST] + + self.sources = [] + + self.category = CATEGORY_TELEVISION + television = self.add_preload_service(SERV_TELEVISION, + [ + CHAR_CONFIGURED_NAME, + CHAR_REMOTE_KEY + ]) + television.configure_char(CHAR_CONFIGURED_NAME, + value=self.display_name) + television.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) + self.chars[FEATURE_ON_OFF] = television.configure_char( + CHAR_ACTIVE, setter_callback=self.set_on_off) + + if FEATURE_PLAY_PAUSE in feature_list: + self.chars[FEATURE_PLAY_PAUSE] \ + = television.configure_char( + CHAR_REMOTE_KEY, + setter_callback=self.set_remote_key) + + if FEATURE_TOGGLE_MUTE in feature_list: + + television_speaker = self.add_preload_service( + SERV_TELEVISION_SPEAKER, [ + CHAR_NAME, CHAR_ACTIVE, + CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR, + CHAR_VOLUME + ]) + television.add_linked_service(television_speaker) + + name = '{} {}'.format(self.display_name, 'Volume') + television_speaker.configure_char(CHAR_NAME, value=name) + television_speaker.configure_char(CHAR_ACTIVE, value=1) + + self.chars[FEATURE_TOGGLE_MUTE] \ + = television_speaker.configure_char( + CHAR_MUTE, value=False, + setter_callback=self.set_toggle_mute) + + if FEATURE_VOLUME_STEP in feature_list: + television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, + value=1) + self.chars[FEATURE_VOLUME_STEP] = television_speaker.\ + configure_char( + CHAR_VOLUME_SELECTOR, + setter_callback=self.set_volume_step) + + if FEATURE_SELECT_SOURCE in feature_list: + + self.chars[FEATURE_SELECT_SOURCE] \ + = television.configure_char( + CHAR_ACTIVE_IDENTIFIER, + setter_callback=self.set_input_source) + + self.sources = self.hass.states.get( + self.entity_id).attributes.get('source_list') + if self.sources: + for index, source in enumerate(self.sources): + input_service = self.add_preload_service( + SERV_INPUT_SOURCE, [ + CHAR_IDENTIFIER, + CHAR_NAME + ]) + + input_service.configure_char( + CHAR_CONFIGURED_NAME, value=source) + input_service.configure_char(CHAR_NAME, value=source) + input_service.configure_char( + CHAR_IDENTIFIER, value=index) + input_service.configure_char( + CHAR_IS_CONFIGURED, value=True) + input_type = 3 if "hdmi" in source.lower() else 0 + input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, + value=input_type) + input_service.configure_char( + CHAR_CURRENT_VISIBILITY_STATE, value=False) + television.add_linked_service(input_service) + _LOGGER.debug('%s: Added source %s.', self.entity_id, + source) + else: + _LOGGER.warning('%s: Source list empty when setting up sources. Please check \ + to make sure your media_player is turned on.', + self.entity_id) + + self.set_primary_service(television) + + def set_on_off(self, value): + """Move switch state to value if call came from HomeKit.""" + _LOGGER.debug('%s: Set switch state for "on_off" to %s', + self.entity_id, value) + self._flag[FEATURE_ON_OFF] = True + service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF + params = {ATTR_ENTITY_ID: self.entity_id} + self.call_service(DOMAIN, service, params) + + def set_play_pause(self, value): + """Move switch state to value if call came from HomeKit.""" + _LOGGER.debug('%s: Set switch state for "play_pause" to %s', + self.entity_id, value) + self._flag[FEATURE_PLAY_PAUSE] = True + service = SERVICE_MEDIA_PLAY if value else SERVICE_MEDIA_PAUSE + params = {ATTR_ENTITY_ID: self.entity_id} + self.call_service(DOMAIN, service, params) + + def set_toggle_mute(self, value): + """Move switch state to value if call came from HomeKit.""" + _LOGGER.debug('%s: Set switch state for "toggle_mute" to %s', + self.entity_id, value) + self._flag[FEATURE_TOGGLE_MUTE] = True + params = {ATTR_ENTITY_ID: self.entity_id, + ATTR_MEDIA_VOLUME_MUTED: value} + self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) + def set_volume_step(self, value): """Send volume step value if call came from HomeKit.""" _LOGGER.debug('%s: Step tv_volume for "tv_volume" to %s', @@ -286,14 +358,6 @@ def update_state(self, new_state): self.chars[FEATURE_PLAY_PAUSE].set_value(hk_state) self._flag[FEATURE_PLAY_PAUSE] = False - if self.chars[FEATURE_PLAY_STOP]: - hk_state = current_state == STATE_PLAYING - if not self._flag[FEATURE_PLAY_STOP]: - _LOGGER.debug('%s: Set current state for "play_stop" to %s', - self.entity_id, hk_state) - self.chars[FEATURE_PLAY_STOP].set_value(hk_state) - self._flag[FEATURE_PLAY_STOP] = False - if self.chars[FEATURE_TOGGLE_MUTE]: current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) if not self._flag[FEATURE_TOGGLE_MUTE]: From 2d6ed88ccfd345e6b75ffa2f484b5d13cb95f98d Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 09:55:42 -0400 Subject: [PATCH 21/77] map televisionmediaplayer --- homeassistant/components/homekit/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index fb7ecc074a269f..db9126d5356a53 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -138,10 +138,15 @@ def get_accessory(hass, driver, state, aid, config): a_type = 'Lock' elif state.domain == 'media_player': + device_class = state.attributes.get(ATTR_DEVICE_CLASS) feature_list = config.get(CONF_FEATURE_LIST) + if feature_list and \ validate_media_player_features(state, feature_list): - a_type = 'MediaPlayer' + if device_class == 'television': + a_type = 'TelevisionMediaPlayer' + else: + a_type = 'MediaPlayer' elif state.domain == 'sensor': device_class = state.attributes.get(ATTR_DEVICE_CLASS) From c0aa9dc144b98822cf6f7dc3e4914f557adf8a04 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 10:25:07 -0400 Subject: [PATCH 22/77] removed conf_type for media players --- homeassistant/components/homekit/__init__.py | 2 +- homeassistant/components/homekit/const.py | 1 - homeassistant/components/homekit/type_media_players.py | 10 +++++----- homeassistant/components/homekit/util.py | 4 +--- tests/components/homekit/test_type_media_players.py | 2 +- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index db9126d5356a53..fbca8559754573 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -143,7 +143,7 @@ def get_accessory(hass, driver, state, aid, config): if feature_list and \ validate_media_player_features(state, feature_list): - if device_class == 'television': + if device_class == 'tv': a_type = 'TelevisionMediaPlayer' else: a_type = 'MediaPlayer' diff --git a/homeassistant/components/homekit/const.py b/homeassistant/components/homekit/const.py index 24ebe83e929feb..1eb501ba6375b1 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -49,7 +49,6 @@ TYPE_SHOWER = 'shower' TYPE_SPRINKLER = 'sprinkler' TYPE_SWITCH = 'switch' -TYPE_TELEVISION = 'television' TYPE_VALVE = 'valve' # #### Services #### diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 8f96383cd82025..24fdb1da66ab66 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -18,11 +18,11 @@ CHAR_ACTIVE, CHAR_ACTIVE_IDENTIFIER, CHAR_CONFIGURED_NAME, CHAR_CURRENT_VISIBILITY_STATE, CHAR_IDENTIFIER, CHAR_INPUT_SOURCE_TYPE, CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_SLEEP_DISCOVER_MODE, - CHAR_MUTE, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, - CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, - FEATURE_VOLUME_STEP, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, - SERV_INPUT_SOURCE) + CHAR_MUTE, CHAR_ON, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR, CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, + FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, + FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP, SERV_SWITCH, SERV_TELEVISION, + SERV_TELEVISION_SPEAKER, SERV_INPUT_SOURCE) _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index 6baa65abfc2fc6..c3c938595ba7e6 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -16,7 +16,7 @@ FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP, FEATURE_SELECT_SOURCE, HOMEKIT_NOTIFY_ID, TYPE_FAUCET, TYPE_OUTLET, TYPE_SHOWER, - TYPE_SPRINKLER, TYPE_SWITCH, TYPE_TELEVISION, TYPE_VALVE) + TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) _LOGGER = logging.getLogger(__name__) @@ -28,8 +28,6 @@ FEATURE_SCHEMA = BASIC_INFO_SCHEMA.extend({ vol.Optional(CONF_FEATURE_LIST, default=None): cv.ensure_list, - vol.Optional(CONF_TYPE, default=TYPE_SWITCH): vol.All( - cv.string, vol.In((TYPE_SWITCH, TYPE_TELEVISION))), }) CODE_SCHEMA = BASIC_INFO_SCHEMA.extend({ diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index fbab23643403f6..8f553dc47c839e 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -136,7 +136,7 @@ async def test_media_player_set_state(hass, hk_driver, events): async def test_media_player_television_set_state(hass, hk_driver, events): """Test if television accessory and HA are updated accordingly.""" - config = {CONF_TYPE: TYPE_TELEVISION, CONF_FEATURE_LIST: { + config = {CONF_FEATURE_LIST: { FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, FEATURE_SELECT_SOURCE: None, FEATURE_TOGGLE_MUTE: None, FEATURE_VOLUME_STEP: None}} From d3317fabd84080bf6ebbc1d2900a4adc55693cb7 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 10:25:17 -0400 Subject: [PATCH 23/77] fixed tests --- .../components/homekit/type_media_players.py | 2 +- .../components/homekit/test_type_media_players.py | 15 +++++++++------ tests/components/homekit/test_util.py | 6 +----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 24fdb1da66ab66..bd100debc9b564 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -7,7 +7,7 @@ ATTR_INPUT_SOURCE, ATTR_MEDIA_VOLUME_MUTED, SERVICE_SELECT_SOURCE, DOMAIN) from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, - SERVICE_MEDIA_PLAY_PAUSE, SERVICE_TURN_OFF, + SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN, STATE_OFF, STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 8f553dc47c839e..976d6a86eabded 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -3,14 +3,15 @@ from homeassistant.components.homekit.const import ( ATTR_VALUE, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, - FEATURE_VOLUME_STEP, TYPE_TELEVISION) -from homeassistant.components.homekit.type_media_players import MediaPlayer + FEATURE_VOLUME_STEP) +from homeassistant.components.homekit.type_media_players import ( + MediaPlayer, TelevisionMediaPlayer) from homeassistant.components.media_player.const import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, DOMAIN) from homeassistant.const import ( - ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_TYPE, STATE_IDLE, STATE_OFF, - STATE_ON, STATE_PAUSED, STATE_PLAYING) + ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_TYPE, + STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) from tests.common import async_mock_service @@ -142,14 +143,16 @@ async def test_media_player_television_set_state(hass, hk_driver, events): FEATURE_VOLUME_STEP: None}} entity_id = 'media_player.television' - hass.states.async_set(entity_id, None, {ATTR_SUPPORTED_FEATURES: 20873, + hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: 'tv', + ATTR_SUPPORTED_FEATURES: 20873, ATTR_MEDIA_VOLUME_MUTED: False, ATTR_INPUT_SOURCE_LIST: ['HDMI 1', 'HDMI 2', 'HDMI 3', 'HDMI 4'] }) await hass.async_block_till_done() - acc = MediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, config) + acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, + config) await hass.async_add_job(acc.run) assert acc.aid == 2 diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index f4b680638d86e7..ca34e44d1d9e2c 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -5,8 +5,7 @@ from homeassistant.components.homekit.const import ( CONF_FEATURE, CONF_FEATURE_LIST, CONF_LINKED_BATTERY_SENSOR, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, HOMEKIT_NOTIFY_ID, TYPE_FAUCET, - TYPE_OUTLET, TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_TELEVISION, - TYPE_VALVE) + TYPE_OUTLET, TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) from homeassistant.components.homekit.util import ( HomeKitSpeedMapping, SpeedRange, convert_to_float, density_to_air_quality, dismiss_setup_message, show_setup_message, temperature_to_homekit, @@ -70,9 +69,6 @@ def test_validate_entity_config(): {FEATURE_ON_OFF: {}, FEATURE_PLAY_PAUSE: {}}}} assert vec({'media_player.demo': {}}) == \ {'media_player.demo': {CONF_TYPE: TYPE_SWITCH, CONF_FEATURE_LIST: {}}} - assert vec({'media_player.demo': {CONF_TYPE: TYPE_TELEVISION}}) == \ - {'media_player.demo': {CONF_TYPE: TYPE_TELEVISION, - CONF_FEATURE_LIST: {}}} assert vec({'switch.demo': {CONF_TYPE: TYPE_FAUCET}}) == \ {'switch.demo': {CONF_TYPE: TYPE_FAUCET}} From 9e8ce161965e961256fbf71d724bb157fcb997a6 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 10:32:37 -0400 Subject: [PATCH 24/77] fixed lint --- tests/components/homekit/test_type_media_players.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 976d6a86eabded..b5fee161fbfa3d 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -10,8 +10,8 @@ ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, DOMAIN) from homeassistant.const import ( - ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_TYPE, - STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) + ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, STATE_IDLE, + STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) from tests.common import async_mock_service From a22a1f92e50b65d790db37dde955bd09ef9e2982 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 14:22:56 -0400 Subject: [PATCH 25/77] changed device class to const --- homeassistant/components/homekit/__init__.py | 12 ++++++------ homeassistant/const.py | 4 ++++ tests/components/homekit/test_type_media_players.py | 8 ++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index fbca8559754573..43096e7ce78135 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -9,7 +9,7 @@ from homeassistant.const import ( ATTR_DEVICE_CLASS, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, CONF_IP_ADDRESS, CONF_NAME, CONF_PORT, CONF_TYPE, DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TV, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, TEMP_CELSIUS, TEMP_FAHRENHEIT) import homeassistant.helpers.config_validation as cv @@ -141,11 +141,11 @@ def get_accessory(hass, driver, state, aid, config): device_class = state.attributes.get(ATTR_DEVICE_CLASS) feature_list = config.get(CONF_FEATURE_LIST) - if feature_list and \ - validate_media_player_features(state, feature_list): - if device_class == 'tv': - a_type = 'TelevisionMediaPlayer' - else: + if device_class == DEVICE_CLASS_TV: + a_type = 'TelevisionMediaPlayer' + else: + if feature_list and \ + validate_media_player_features(state, feature_list): a_type = 'MediaPlayer' elif state.domain == 'sensor': diff --git a/homeassistant/const.py b/homeassistant/const.py index 9176c1b8939240..a15dc1e40f509e 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -185,6 +185,7 @@ DEVICE_CLASS_TIMESTAMP = 'timestamp' DEVICE_CLASS_PRESSURE = 'pressure' DEVICE_CLASS_POWER = 'power' +DEVICE_CLASS_TV = 'tv' # #### STATES #### STATE_ON = 'on' @@ -318,6 +319,9 @@ # Temperature attribute ATTR_TEMPERATURE = 'temperature' +# Device classes +DEVICE_CLASS_BATTERY + # #### UNITS OF MEASUREMENT #### # Power units POWER_WATT = 'W' diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index b5fee161fbfa3d..767e468809fe64 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -1,9 +1,9 @@ """Test different accessory types: Media Players.""" from homeassistant.components.homekit.const import ( - ATTR_VALUE, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, FEATURE_TOGGLE_MUTE, - FEATURE_VOLUME_STEP) + ATTR_VALUE, CONF_FEATURE_LIST, DEVICE_CLASS_TV, FEATURE_ON_OFF, + FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, + FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP) from homeassistant.components.homekit.type_media_players import ( MediaPlayer, TelevisionMediaPlayer) from homeassistant.components.media_player.const import ( @@ -143,7 +143,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): FEATURE_VOLUME_STEP: None}} entity_id = 'media_player.television' - hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: 'tv', + hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, ATTR_SUPPORTED_FEATURES: 20873, ATTR_MEDIA_VOLUME_MUTED: False, ATTR_INPUT_SOURCE_LIST: From a80ae08d3fb9545252573b1bb27302afb3d4d02a Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 22:32:16 -0400 Subject: [PATCH 26/77] dont add already required characteristic --- homeassistant/components/homekit/type_media_players.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index bd100debc9b564..60ce41b51f4568 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -190,10 +190,7 @@ def __init__(self, *args): self.category = CATEGORY_TELEVISION television = self.add_preload_service(SERV_TELEVISION, - [ - CHAR_CONFIGURED_NAME, - CHAR_REMOTE_KEY - ]) + [CHAR_REMOTE_KEY]) television.configure_char(CHAR_CONFIGURED_NAME, value=self.display_name) television.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) From 054dcd70ad05efb05ab9280218f3fb3f522c4f3d Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 22:39:50 -0400 Subject: [PATCH 27/77] remove unused feature list --- .../components/homekit/type_media_players.py | 117 +++++++----------- 1 file changed, 46 insertions(+), 71 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 60ce41b51f4568..2b6989db382efb 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -184,7 +184,6 @@ def __init__(self, *args): self.chars = {FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, FEATURE_TOGGLE_MUTE: None, FEATURE_SELECT_SOURCE: None, FEATURE_VOLUME_STEP: None} - feature_list = self.config[CONF_FEATURE_LIST] self.sources = [] @@ -197,76 +196,52 @@ def __init__(self, *args): self.chars[FEATURE_ON_OFF] = television.configure_char( CHAR_ACTIVE, setter_callback=self.set_on_off) - if FEATURE_PLAY_PAUSE in feature_list: - self.chars[FEATURE_PLAY_PAUSE] \ - = television.configure_char( - CHAR_REMOTE_KEY, - setter_callback=self.set_remote_key) - - if FEATURE_TOGGLE_MUTE in feature_list: - - television_speaker = self.add_preload_service( - SERV_TELEVISION_SPEAKER, [ - CHAR_NAME, CHAR_ACTIVE, - CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR, - CHAR_VOLUME - ]) - television.add_linked_service(television_speaker) - - name = '{} {}'.format(self.display_name, 'Volume') - television_speaker.configure_char(CHAR_NAME, value=name) - television_speaker.configure_char(CHAR_ACTIVE, value=1) - - self.chars[FEATURE_TOGGLE_MUTE] \ - = television_speaker.configure_char( - CHAR_MUTE, value=False, - setter_callback=self.set_toggle_mute) - - if FEATURE_VOLUME_STEP in feature_list: - television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, - value=1) - self.chars[FEATURE_VOLUME_STEP] = television_speaker.\ - configure_char( - CHAR_VOLUME_SELECTOR, - setter_callback=self.set_volume_step) - - if FEATURE_SELECT_SOURCE in feature_list: - - self.chars[FEATURE_SELECT_SOURCE] \ - = television.configure_char( - CHAR_ACTIVE_IDENTIFIER, - setter_callback=self.set_input_source) - - self.sources = self.hass.states.get( - self.entity_id).attributes.get('source_list') - if self.sources: - for index, source in enumerate(self.sources): - input_service = self.add_preload_service( - SERV_INPUT_SOURCE, [ - CHAR_IDENTIFIER, - CHAR_NAME - ]) - - input_service.configure_char( - CHAR_CONFIGURED_NAME, value=source) - input_service.configure_char(CHAR_NAME, value=source) - input_service.configure_char( - CHAR_IDENTIFIER, value=index) - input_service.configure_char( - CHAR_IS_CONFIGURED, value=True) - input_type = 3 if "hdmi" in source.lower() else 0 - input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, - value=input_type) - input_service.configure_char( - CHAR_CURRENT_VISIBILITY_STATE, value=False) - television.add_linked_service(input_service) - _LOGGER.debug('%s: Added source %s.', self.entity_id, - source) - else: - _LOGGER.warning('%s: Source list empty when setting up sources. Please check \ - to make sure your media_player is turned on.', - self.entity_id) + self.chars[FEATURE_PLAY_PAUSE] = television.configure_char( + CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) + + television_speaker = self.add_preload_service( + SERV_TELEVISION_SPEAKER, [CHAR_NAME, CHAR_ACTIVE, + CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR, CHAR_VOLUME]) + television.add_linked_service(television_speaker) + + name = '{} {}'.format(self.display_name, 'Volume') + television_speaker.configure_char(CHAR_NAME, value=name) + television_speaker.configure_char(CHAR_ACTIVE, value=1) + + self.chars[FEATURE_TOGGLE_MUTE] = television_speaker.configure_char( + CHAR_MUTE, value=False, + setter_callback=self.set_toggle_mute) + + television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) + self.chars[FEATURE_VOLUME_STEP] = television_speaker.configure_char( + CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) + + self.chars[FEATURE_SELECT_SOURCE] = television.configure_char( + CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) + + self.sources = self.hass.states.get( + self.entity_id).attributes.get('source_list') + if self.sources: + for index, source in enumerate(self.sources): + input_service = self.add_preload_service(SERV_INPUT_SOURCE, [ + CHAR_IDENTIFIER, CHAR_NAME]) + + input_service.configure_char( + CHAR_CONFIGURED_NAME, value=source) + input_service.configure_char(CHAR_NAME, value=source) + input_service.configure_char( + CHAR_IDENTIFIER, value=index) + input_service.configure_char( + CHAR_IS_CONFIGURED, value=True) + input_type = 3 if "hdmi" in source.lower() else 0 + input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, + value=input_type) + input_service.configure_char( + CHAR_CURRENT_VISIBILITY_STATE, value=False) + television.add_linked_service(input_service) + _LOGGER.debug('%s: Added source %s.', self.entity_id, + source) self.set_primary_service(television) From 05dbdf06f830058863be58e0f474102fa0335eb5 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 22:43:50 -0400 Subject: [PATCH 28/77] more fixes --- .../components/homekit/type_media_players.py | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 2b6989db382efb..cc6a0a025ccfce 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -178,7 +178,7 @@ class TelevisionMediaPlayer(HomeAccessory): def __init__(self, *args): """Initialize a Switch accessory object.""" - super().__init__(*args, category=CATEGORY_SWITCH) + super().__init__(*args, category=CATEGORY_TELEVISION) self._flag = {FEATURE_ON_OFF: False, FEATURE_PLAY_PAUSE: False, FEATURE_TOGGLE_MUTE: False, FEATURE_SELECT_SOURCE: False} self.chars = {FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, @@ -187,37 +187,37 @@ def __init__(self, *args): self.sources = [] - self.category = CATEGORY_TELEVISION - television = self.add_preload_service(SERV_TELEVISION, - [CHAR_REMOTE_KEY]) - television.configure_char(CHAR_CONFIGURED_NAME, + serv_tv = self.add_preload_service(SERV_TELEVISION, + serv_tv[CHAR_REMOTE_KEY]) + self.set_primary_service(serv_tv) + serv_tv.configure_char(CHAR_CONFIGURED_NAME, value=self.display_name) - television.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) - self.chars[FEATURE_ON_OFF] = television.configure_char( + serv_tv.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) + self.chars[FEATURE_ON_OFF] = serv_tv.configure_char( CHAR_ACTIVE, setter_callback=self.set_on_off) - self.chars[FEATURE_PLAY_PAUSE] = television.configure_char( + self.chars[FEATURE_PLAY_PAUSE] = serv_tv.configure_char( CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) - television_speaker = self.add_preload_service( + serv_tv_speaker = self.add_preload_service( SERV_TELEVISION_SPEAKER, [CHAR_NAME, CHAR_ACTIVE, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, CHAR_VOLUME]) - television.add_linked_service(television_speaker) + serv_tv.add_linked_service(serv_tv_speaker) name = '{} {}'.format(self.display_name, 'Volume') - television_speaker.configure_char(CHAR_NAME, value=name) - television_speaker.configure_char(CHAR_ACTIVE, value=1) + serv_tv_speaker.configure_char(CHAR_NAME, value=name) + serv_tv_speaker.configure_char(CHAR_ACTIVE, value=1) - self.chars[FEATURE_TOGGLE_MUTE] = television_speaker.configure_char( + self.chars[FEATURE_TOGGLE_MUTE] = serv_tv_speaker.configure_char( CHAR_MUTE, value=False, setter_callback=self.set_toggle_mute) - television_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) - self.chars[FEATURE_VOLUME_STEP] = television_speaker.configure_char( + serv_tv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) + self.chars[FEATURE_VOLUME_STEP] = serv_tv_speaker.configure_char( CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) - self.chars[FEATURE_SELECT_SOURCE] = television.configure_char( + self.chars[FEATURE_SELECT_SOURCE] = serv_tv.configure_char( CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) self.sources = self.hass.states.get( @@ -239,12 +239,10 @@ def __init__(self, *args): value=input_type) input_service.configure_char( CHAR_CURRENT_VISIBILITY_STATE, value=False) - television.add_linked_service(input_service) + serv_tv.add_linked_service(input_service) _LOGGER.debug('%s: Added source %s.', self.entity_id, source) - self.set_primary_service(television) - def set_on_off(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "on_off" to %s', From c91e9353a63ac86f07245daafc78479f96632b12 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sun, 28 Apr 2019 22:52:17 -0400 Subject: [PATCH 29/77] more simplification --- .../components/homekit/type_media_players.py | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index cc6a0a025ccfce..8a1795e41684f3 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -179,25 +179,23 @@ class TelevisionMediaPlayer(HomeAccessory): def __init__(self, *args): """Initialize a Switch accessory object.""" super().__init__(*args, category=CATEGORY_TELEVISION) - self._flag = {FEATURE_ON_OFF: False, FEATURE_PLAY_PAUSE: False, - FEATURE_TOGGLE_MUTE: False, FEATURE_SELECT_SOURCE: False} - self.chars = {FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, - FEATURE_TOGGLE_MUTE: None, FEATURE_SELECT_SOURCE: None, - FEATURE_VOLUME_STEP: None} + self._flag = {FEATURE_ON_OFF: False, FEATURE_TOGGLE_MUTE: False, + FEATURE_SELECT_SOURCE: False} + self.chars = {FEATURE_ON_OFF: None, FEATURE_TOGGLE_MUTE: None, + FEATURE_SELECT_SOURCE: None, FEATURE_VOLUME_STEP: None} self.sources = [] - serv_tv = self.add_preload_service(SERV_TELEVISION, - serv_tv[CHAR_REMOTE_KEY]) + serv_tv = self.add_preload_service(SERV_TELEVISION, [CHAR_REMOTE_KEY]) self.set_primary_service(serv_tv) serv_tv.configure_char(CHAR_CONFIGURED_NAME, - value=self.display_name) + value=self.display_name) serv_tv.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) self.chars[FEATURE_ON_OFF] = serv_tv.configure_char( CHAR_ACTIVE, setter_callback=self.set_on_off) - self.chars[FEATURE_PLAY_PAUSE] = serv_tv.configure_char( - CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) + serv_tv.configure_char(CHAR_REMOTE_KEY, + setter_callback=self.set_remote_key) serv_tv_speaker = self.add_preload_service( SERV_TELEVISION_SPEAKER, [CHAR_NAME, CHAR_ACTIVE, @@ -220,8 +218,8 @@ def __init__(self, *args): self.chars[FEATURE_SELECT_SOURCE] = serv_tv.configure_char( CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) - self.sources = self.hass.states.get( - self.entity_id).attributes.get('source_list') + self.sources = self.hass.states.get(self.entity_id).attributes.get( + ATTR_INPUT_SOURCE) if self.sources: for index, source in enumerate(self.sources): input_service = self.add_preload_service(SERV_INPUT_SOURCE, [ @@ -312,22 +310,12 @@ def update_state(self, new_state): if self.chars[FEATURE_ON_OFF]: hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') if not self._flag[FEATURE_ON_OFF]: - if self.category is CATEGORY_TELEVISION: - hk_state = 1 if hk_state else 0 + hk_state = 1 if hk_state else 0 _LOGGER.debug('%s: Set current state for "on_off" to %s', self.entity_id, hk_state) self.chars[FEATURE_ON_OFF].set_value(hk_state) self._flag[FEATURE_ON_OFF] = False - if self.chars[FEATURE_PLAY_PAUSE]: - hk_state = current_state == STATE_PLAYING - if not self._flag[FEATURE_PLAY_PAUSE] and \ - not self.category == CATEGORY_TELEVISION: - _LOGGER.debug('%s: Set current state for "play_pause" to %s', - self.entity_id, hk_state) - self.chars[FEATURE_PLAY_PAUSE].set_value(hk_state) - self._flag[FEATURE_PLAY_PAUSE] = False - if self.chars[FEATURE_TOGGLE_MUTE]: current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) if not self._flag[FEATURE_TOGGLE_MUTE]: From 647810b919c6fb125b205e70b4ab5878ea44bc24 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 00:15:32 -0400 Subject: [PATCH 30/77] fixed device class import --- homeassistant/components/homekit/__init__.py | 3 ++- homeassistant/const.py | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 39a3aa0f2409a8..a37b085c0dc618 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -6,10 +6,11 @@ import voluptuous as vol from homeassistant.components import cover +from homeassistant.components.media_player import DEVICE_CLASS_TV from homeassistant.const import ( ATTR_DEVICE_CLASS, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, CONF_IP_ADDRESS, CONF_NAME, CONF_PORT, CONF_TYPE, DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TV, + DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, TEMP_CELSIUS, TEMP_FAHRENHEIT) import homeassistant.helpers.config_validation as cv diff --git a/homeassistant/const.py b/homeassistant/const.py index a15dc1e40f509e..9176c1b8939240 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -185,7 +185,6 @@ DEVICE_CLASS_TIMESTAMP = 'timestamp' DEVICE_CLASS_PRESSURE = 'pressure' DEVICE_CLASS_POWER = 'power' -DEVICE_CLASS_TV = 'tv' # #### STATES #### STATE_ON = 'on' @@ -319,9 +318,6 @@ # Temperature attribute ATTR_TEMPERATURE = 'temperature' -# Device classes -DEVICE_CLASS_BATTERY - # #### UNITS OF MEASUREMENT #### # Power units POWER_WATT = 'W' From 1b454db2412783a8f2e3a1c279b8e41d1274d7f8 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 22:43:40 -0400 Subject: [PATCH 31/77] renamed input service --- .../components/homekit/type_media_players.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 8a1795e41684f3..54216194e74811 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -222,22 +222,22 @@ def __init__(self, *args): ATTR_INPUT_SOURCE) if self.sources: for index, source in enumerate(self.sources): - input_service = self.add_preload_service(SERV_INPUT_SOURCE, [ + serv_input = self.add_preload_service(SERV_INPUT_SOURCE, [ CHAR_IDENTIFIER, CHAR_NAME]) - input_service.configure_char( + serv_input.configure_char( CHAR_CONFIGURED_NAME, value=source) - input_service.configure_char(CHAR_NAME, value=source) - input_service.configure_char( + serv_input.configure_char(CHAR_NAME, value=source) + serv_input.configure_char( CHAR_IDENTIFIER, value=index) - input_service.configure_char( + serv_input.configure_char( CHAR_IS_CONFIGURED, value=True) input_type = 3 if "hdmi" in source.lower() else 0 - input_service.configure_char(CHAR_INPUT_SOURCE_TYPE, + serv_input.configure_char(CHAR_INPUT_SOURCE_TYPE, value=input_type) - input_service.configure_char( + serv_input.configure_char( CHAR_CURRENT_VISIBILITY_STATE, value=False) - serv_tv.add_linked_service(input_service) + serv_tv.add_linked_service(serv_input) _LOGGER.debug('%s: Added source %s.', self.entity_id, source) From 5da64234fab6cde2ddcd47ce5b20bddef000899b Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 22:47:22 -0400 Subject: [PATCH 32/77] dont validate TelevisionMediaPlayer accessory via config features --- homeassistant/components/homekit/util.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index c3c938595ba7e6..30f7f6310ea083 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -37,8 +37,7 @@ MEDIA_PLAYER_SCHEMA = vol.Schema({ vol.Required(CONF_FEATURE): vol.All( cv.string, vol.In((FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, - FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, - FEATURE_SELECT_SOURCE, FEATURE_VOLUME_STEP))), + FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE))), }) SWITCH_TYPE_SCHEMA = BASIC_INFO_SCHEMA.extend({ @@ -104,10 +103,6 @@ def validate_media_player_features(state, feature_list): supported_modes.append(FEATURE_PLAY_STOP) if features & media_player.const.SUPPORT_VOLUME_MUTE: supported_modes.append(FEATURE_TOGGLE_MUTE) - if features & media_player.const.SUPPORT_VOLUME_STEP: - supported_modes.append(FEATURE_VOLUME_STEP) - if features & media_player.const.SUPPORT_SELECT_SOURCE: - supported_modes.append(FEATURE_SELECT_SOURCE) error_list = [] for feature in feature_list: From 3076c0b310f4c9939e5371c3ae3f1cf3f9046db6 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 23:16:22 -0400 Subject: [PATCH 33/77] updated char structure --- .../components/homekit/type_media_players.py | 177 ++++++++++-------- 1 file changed, 96 insertions(+), 81 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 54216194e74811..a6b8373dc8acf2 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -4,11 +4,13 @@ from pyhap.const import CATEGORY_SWITCH, CATEGORY_TELEVISION from homeassistant.components.media_player import ( - ATTR_INPUT_SOURCE, ATTR_MEDIA_VOLUME_MUTED, SERVICE_SELECT_SOURCE, DOMAIN) + ATTR_INPUT_SOURCE, ATTR_MEDIA_VOLUME_MUTED, SERVICE_SELECT_SOURCE, DOMAIN, + SUPPORT_PLAY, SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_STOP, + SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) from homeassistant.const import ( - ATTR_ENTITY_ID, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, - SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, - SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, + ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_MEDIA_PAUSE, + SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, + SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN, STATE_OFF, STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN) @@ -20,7 +22,7 @@ CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_SLEEP_DISCOVER_MODE, CHAR_MUTE, CHAR_ON, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, - FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, + FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, CHAR_ACTIVE_IDENTIFIER, FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP, SERV_SWITCH, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, SERV_INPUT_SOURCE) @@ -179,73 +181,88 @@ class TelevisionMediaPlayer(HomeAccessory): def __init__(self, *args): """Initialize a Switch accessory object.""" super().__init__(*args, category=CATEGORY_TELEVISION) - self._flag = {FEATURE_ON_OFF: False, FEATURE_TOGGLE_MUTE: False, - FEATURE_SELECT_SOURCE: False} - self.chars = {FEATURE_ON_OFF: None, FEATURE_TOGGLE_MUTE: None, - FEATURE_SELECT_SOURCE: None, FEATURE_VOLUME_STEP: None} + self._flag_active = False + self._flag_active_identifier = False + self._flag_toggle_mute = False + + # Add additional characteristics if volume or input selection supported + self.chars = [] self.sources = [] + features = self.hass.states.get(self.entity_id) \ + .attributes.get(ATTR_SUPPORTED_FEATURES, 0) + + if features & (SUPPORT_PLAY | SUPPORT_PAUSE): + self.chars.append(CHAR_REMOTE_KEY) + if features & SUPPORT_VOLUME_MUTE or features & SUPPORT_VOLUME_STEP: + self.chars.extend((CHAR_VOLUME, CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR)) + if features & SUPPORT_SELECT_SOURCE: + self.chars.append(CHAR_ACTIVE_IDENTIFIER) serv_tv = self.add_preload_service(SERV_TELEVISION, [CHAR_REMOTE_KEY]) self.set_primary_service(serv_tv) serv_tv.configure_char(CHAR_CONFIGURED_NAME, value=self.display_name) serv_tv.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) - self.chars[FEATURE_ON_OFF] = serv_tv.configure_char( + self.char_active = serv_tv.configure_char( CHAR_ACTIVE, setter_callback=self.set_on_off) - serv_tv.configure_char(CHAR_REMOTE_KEY, - setter_callback=self.set_remote_key) - - serv_tv_speaker = self.add_preload_service( - SERV_TELEVISION_SPEAKER, [CHAR_NAME, CHAR_ACTIVE, - CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR, CHAR_VOLUME]) - serv_tv.add_linked_service(serv_tv_speaker) - - name = '{} {}'.format(self.display_name, 'Volume') - serv_tv_speaker.configure_char(CHAR_NAME, value=name) - serv_tv_speaker.configure_char(CHAR_ACTIVE, value=1) - - self.chars[FEATURE_TOGGLE_MUTE] = serv_tv_speaker.configure_char( - CHAR_MUTE, value=False, - setter_callback=self.set_toggle_mute) - - serv_tv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) - self.chars[FEATURE_VOLUME_STEP] = serv_tv_speaker.configure_char( - CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) - - self.chars[FEATURE_SELECT_SOURCE] = serv_tv.configure_char( - CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) - - self.sources = self.hass.states.get(self.entity_id).attributes.get( - ATTR_INPUT_SOURCE) - if self.sources: - for index, source in enumerate(self.sources): - serv_input = self.add_preload_service(SERV_INPUT_SOURCE, [ - CHAR_IDENTIFIER, CHAR_NAME]) - - serv_input.configure_char( - CHAR_CONFIGURED_NAME, value=source) - serv_input.configure_char(CHAR_NAME, value=source) - serv_input.configure_char( - CHAR_IDENTIFIER, value=index) - serv_input.configure_char( - CHAR_IS_CONFIGURED, value=True) - input_type = 3 if "hdmi" in source.lower() else 0 - serv_input.configure_char(CHAR_INPUT_SOURCE_TYPE, - value=input_type) - serv_input.configure_char( - CHAR_CURRENT_VISIBILITY_STATE, value=False) - serv_tv.add_linked_service(serv_input) - _LOGGER.debug('%s: Added source %s.', self.entity_id, - source) + if CHAR_REMOTE_KEY in self.chars: + serv_tv.configure_char(CHAR_REMOTE_KEY, + setter_callback=self.set_remote_key) + + if CHAR_VOLUME in self.chars: + serv_tv_speaker = self.add_preload_service( + SERV_TELEVISION_SPEAKER, [CHAR_NAME, CHAR_ACTIVE, CHAR_VOLUME, + CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR]) + serv_tv.add_linked_service(serv_tv_speaker) + + name = '{} {}'.format(self.display_name, 'Volume') + serv_tv_speaker.configure_char(CHAR_NAME, value=name) + serv_tv_speaker.configure_char(CHAR_ACTIVE, value=1) + + self.char_toggle_mute = serv_tv_speaker.configure_char( + CHAR_MUTE, value=False, setter_callback=self.set_toggle_mute) + + serv_tv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) + + self.char_volume_selector = serv_tv_speaker.configure_char( + CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) + + if CHAR_ACTIVE_IDENTIFIER in self.chars: + self.sources = self.hass.states.get(self.entity_id).attributes.get( + ATTR_INPUT_SOURCE) + if self.sources: + self.char_active_identifier = serv_tv.configure_char( + CHAR_ACTIVE_IDENTIFIER, + setter_callback=self.set_input_source) + for index, source in enumerate(self.sources): + serv_input = self.add_preload_service( + SERV_INPUT_SOURCE, [CHAR_IDENTIFIER, CHAR_NAME]) + + serv_input.configure_char( + CHAR_CONFIGURED_NAME, value=source) + serv_input.configure_char(CHAR_NAME, value=source) + serv_input.configure_char( + CHAR_IDENTIFIER, value=index) + serv_input.configure_char( + CHAR_IS_CONFIGURED, value=True) + input_type = 3 if "hdmi" in source.lower() else 0 + serv_input.configure_char(CHAR_INPUT_SOURCE_TYPE, + value=input_type) + serv_input.configure_char( + CHAR_CURRENT_VISIBILITY_STATE, value=False) + serv_tv.add_linked_service(serv_input) + _LOGGER.debug('%s: Added source %s.', self.entity_id, + source) def set_on_off(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "on_off" to %s', self.entity_id, value) - self._flag[FEATURE_ON_OFF] = True + self._flag_active = True service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) @@ -254,7 +271,6 @@ def set_play_pause(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "play_pause" to %s', self.entity_id, value) - self._flag[FEATURE_PLAY_PAUSE] = True service = SERVICE_MEDIA_PLAY if value else SERVICE_MEDIA_PAUSE params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) @@ -263,14 +279,14 @@ def set_toggle_mute(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "toggle_mute" to %s', self.entity_id, value) - self._flag[FEATURE_TOGGLE_MUTE] = True + self._flag_toggle_mute = True params = {ATTR_ENTITY_ID: self.entity_id, ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) def set_volume_step(self, value): """Send volume step value if call came from HomeKit.""" - _LOGGER.debug('%s: Step tv_volume for "tv_volume" to %s', + _LOGGER.debug('%s: Step volume by %s', self.entity_id, value) service = SERVICE_VOLUME_DOWN if value else SERVICE_VOLUME_UP @@ -279,19 +295,18 @@ def set_volume_step(self, value): def set_input_source(self, value): """Send input set value if call came from HomeKit.""" - _LOGGER.debug('%s: Set select_source for "select_source" to %s', + _LOGGER.debug('%s: Set active_identifer to %s', self.entity_id, value) source = self.sources[value] - self._flag[FEATURE_SELECT_SOURCE] = True + self._flag_active_identifier = True params = {ATTR_ENTITY_ID: self.entity_id, ATTR_INPUT_SOURCE: source} self.call_service(DOMAIN, SERVICE_SELECT_SOURCE, params) def set_remote_key(self, value): """Send remote key value if call came from HomeKit.""" - _LOGGER.debug('%s: Set remote key for "play_pause" to %s', - self.entity_id, value) + _LOGGER.debug('%s: Set remote key to %s', self.entity_id, value) if value in MEDIA_PLAYER_KEYS: service = MEDIA_PLAYER_KEYS[value] @@ -304,35 +319,35 @@ def set_remote_key(self, value): self.call_service(DOMAIN, service, params) def update_state(self, new_state): - """Update switch state after state changed.""" + """Update Television state after state changed.""" current_state = new_state.state - if self.chars[FEATURE_ON_OFF]: + if self.char_active: hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') - if not self._flag[FEATURE_ON_OFF]: + if not self._flag_active: hk_state = 1 if hk_state else 0 - _LOGGER.debug('%s: Set current state for "on_off" to %s', + _LOGGER.debug('%s: Set current active state to %s', self.entity_id, hk_state) - self.chars[FEATURE_ON_OFF].set_value(hk_state) - self._flag[FEATURE_ON_OFF] = False + self.char_active.set_value(hk_state) + self._flag_active = False - if self.chars[FEATURE_TOGGLE_MUTE]: + if self.char_toggle_mute: current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) - if not self._flag[FEATURE_TOGGLE_MUTE]: - _LOGGER.debug('%s: Set current state for "toggle_mute" to %s', + if not self._flag_toggle_mute: + _LOGGER.debug('%s: Set current mute state to %s', self.entity_id, current_state) - self.chars[FEATURE_TOGGLE_MUTE].set_value(current_state) - self._flag[FEATURE_TOGGLE_MUTE] = False + self.char_toggle_mute.set_value(current_state) + self._flag_toggle_mute = False - if self.chars[FEATURE_SELECT_SOURCE]: + if self.char_active_identifier: source_name = new_state.attributes.get(ATTR_INPUT_SOURCE) - if self.sources and not self._flag[FEATURE_SELECT_SOURCE]: + if self.sources and not self._flag_active_identifier: _LOGGER.debug( - '%s: Set current state for "select_source" to %s', + '%s: Set current input to %s', self.entity_id, source_name) if source_name in self.sources: index = self.sources.index(source_name) - self.chars[FEATURE_SELECT_SOURCE].set_value(index) + self.char_active_identifier.set_value(index) else: - self.chars[FEATURE_SELECT_SOURCE].set_value(0) - self._flag[FEATURE_SELECT_SOURCE] = False + self.char_active_identifier.set_value(0) + self._flag_active_identifier = False From d3475d6a7e6c546a0c3439ad37239896a2b6f359 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 23:24:10 -0400 Subject: [PATCH 34/77] fixed tests --- .../homekit/test_type_media_players.py | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 767e468809fe64..f98b6346ac0495 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -160,7 +160,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert acc.chars[FEATURE_ON_OFF].value == 0 assert acc.chars[FEATURE_PLAY_PAUSE].value == 0 - assert acc.chars[FEATURE_SELECT_SOURCE].value == 0 + assert acc.char_active_identifier.value == 0 assert acc.chars[FEATURE_TOGGLE_MUTE].value is False hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True}) @@ -174,11 +174,11 @@ async def test_media_player_television_set_state(hass, hk_driver, events): hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 2'}) await hass.async_block_till_done() - assert acc.chars[FEATURE_SELECT_SOURCE].value == 1 + assert acc.char_active_identifier.value == 1 hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 3'}) await hass.async_block_till_done() - assert acc.chars[FEATURE_SELECT_SOURCE].value == 2 + assert acc.char_active_identifier.value == 2 # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on') @@ -190,16 +190,14 @@ async def test_media_player_television_set_state(hass, hk_driver, events): call_volume_up = async_mock_service(hass, DOMAIN, 'volume_up') call_volume_down = async_mock_service(hass, DOMAIN, 'volume_down') - await hass.async_add_job(acc.chars[FEATURE_ON_OFF] - .client_update_value, 1) + await hass.async_add_job(acc.char_active.client_update_value, 1) await hass.async_block_till_done() assert call_turn_on assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id assert len(events) == 1 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.chars[FEATURE_ON_OFF] - .client_update_value, 0) + await hass.async_add_job(acc.char_active.client_update_value, 0) await hass.async_block_till_done() assert call_turn_off assert call_turn_off[0].data[ATTR_ENTITY_ID] == entity_id @@ -208,8 +206,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): hass.states.async_set(entity_id, STATE_PAUSED) await hass.async_block_till_done() - await hass.async_add_job(acc.chars[FEATURE_PLAY_PAUSE] - .client_update_value, 11) + await hass.async_add_job(acc.char_remote_key.client_update_value, 11) await hass.async_block_till_done() assert call_media_play assert call_media_play[0].data[ATTR_ENTITY_ID] == entity_id @@ -218,16 +215,14 @@ async def test_media_player_television_set_state(hass, hk_driver, events): hass.states.async_set(entity_id, STATE_PLAYING) await hass.async_block_till_done() - await hass.async_add_job(acc.chars[FEATURE_PLAY_PAUSE] - .client_update_value, 11) + await hass.async_add_job(acc.char_remote_key.client_update_value, 11) await hass.async_block_till_done() assert call_media_pause assert call_media_pause[0].data[ATTR_ENTITY_ID] == entity_id assert len(events) == 4 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.chars[FEATURE_TOGGLE_MUTE] - .client_update_value, True) + await hass.async_add_job(acc.char_toggle_mute.client_update_value, True) await hass.async_block_till_done() assert call_toggle_mute assert call_toggle_mute[0].data[ATTR_ENTITY_ID] == entity_id @@ -235,8 +230,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 5 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.chars[FEATURE_TOGGLE_MUTE] - .client_update_value, False) + await hass.async_add_job(acc.char_toggle_mute.client_update_value, False) await hass.async_block_till_done() assert call_toggle_mute assert call_toggle_mute[1].data[ATTR_ENTITY_ID] == entity_id @@ -244,8 +238,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 6 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.chars[FEATURE_SELECT_SOURCE] - .client_update_value, 1) + await hass.async_add_job(acc.char_active_identifier.client_update_value, 1) await hass.async_block_till_done() assert call_select_source assert call_select_source[0].data[ATTR_ENTITY_ID] == entity_id @@ -253,16 +246,14 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 7 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.chars[FEATURE_VOLUME_STEP] - .client_update_value, 0) + await hass.async_add_job(acc.char_volume_selector.client_update_value, 0) await hass.async_block_till_done() assert call_volume_up assert call_volume_up[0].data[ATTR_ENTITY_ID] == entity_id assert len(events) == 8 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.chars[FEATURE_VOLUME_STEP] - .client_update_value, 1) + await hass.async_add_job(acc.char_volume_selector.client_update_value, 1) await hass.async_block_till_done() assert call_volume_down assert call_volume_down[0].data[ATTR_ENTITY_ID] == entity_id From ef76a30b4140c2bfa33c1344a333a10b5d507686 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 23:24:18 -0400 Subject: [PATCH 35/77] lint fixes --- homeassistant/components/homekit/const.py | 2 -- .../components/homekit/type_media_players.py | 19 +++++++++---------- homeassistant/components/homekit/util.py | 5 ++--- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/homekit/const.py b/homeassistant/components/homekit/const.py index 1eb501ba6375b1..488632d23eb305 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -28,8 +28,6 @@ FEATURE_PLAY_PAUSE = 'play_pause' FEATURE_PLAY_STOP = 'play_stop' FEATURE_TOGGLE_MUTE = 'toggle_mute' -FEATURE_VOLUME_STEP = 'volume_step' -FEATURE_SELECT_SOURCE = 'select_source' # #### HomeKit Component Event #### EVENT_HOMEKIT_CHANGED = 'homekit_state_change' diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index a6b8373dc8acf2..3853709e680152 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -5,8 +5,8 @@ from homeassistant.components.media_player import ( ATTR_INPUT_SOURCE, ATTR_MEDIA_VOLUME_MUTED, SERVICE_SELECT_SOURCE, DOMAIN, - SUPPORT_PLAY, SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_STOP, - SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) + SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, + SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, @@ -22,9 +22,9 @@ CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_SLEEP_DISCOVER_MODE, CHAR_MUTE, CHAR_ON, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, - FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, CHAR_ACTIVE_IDENTIFIER, - FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP, SERV_SWITCH, SERV_TELEVISION, - SERV_TELEVISION_SPEAKER, SERV_INPUT_SOURCE) + FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, + SERV_SWITCH, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, + SERV_INPUT_SOURCE) _LOGGER = logging.getLogger(__name__) @@ -47,7 +47,6 @@ 11: SERVICE_MEDIA_PLAY_PAUSE, } - MODE_FRIENDLY_NAME = { FEATURE_ON_OFF: 'Power', FEATURE_PLAY_PAUSE: 'Play/Pause', @@ -196,7 +195,7 @@ def __init__(self, *args): self.chars.append(CHAR_REMOTE_KEY) if features & SUPPORT_VOLUME_MUTE or features & SUPPORT_VOLUME_STEP: self.chars.extend((CHAR_VOLUME, CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR)) + CHAR_VOLUME_SELECTOR)) if features & SUPPORT_SELECT_SOURCE: self.chars.append(CHAR_ACTIVE_IDENTIFIER) @@ -209,8 +208,8 @@ def __init__(self, *args): CHAR_ACTIVE, setter_callback=self.set_on_off) if CHAR_REMOTE_KEY in self.chars: - serv_tv.configure_char(CHAR_REMOTE_KEY, - setter_callback=self.set_remote_key) + self.char_remote_key = serv_tv.configure_char( + CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) if CHAR_VOLUME in self.chars: serv_tv_speaker = self.add_preload_service( @@ -251,7 +250,7 @@ def __init__(self, *args): CHAR_IS_CONFIGURED, value=True) input_type = 3 if "hdmi" in source.lower() else 0 serv_input.configure_char(CHAR_INPUT_SOURCE_TYPE, - value=input_type) + value=input_type) serv_input.configure_char( CHAR_CURRENT_VISIBILITY_STATE, value=False) serv_tv.add_linked_service(serv_input) diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index 30f7f6310ea083..117859e79948dc 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -14,9 +14,8 @@ from .const import ( CONF_FEATURE, CONF_FEATURE_LIST, CONF_LINKED_BATTERY_SENSOR, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, - FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP, FEATURE_SELECT_SOURCE, - HOMEKIT_NOTIFY_ID, TYPE_FAUCET, TYPE_OUTLET, TYPE_SHOWER, - TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) + FEATURE_TOGGLE_MUTE, HOMEKIT_NOTIFY_ID, TYPE_FAUCET, TYPE_OUTLET, + TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) _LOGGER = logging.getLogger(__name__) From 7cab1d3aed7341fe5805e645bf8c5b12f93bfbf6 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 23:37:30 -0400 Subject: [PATCH 36/77] condensed lines --- .../components/homekit/type_media_players.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 3853709e680152..223be15c89a394 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -19,12 +19,11 @@ from .const import ( CHAR_ACTIVE, CHAR_ACTIVE_IDENTIFIER, CHAR_CONFIGURED_NAME, CHAR_CURRENT_VISIBILITY_STATE, CHAR_IDENTIFIER, CHAR_INPUT_SOURCE_TYPE, - CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_SLEEP_DISCOVER_MODE, - CHAR_MUTE, CHAR_ON, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR, CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, - FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, - SERV_SWITCH, SERV_TELEVISION, SERV_TELEVISION_SPEAKER, - SERV_INPUT_SOURCE) + CHAR_IS_CONFIGURED, CHAR_NAME, CHAR_SLEEP_DISCOVER_MODE, CHAR_MUTE, + CHAR_ON, CHAR_REMOTE_KEY, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR, + CHAR_VOLUME, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, + FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, SERV_SWITCH, SERV_TELEVISION, + SERV_TELEVISION_SPEAKER, SERV_INPUT_SOURCE) _LOGGER = logging.getLogger(__name__) From 588b053099c1090981b2ee92c8e47a5a50618842 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Mon, 29 Apr 2019 23:44:29 -0400 Subject: [PATCH 37/77] more lint and test fixes --- homeassistant/components/homekit/util.py | 6 ++--- .../homekit/test_type_media_players.py | 24 ++++++++----------- tests/components/homekit/test_util.py | 7 ++---- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index 117859e79948dc..1bf57f1b1f9b58 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -13,9 +13,9 @@ from .const import ( CONF_FEATURE, CONF_FEATURE_LIST, CONF_LINKED_BATTERY_SENSOR, - FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, - FEATURE_TOGGLE_MUTE, HOMEKIT_NOTIFY_ID, TYPE_FAUCET, TYPE_OUTLET, - TYPE_SHOWER, TYPE_SPRINKLER, TYPE_SWITCH, TYPE_VALVE) + FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE, + HOMEKIT_NOTIFY_ID, TYPE_FAUCET, TYPE_OUTLET, TYPE_SHOWER, TYPE_SPRINKLER, + TYPE_SWITCH, TYPE_VALVE) _LOGGER = logging.getLogger(__name__) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index f98b6346ac0495..ef05ae6ac01d29 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -1,9 +1,9 @@ """Test different accessory types: Media Players.""" from homeassistant.components.homekit.const import ( - ATTR_VALUE, CONF_FEATURE_LIST, DEVICE_CLASS_TV, FEATURE_ON_OFF, - FEATURE_PLAY_PAUSE, FEATURE_PLAY_STOP, FEATURE_SELECT_SOURCE, - FEATURE_TOGGLE_MUTE, FEATURE_VOLUME_STEP) + ATTR_VALUE, CONF_FEATURE_LIST, FEATURE_ON_OFF, FEATURE_PLAY_PAUSE, + FEATURE_PLAY_STOP, FEATURE_TOGGLE_MUTE) +from homeassistant.components.media_player import DEVICE_CLASS_TV from homeassistant.components.homekit.type_media_players import ( MediaPlayer, TelevisionMediaPlayer) from homeassistant.components.media_player.const import ( @@ -137,10 +137,6 @@ async def test_media_player_set_state(hass, hk_driver, events): async def test_media_player_television_set_state(hass, hk_driver, events): """Test if television accessory and HA are updated accordingly.""" - config = {CONF_FEATURE_LIST: { - FEATURE_ON_OFF: None, FEATURE_PLAY_PAUSE: None, - FEATURE_SELECT_SOURCE: None, FEATURE_TOGGLE_MUTE: None, - FEATURE_VOLUME_STEP: None}} entity_id = 'media_player.television' hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, @@ -152,25 +148,25 @@ async def test_media_player_television_set_state(hass, hk_driver, events): }) await hass.async_block_till_done() acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, - config) + None) await hass.async_add_job(acc.run) assert acc.aid == 2 assert acc.category == 31 # Television - assert acc.chars[FEATURE_ON_OFF].value == 0 - assert acc.chars[FEATURE_PLAY_PAUSE].value == 0 + assert acc.char_active.value == 0 + assert acc.char_remote_key.value == 0 assert acc.char_active_identifier.value == 0 - assert acc.chars[FEATURE_TOGGLE_MUTE].value is False + assert acc.char_toggle_mute.value is False hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True}) await hass.async_block_till_done() - assert acc.chars[FEATURE_ON_OFF].value == 1 - assert acc.chars[FEATURE_TOGGLE_MUTE].value is True + assert acc.char_active.value == 1 + assert acc.char_toggle_mute.value is True hass.states.async_set(entity_id, STATE_OFF) await hass.async_block_till_done() - assert acc.chars[FEATURE_ON_OFF].value == 0 + assert acc.char_active.value == 0 hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 2'}) await hass.async_block_till_done() diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index ca34e44d1d9e2c..14e316a7fd0a30 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -35,7 +35,6 @@ def test_validate_entity_config(): {'media_player.test': {CONF_FEATURE_LIST: [ {CONF_FEATURE: FEATURE_ON_OFF}, {CONF_FEATURE: FEATURE_ON_OFF}]}}, - {'media_player.test': {CONF_TYPE: 'invalid_type'}}, {'switch.test': {CONF_TYPE: 'invalid_type'}}] for conf in configs: @@ -61,14 +60,12 @@ def test_validate_entity_config(): {'lock.demo': {ATTR_CODE: '1234'}} assert vec({'media_player.demo': {}}) == \ - {'media_player.demo': {CONF_TYPE: TYPE_SWITCH, CONF_FEATURE_LIST: {}}} + {'media_player.demo': {CONF_FEATURE_LIST: {}}} config = {CONF_FEATURE_LIST: [{CONF_FEATURE: FEATURE_ON_OFF}, {CONF_FEATURE: FEATURE_PLAY_PAUSE}]} assert vec({'media_player.demo': config}) == \ - {'media_player.demo': {CONF_TYPE: TYPE_SWITCH, CONF_FEATURE_LIST: + {'media_player.demo': {CONF_FEATURE_LIST: {FEATURE_ON_OFF: {}, FEATURE_PLAY_PAUSE: {}}}} - assert vec({'media_player.demo': {}}) == \ - {'media_player.demo': {CONF_TYPE: TYPE_SWITCH, CONF_FEATURE_LIST: {}}} assert vec({'switch.demo': {CONF_TYPE: TYPE_FAUCET}}) == \ {'switch.demo': {CONF_TYPE: TYPE_FAUCET}} From e0bf9d00033a6f3dbcdae177f9afa6e17cb4650e Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 00:10:39 -0400 Subject: [PATCH 38/77] fixed tests --- homeassistant/components/homekit/type_media_players.py | 8 ++++---- tests/components/homekit/test_type_media_players.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 223be15c89a394..934df60f9980c6 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -4,9 +4,9 @@ from pyhap.const import CATEGORY_SWITCH, CATEGORY_TELEVISION from homeassistant.components.media_player import ( - ATTR_INPUT_SOURCE, ATTR_MEDIA_VOLUME_MUTED, SERVICE_SELECT_SOURCE, DOMAIN, - SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, - SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) + ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, + SERVICE_SELECT_SOURCE, DOMAIN, SUPPORT_PAUSE, SUPPORT_PLAY, + SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, @@ -231,7 +231,7 @@ def __init__(self, *args): if CHAR_ACTIVE_IDENTIFIER in self.chars: self.sources = self.hass.states.get(self.entity_id).attributes.get( - ATTR_INPUT_SOURCE) + ATTR_INPUT_SOURCE_LIST) if self.sources: self.char_active_identifier = serv_tv.configure_char( CHAR_ACTIVE_IDENTIFIER, diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index ef05ae6ac01d29..fbafdf4e43e9a0 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -140,7 +140,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): entity_id = 'media_player.television' hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, - ATTR_SUPPORTED_FEATURES: 20873, + ATTR_SUPPORTED_FEATURES: 3469, ATTR_MEDIA_VOLUME_MUTED: False, ATTR_INPUT_SOURCE_LIST: ['HDMI 1', 'HDMI 2', 'HDMI 3', From fbf715483a7cc94bb0f9108a6aa10a97719023f0 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 21:24:52 -0400 Subject: [PATCH 39/77] flags --- .../components/homekit/type_media_players.py | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 934df60f9980c6..46183067955855 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -39,7 +39,7 @@ 8: "Select", 9: "Back", 10: "Exit", - 15: "Information" + 15: "Information", } MEDIA_PLAYER_KEYS = { @@ -180,9 +180,8 @@ def __init__(self, *args): """Initialize a Switch accessory object.""" super().__init__(*args, category=CATEGORY_TELEVISION) - self._flag_active = False - self._flag_active_identifier = False - self._flag_toggle_mute = False + self._flag = {CHAR_ACTIVE: False, CHAR_ACTIVE_IDENTIFIER: False, + FEATURE_TOGGLE_MUTE: False} # Add additional characteristics if volume or input selection supported self.chars = [] @@ -322,30 +321,29 @@ def update_state(self, new_state): if self.char_active: hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') - if not self._flag_active: + if not self._flag[CHAR_ACTIVE]: hk_state = 1 if hk_state else 0 _LOGGER.debug('%s: Set current active state to %s', self.entity_id, hk_state) self.char_active.set_value(hk_state) - self._flag_active = False + self._flag[CHAR_ACTIVE] = False if self.char_toggle_mute: current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) - if not self._flag_toggle_mute: + if not self._flag[FEATURE_TOGGLE_MUTE]: _LOGGER.debug('%s: Set current mute state to %s', self.entity_id, current_state) self.char_toggle_mute.set_value(current_state) - self._flag_toggle_mute = False + self._flag[FEATURE_TOGGLE_MUTE] = False if self.char_active_identifier: source_name = new_state.attributes.get(ATTR_INPUT_SOURCE) - if self.sources and not self._flag_active_identifier: - _LOGGER.debug( - '%s: Set current input to %s', - self.entity_id, source_name) + if self.sources and not self._flag[CHAR_ACTIVE_IDENTIFIER]: + _LOGGER.debug('%s: Set current input to %s', self.entity_id, + source_name) if source_name in self.sources: index = self.sources.index(source_name) self.char_active_identifier.set_value(index) else: self.char_active_identifier.set_value(0) - self._flag_active_identifier = False + self._flag[CHAR_ACTIVE_IDENTIFIER] = False From 03cbc84205c6d8b5662b886c33337d571b24e6a2 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 21:26:30 -0400 Subject: [PATCH 40/77] one line for name --- homeassistant/components/homekit/type_media_players.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 46183067955855..a1ff784bb5d790 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -199,8 +199,7 @@ def __init__(self, *args): serv_tv = self.add_preload_service(SERV_TELEVISION, [CHAR_REMOTE_KEY]) self.set_primary_service(serv_tv) - serv_tv.configure_char(CHAR_CONFIGURED_NAME, - value=self.display_name) + serv_tv.configure_char(CHAR_CONFIGURED_NAME, value=self.display_name) serv_tv.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) self.char_active = serv_tv.configure_char( CHAR_ACTIVE, setter_callback=self.set_on_off) From 9c493d1b6dcb7a50e10c74cad197799ca661f6e9 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 21:27:07 -0400 Subject: [PATCH 41/77] serv_speaker --- .../components/homekit/type_media_players.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index a1ff784bb5d790..fe488b15db4f79 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -209,22 +209,22 @@ def __init__(self, *args): CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) if CHAR_VOLUME in self.chars: - serv_tv_speaker = self.add_preload_service( + serv_speaker = self.add_preload_service( SERV_TELEVISION_SPEAKER, [CHAR_NAME, CHAR_ACTIVE, CHAR_VOLUME, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR]) - serv_tv.add_linked_service(serv_tv_speaker) + serv_tv.add_linked_service(serv_speaker) name = '{} {}'.format(self.display_name, 'Volume') - serv_tv_speaker.configure_char(CHAR_NAME, value=name) - serv_tv_speaker.configure_char(CHAR_ACTIVE, value=1) + serv_speaker.configure_char(CHAR_NAME, value=name) + serv_speaker.configure_char(CHAR_ACTIVE, value=1) - self.char_toggle_mute = serv_tv_speaker.configure_char( + self.char_toggle_mute = serv_speaker.configure_char( CHAR_MUTE, value=False, setter_callback=self.set_toggle_mute) - serv_tv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) + serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) - self.char_volume_selector = serv_tv_speaker.configure_char( + self.char_volume_selector = serv_speaker.configure_char( CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) if CHAR_ACTIVE_IDENTIFIER in self.chars: From 970a1c3c0ba4fd34c6c4f45acf1139b2f85722d0 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 21:27:52 -0400 Subject: [PATCH 42/77] char_mute --- homeassistant/components/homekit/type_media_players.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index fe488b15db4f79..139997a0252a46 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -219,7 +219,7 @@ def __init__(self, *args): serv_speaker.configure_char(CHAR_NAME, value=name) serv_speaker.configure_char(CHAR_ACTIVE, value=1) - self.char_toggle_mute = serv_speaker.configure_char( + self.char_mute = serv_speaker.configure_char( CHAR_MUTE, value=False, setter_callback=self.set_toggle_mute) serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) @@ -327,12 +327,12 @@ def update_state(self, new_state): self.char_active.set_value(hk_state) self._flag[CHAR_ACTIVE] = False - if self.char_toggle_mute: + if self.char_mute: current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) if not self._flag[FEATURE_TOGGLE_MUTE]: _LOGGER.debug('%s: Set current mute state to %s', self.entity_id, current_state) - self.char_toggle_mute.set_value(current_state) + self.char_mute.set_value(current_state) self._flag[FEATURE_TOGGLE_MUTE] = False if self.char_active_identifier: From 15eee34763f8014c1ed00e76ac7e2fcca217bb51 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 21:29:35 -0400 Subject: [PATCH 43/77] single line for inputs --- homeassistant/components/homekit/type_media_players.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 139997a0252a46..95aa35040603b4 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -241,10 +241,8 @@ def __init__(self, *args): serv_input.configure_char( CHAR_CONFIGURED_NAME, value=source) serv_input.configure_char(CHAR_NAME, value=source) - serv_input.configure_char( - CHAR_IDENTIFIER, value=index) - serv_input.configure_char( - CHAR_IS_CONFIGURED, value=True) + serv_input.configure_char(CHAR_IDENTIFIER, value=index) + serv_input.configure_char(CHAR_IS_CONFIGURED, value=True) input_type = 3 if "hdmi" in source.lower() else 0 serv_input.configure_char(CHAR_INPUT_SOURCE_TYPE, value=input_type) From f8bd62f9c3ed18d0db4f6b67349c4c11375e8270 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 21:30:42 -0400 Subject: [PATCH 44/77] revert whitespace in test util --- tests/components/homekit/test_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index caa9d07cc173f2..f35194608c6ea5 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -35,10 +35,10 @@ def test_validate_entity_config(): {'demo.test': 'test'}, {'demo.test': [1, 2]}, {'demo.test': None}, {'demo.test': {CONF_NAME: None}}, {'media_player.test': {CONF_FEATURE_LIST: [ - {CONF_FEATURE: 'invalid_feature'}]}}, + {CONF_FEATURE: 'invalid_feature'}]}}, {'media_player.test': {CONF_FEATURE_LIST: [ - {CONF_FEATURE: FEATURE_ON_OFF}, - {CONF_FEATURE: FEATURE_ON_OFF}]}}, + {CONF_FEATURE: FEATURE_ON_OFF}, + {CONF_FEATURE: FEATURE_ON_OFF}]}}, {'switch.test': {CONF_TYPE: 'invalid_type'}}] for conf in configs: From 4168cba302e67a0f62d0d59e12a3c39f000bd9a2 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:07:33 -0400 Subject: [PATCH 45/77] renamed chars array --- .../components/homekit/type_media_players.py | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 95aa35040603b4..f9d670fa9d9912 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -184,35 +184,38 @@ def __init__(self, *args): FEATURE_TOGGLE_MUTE: False} # Add additional characteristics if volume or input selection supported - self.chars = [] + self.chars_tv = [] + self.chars_speaker = [] self.sources = [] features = self.hass.states.get(self.entity_id) \ .attributes.get(ATTR_SUPPORTED_FEATURES, 0) if features & (SUPPORT_PLAY | SUPPORT_PAUSE): - self.chars.append(CHAR_REMOTE_KEY) + self.chars_tv.append(CHAR_REMOTE_KEY) if features & SUPPORT_VOLUME_MUTE or features & SUPPORT_VOLUME_STEP: - self.chars.extend((CHAR_VOLUME, CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR)) + self.chars_speaker.extend((CHAR_VOLUME, CHAR_VOLUME_CONTROL_TYPE, + CHAR_VOLUME_SELECTOR)) if features & SUPPORT_SELECT_SOURCE: - self.chars.append(CHAR_ACTIVE_IDENTIFIER) + self.chars_speaker.append(CHAR_ACTIVE_IDENTIFIER) - serv_tv = self.add_preload_service(SERV_TELEVISION, [CHAR_REMOTE_KEY]) + # TODO: find a place for these chars + if len(self.chars_speaker): + self.chars_speaker.extend((CHAR_NAME, CHAR_ACTIVE)) + + serv_tv = self.add_preload_service(SERV_TELEVISION, self.chars_tv) self.set_primary_service(serv_tv) serv_tv.configure_char(CHAR_CONFIGURED_NAME, value=self.display_name) serv_tv.configure_char(CHAR_SLEEP_DISCOVER_MODE, value=True) self.char_active = serv_tv.configure_char( CHAR_ACTIVE, setter_callback=self.set_on_off) - if CHAR_REMOTE_KEY in self.chars: + if CHAR_REMOTE_KEY in self.chars_tv: self.char_remote_key = serv_tv.configure_char( CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) - if CHAR_VOLUME in self.chars: + if CHAR_VOLUME in self.chars_speaker: serv_speaker = self.add_preload_service( - SERV_TELEVISION_SPEAKER, [CHAR_NAME, CHAR_ACTIVE, CHAR_VOLUME, - CHAR_VOLUME_CONTROL_TYPE, - CHAR_VOLUME_SELECTOR]) + SERV_TELEVISION_SPEAKER, self.chars_speaker) serv_tv.add_linked_service(serv_speaker) name = '{} {}'.format(self.display_name, 'Volume') From df5245b05b6cd0107c5b65bdf541b5f0b44e6cf3 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:09:24 -0400 Subject: [PATCH 46/77] moved active identifier to flag --- homeassistant/components/homekit/type_media_players.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index f9d670fa9d9912..84df20f66c5d1f 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -196,7 +196,7 @@ def __init__(self, *args): self.chars_speaker.extend((CHAR_VOLUME, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR)) if features & SUPPORT_SELECT_SOURCE: - self.chars_speaker.append(CHAR_ACTIVE_IDENTIFIER) + self.support_select_source = True # TODO: find a place for these chars if len(self.chars_speaker): @@ -230,13 +230,12 @@ def __init__(self, *args): self.char_volume_selector = serv_speaker.configure_char( CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) - if CHAR_ACTIVE_IDENTIFIER in self.chars: + if self.support_select_source: self.sources = self.hass.states.get(self.entity_id).attributes.get( ATTR_INPUT_SOURCE_LIST) if self.sources: self.char_active_identifier = serv_tv.configure_char( - CHAR_ACTIVE_IDENTIFIER, - setter_callback=self.set_input_source) + CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) for index, source in enumerate(self.sources): serv_input = self.add_preload_service( SERV_INPUT_SOURCE, [CHAR_IDENTIFIER, CHAR_NAME]) @@ -336,7 +335,7 @@ def update_state(self, new_state): self.char_mute.set_value(current_state) self._flag[FEATURE_TOGGLE_MUTE] = False - if self.char_active_identifier: + if self.support_select_source: source_name = new_state.attributes.get(ATTR_INPUT_SOURCE) if self.sources and not self._flag[CHAR_ACTIVE_IDENTIFIER]: _LOGGER.debug('%s: Set current input to %s', self.entity_id, From 71a8626502064c9ede265375047303c834bf223a Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:12:19 -0400 Subject: [PATCH 47/77] removed possible error power state --- .../components/homekit/type_media_players.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 84df20f66c5d1f..0ddb62a669a67d 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -318,14 +318,14 @@ def update_state(self, new_state): """Update Television state after state changed.""" current_state = new_state.state - if self.char_active: - hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') - if not self._flag[CHAR_ACTIVE]: - hk_state = 1 if hk_state else 0 - _LOGGER.debug('%s: Set current active state to %s', - self.entity_id, hk_state) - self.char_active.set_value(hk_state) - self._flag[CHAR_ACTIVE] = False + # Power state television + hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') + if not self._flag[CHAR_ACTIVE]: + hk_state = 1 if hk_state else 0 + _LOGGER.debug('%s: Set current active state to %s', + self.entity_id, hk_state) + self.char_active.set_value(hk_state) + self._flag[CHAR_ACTIVE] = False if self.char_mute: current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) From 997786eaa465533247bf0130895cd66b27b6daf2 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:15:04 -0400 Subject: [PATCH 48/77] cleaned up sources --- .../components/homekit/type_media_players.py | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 0ddb62a669a67d..e77c7a464091a8 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -233,26 +233,26 @@ def __init__(self, *args): if self.support_select_source: self.sources = self.hass.states.get(self.entity_id).attributes.get( ATTR_INPUT_SOURCE_LIST) - if self.sources: - self.char_active_identifier = serv_tv.configure_char( - CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) - for index, source in enumerate(self.sources): - serv_input = self.add_preload_service( - SERV_INPUT_SOURCE, [CHAR_IDENTIFIER, CHAR_NAME]) - - serv_input.configure_char( - CHAR_CONFIGURED_NAME, value=source) - serv_input.configure_char(CHAR_NAME, value=source) - serv_input.configure_char(CHAR_IDENTIFIER, value=index) - serv_input.configure_char(CHAR_IS_CONFIGURED, value=True) - input_type = 3 if "hdmi" in source.lower() else 0 - serv_input.configure_char(CHAR_INPUT_SOURCE_TYPE, - value=input_type) - serv_input.configure_char( - CHAR_CURRENT_VISIBILITY_STATE, value=False) - serv_tv.add_linked_service(serv_input) - _LOGGER.debug('%s: Added source %s.', self.entity_id, - source) + if not self.sources: + return + self.char_active_identifier = serv_tv.configure_char( + CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) + for index, source in enumerate(self.sources): + serv_input = self.add_preload_service( + SERV_INPUT_SOURCE, [CHAR_IDENTIFIER, CHAR_NAME]) + + serv_input.configure_char( + CHAR_CONFIGURED_NAME, value=source) + serv_input.configure_char(CHAR_NAME, value=source) + serv_input.configure_char(CHAR_IDENTIFIER, value=index) + serv_input.configure_char(CHAR_IS_CONFIGURED, value=True) + input_type = 3 if "hdmi" in source.lower() else 0 + serv_input.configure_char(CHAR_INPUT_SOURCE_TYPE, + value=input_type) + serv_input.configure_char(CHAR_CURRENT_VISIBILITY_STATE, + value=False) + serv_tv.add_linked_service(serv_input) + _LOGGER.debug('%s: Added source %s.', self.entity_id, source) def set_on_off(self, value): """Move switch state to value if call came from HomeKit.""" From bd5e3b07a7a43e0cab9a40a83926061526f98474 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:16:01 -0400 Subject: [PATCH 49/77] renamed char input source --- homeassistant/components/homekit/type_media_players.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index e77c7a464091a8..dd10689b1fcea7 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -235,7 +235,7 @@ def __init__(self, *args): ATTR_INPUT_SOURCE_LIST) if not self.sources: return - self.char_active_identifier = serv_tv.configure_char( + self.char_input_source = serv_tv.configure_char( CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) for index, source in enumerate(self.sources): serv_input = self.add_preload_service( @@ -342,7 +342,7 @@ def update_state(self, new_state): source_name) if source_name in self.sources: index = self.sources.index(source_name) - self.char_active_identifier.set_value(index) + self.char_input_source.set_value(index) else: - self.char_active_identifier.set_value(0) + self.char_input_source.set_value(0) self._flag[CHAR_ACTIVE_IDENTIFIER] = False From 926446976d719e0688c5203ce75e2ebccdb8fb9c Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:17:10 -0400 Subject: [PATCH 50/77] moved add linked input service --- homeassistant/components/homekit/type_media_players.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index dd10689b1fcea7..ddb03e78e96d38 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -240,7 +240,7 @@ def __init__(self, *args): for index, source in enumerate(self.sources): serv_input = self.add_preload_service( SERV_INPUT_SOURCE, [CHAR_IDENTIFIER, CHAR_NAME]) - + serv_tv.add_linked_service(serv_input) serv_input.configure_char( CHAR_CONFIGURED_NAME, value=source) serv_input.configure_char(CHAR_NAME, value=source) @@ -251,7 +251,6 @@ def __init__(self, *args): value=input_type) serv_input.configure_char(CHAR_CURRENT_VISIBILITY_STATE, value=False) - serv_tv.add_linked_service(serv_input) _LOGGER.debug('%s: Added source %s.', self.entity_id, source) def set_on_off(self, value): From 8333782e427a17ea820f307c10ac5ee3aa4326f1 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:21:04 -0400 Subject: [PATCH 51/77] fixed a possible error when checking for mute status --- homeassistant/components/homekit/type_media_players.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index ddb03e78e96d38..1554dc7c9f6388 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -326,7 +326,7 @@ def update_state(self, new_state): self.char_active.set_value(hk_state) self._flag[CHAR_ACTIVE] = False - if self.char_mute: + if CHAR_VOLUME in self.chars_speaker: current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) if not self._flag[FEATURE_TOGGLE_MUTE]: _LOGGER.debug('%s: Set current mute state to %s', From 985dc7b292b3f6830d2832654fba59dd3a879e91 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:29:16 -0400 Subject: [PATCH 52/77] added volume char configured --- .../components/homekit/type_media_players.py | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 1554dc7c9f6388..b2d9177839436c 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -5,14 +5,15 @@ from homeassistant.components.media_player import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, - SERVICE_SELECT_SOURCE, DOMAIN, SUPPORT_PAUSE, SUPPORT_PLAY, - SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) + ATTR_MEDIA_VOLUME_LEVEL ,SERVICE_SELECT_SOURCE, DOMAIN, SUPPORT_PAUSE, + SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + SUPPORT_SELECT_SOURCE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_UP, - SERVICE_VOLUME_DOWN, STATE_OFF, STATE_PLAYING, STATE_PAUSED, - STATE_UNKNOWN) + SERVICE_VOLUME_DOWN, SERVICE_VOLUME_SET, STATE_OFF, STATE_PLAYING, + STATE_PAUSED, STATE_UNKNOWN) from . import TYPES from .accessories import HomeAccessory @@ -181,7 +182,7 @@ def __init__(self, *args): super().__init__(*args, category=CATEGORY_TELEVISION) self._flag = {CHAR_ACTIVE: False, CHAR_ACTIVE_IDENTIFIER: False, - FEATURE_TOGGLE_MUTE: False} + FEATURE_TOGGLE_MUTE: False, CHAR_VOLUME: False} # Add additional characteristics if volume or input selection supported self.chars_tv = [] @@ -227,6 +228,9 @@ def __init__(self, *args): serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) + self.char_volume = serv_speaker.configure_char( + CHAR_VOLUME, setter_callback=self.set_volume) + self.char_volume_selector = serv_speaker.configure_char( CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) @@ -279,6 +283,15 @@ def set_toggle_mute(self, value): ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) + def set_volume(self, value): + """Send volume step value if call came from HomeKit.""" + _LOGGER.debug('%s: Set volume to %s', self.entity_id, value) + + self._flag[CHAR_VOLUME] = True + params = {ATTR_ENTITY_ID: self.entity_id, + ATTR_MEDIA_VOLUME_LEVEL: value} + self.call_service(DOMAIN, SERVICE_VOLUME_SET, params) + def set_volume_step(self, value): """Send volume step value if call came from HomeKit.""" _LOGGER.debug('%s: Step volume by %s', @@ -326,14 +339,24 @@ def update_state(self, new_state): self.char_active.set_value(hk_state) self._flag[CHAR_ACTIVE] = False + # TODO: Add logic to detect if media player supports volume_level if CHAR_VOLUME in self.chars_speaker: - current_state = new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED) + current_mute_state = new_state.attributes.get( + ATTR_MEDIA_VOLUME_MUTED) if not self._flag[FEATURE_TOGGLE_MUTE]: _LOGGER.debug('%s: Set current mute state to %s', - self.entity_id, current_state) - self.char_mute.set_value(current_state) + self.entity_id, current_mute_state) + self.char_mute.set_value(current_mute_state) self._flag[FEATURE_TOGGLE_MUTE] = False + current_voume_state = new_state.attributes.get( + ATTR_MEDIA_VOLUME_LEVEL) + if not self._flag[CHAR_VOLUME]: + _LOGGER.debug('%s: Set current volume to %s', + self.entity_id, current_voume_state) + self.char_volume.set_value(current_voume_state) + self._flag[CHAR_VOLUME] = False + if self.support_select_source: source_name = new_state.attributes.get(ATTR_INPUT_SOURCE) if self.sources and not self._flag[CHAR_ACTIVE_IDENTIFIER]: From 40d1d17e5f626b725822dc1b437e669b4dab508d Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:29:23 -0400 Subject: [PATCH 53/77] fixed some flags --- homeassistant/components/homekit/type_media_players.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index b2d9177839436c..85af36df25793a 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -261,7 +261,7 @@ def set_on_off(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "on_off" to %s', self.entity_id, value) - self._flag_active = True + self._flag[CHAR_ACTIVE] = True service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) @@ -278,7 +278,7 @@ def set_toggle_mute(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "toggle_mute" to %s', self.entity_id, value) - self._flag_toggle_mute = True + self._flag[FEATURE_TOGGLE_MUTE] = True params = {ATTR_ENTITY_ID: self.entity_id, ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) @@ -307,7 +307,7 @@ def set_input_source(self, value): self.entity_id, value) source = self.sources[value] - self._flag_active_identifier = True + self._flag[CHAR_ACTIVE_IDENTIFIER] = True params = {ATTR_ENTITY_ID: self.entity_id, ATTR_INPUT_SOURCE: source} self.call_service(DOMAIN, SERVICE_SELECT_SOURCE, params) From 2cf1899f1f5c36d91a2629a87bdc7cac43a866ae Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:30:09 -0400 Subject: [PATCH 54/77] TODO: added tests for volume char --- tests/components/homekit/test_type_media_players.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index fbafdf4e43e9a0..d27f3886493c4f 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -255,3 +255,5 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_volume_down[0].data[ATTR_ENTITY_ID] == entity_id assert len(events) == 9 assert events[-1].data[ATTR_VALUE] is None + + # TODO Add some tests to check volume char From 9e57e2e1003dadf7474f4feeb3c0b9c6ccbf113b Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:36:37 -0400 Subject: [PATCH 55/77] removed none from state --- homeassistant/components/homekit/type_media_players.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 85af36df25793a..935dba6cd2c6de 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -331,7 +331,7 @@ def update_state(self, new_state): current_state = new_state.state # Power state television - hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN, 'None') + hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN) if not self._flag[CHAR_ACTIVE]: hk_state = 1 if hk_state else 0 _LOGGER.debug('%s: Set current active state to %s', From f9d1bdb86135b0123f6b2ccc20016c2b5d6a58b2 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:43:30 -0400 Subject: [PATCH 56/77] added flags for volume level --- .../components/homekit/type_media_players.py | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 935dba6cd2c6de..20cd7126ae26f3 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -5,8 +5,8 @@ from homeassistant.components.media_player import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, - ATTR_MEDIA_VOLUME_LEVEL ,SERVICE_SELECT_SOURCE, DOMAIN, SUPPORT_PAUSE, - SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + ATTR_MEDIA_VOLUME_LEVEL, SERVICE_SELECT_SOURCE, DOMAIN, SUPPORT_PAUSE, + SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_MEDIA_PAUSE, @@ -194,15 +194,16 @@ def __init__(self, *args): if features & (SUPPORT_PLAY | SUPPORT_PAUSE): self.chars_tv.append(CHAR_REMOTE_KEY) if features & SUPPORT_VOLUME_MUTE or features & SUPPORT_VOLUME_STEP: - self.chars_speaker.extend((CHAR_VOLUME, CHAR_VOLUME_CONTROL_TYPE, + self.chars_speaker.extend((CHAR_NAME, CHAR_ACTIVE, + CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR)) + if features & SUPPORT_VOLUME_SET: + self.support_volume_level = True + self.chars_speaker.append(CHAR_VOLUME) + if features & SUPPORT_SELECT_SOURCE: self.support_select_source = True - # TODO: find a place for these chars - if len(self.chars_speaker): - self.chars_speaker.extend((CHAR_NAME, CHAR_ACTIVE)) - serv_tv = self.add_preload_service(SERV_TELEVISION, self.chars_tv) self.set_primary_service(serv_tv) serv_tv.configure_char(CHAR_CONFIGURED_NAME, value=self.display_name) @@ -214,7 +215,7 @@ def __init__(self, *args): self.char_remote_key = serv_tv.configure_char( CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) - if CHAR_VOLUME in self.chars_speaker: + if CHAR_VOLUME_SELECTOR in self.chars_speaker: serv_speaker = self.add_preload_service( SERV_TELEVISION_SPEAKER, self.chars_speaker) serv_tv.add_linked_service(serv_speaker) @@ -226,14 +227,17 @@ def __init__(self, *args): self.char_mute = serv_speaker.configure_char( CHAR_MUTE, value=False, setter_callback=self.set_toggle_mute) - serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=1) - - self.char_volume = serv_speaker.configure_char( - CHAR_VOLUME, setter_callback=self.set_volume) + volume_control_type = 1 if self.support_volume_level else 2 + serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, + value=volume_control_type) self.char_volume_selector = serv_speaker.configure_char( CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) + if self.support_volume_level: + self.char_volume = serv_speaker.configure_char( + CHAR_VOLUME, setter_callback=self.set_volume) + if self.support_select_source: self.sources = self.hass.states.get(self.entity_id).attributes.get( ATTR_INPUT_SOURCE_LIST) @@ -339,8 +343,7 @@ def update_state(self, new_state): self.char_active.set_value(hk_state) self._flag[CHAR_ACTIVE] = False - # TODO: Add logic to detect if media player supports volume_level - if CHAR_VOLUME in self.chars_speaker: + if CHAR_VOLUME_SELECTOR in self.chars_speaker: current_mute_state = new_state.attributes.get( ATTR_MEDIA_VOLUME_MUTED) if not self._flag[FEATURE_TOGGLE_MUTE]: @@ -349,6 +352,7 @@ def update_state(self, new_state): self.char_mute.set_value(current_mute_state) self._flag[FEATURE_TOGGLE_MUTE] = False + if self.support_volume_level: current_voume_state = new_state.attributes.get( ATTR_MEDIA_VOLUME_LEVEL) if not self._flag[CHAR_VOLUME]: From d345013ba6ddc890cf3c8a9191e1ac9c84330d1f Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 22:53:54 -0400 Subject: [PATCH 57/77] fixed tests --- .../components/homekit/type_media_players.py | 2 +- .../homekit/test_type_media_players.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 20cd7126ae26f3..69e01be7e67531 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -355,7 +355,7 @@ def update_state(self, new_state): if self.support_volume_level: current_voume_state = new_state.attributes.get( ATTR_MEDIA_VOLUME_LEVEL) - if not self._flag[CHAR_VOLUME]: + if not self._flag[CHAR_VOLUME] and current_voume_state: _LOGGER.debug('%s: Set current volume to %s', self.entity_id, current_voume_state) self.char_volume.set_value(current_voume_state) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index d27f3886493c4f..53466f68d2462a 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -156,13 +156,13 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert acc.char_active.value == 0 assert acc.char_remote_key.value == 0 - assert acc.char_active_identifier.value == 0 - assert acc.char_toggle_mute.value is False + assert acc.char_input_source.value == 0 + assert acc.char_mute.value is False hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True}) await hass.async_block_till_done() assert acc.char_active.value == 1 - assert acc.char_toggle_mute.value is True + assert acc.char_mute.value is True hass.states.async_set(entity_id, STATE_OFF) await hass.async_block_till_done() @@ -170,11 +170,11 @@ async def test_media_player_television_set_state(hass, hk_driver, events): hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 2'}) await hass.async_block_till_done() - assert acc.char_active_identifier.value == 1 + assert acc.char_input_source.value == 1 hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 3'}) await hass.async_block_till_done() - assert acc.char_active_identifier.value == 2 + assert acc.char_input_source.value == 2 # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on') @@ -218,7 +218,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 4 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.char_toggle_mute.client_update_value, True) + await hass.async_add_job(acc.char_mute.client_update_value, True) await hass.async_block_till_done() assert call_toggle_mute assert call_toggle_mute[0].data[ATTR_ENTITY_ID] == entity_id @@ -226,7 +226,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 5 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.char_toggle_mute.client_update_value, False) + await hass.async_add_job(acc.char_mute.client_update_value, False) await hass.async_block_till_done() assert call_toggle_mute assert call_toggle_mute[1].data[ATTR_ENTITY_ID] == entity_id @@ -234,7 +234,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 6 assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.char_active_identifier.client_update_value, 1) + await hass.async_add_job(acc.char_input_source.client_update_value, 1) await hass.async_block_till_done() assert call_select_source assert call_select_source[0].data[ATTR_ENTITY_ID] == entity_id From 4e213d7982265add048fc509ff540b2ccd6435f6 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 23:16:01 -0400 Subject: [PATCH 58/77] added volume level tests --- .../components/homekit/type_media_players.py | 2 ++ .../homekit/test_type_media_players.py | 23 +++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 69e01be7e67531..bed903e93e5d9e 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -183,6 +183,8 @@ def __init__(self, *args): self._flag = {CHAR_ACTIVE: False, CHAR_ACTIVE_IDENTIFIER: False, FEATURE_TOGGLE_MUTE: False, CHAR_VOLUME: False} + self.support_select_source = False + self.support_volume_level = False # Add additional characteristics if volume or input selection supported self.chars_tv = [] diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 53466f68d2462a..4a62772e31193c 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -8,7 +8,7 @@ MediaPlayer, TelevisionMediaPlayer) from homeassistant.components.media_player.const import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, - ATTR_MEDIA_VOLUME_MUTED, DOMAIN) + ATTR_MEDIA_VOLUME_MUTED, ATTR_MEDIA_VOLUME_LEVEL, DOMAIN) from homeassistant.const import ( ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) @@ -256,4 +256,23 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 9 assert events[-1].data[ATTR_VALUE] is None - # TODO Add some tests to check volume char + +async def test_media_player_television_volume_level(hass, hk_driver, events): + """Test if television accessory and HA are updated accordingly.""" + entity_id = 'media_player.television' + + hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, + ATTR_SUPPORTED_FEATURES: 1420, + ATTR_MEDIA_VOLUME_MUTED: False, + }) + await hass.async_block_till_done() + acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, + None) + await hass.async_add_job(acc.run) + + assert acc.aid == 2 + assert acc.category == 31 # Television + + assert acc.char_active.value == 0 + assert acc.char_volume.value is 0 + assert acc.char_mute.value is False From 66e8fbc53b941f160608f09158682be13b95a164 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Tue, 30 Apr 2019 23:29:59 -0400 Subject: [PATCH 59/77] renamed setter for mute char --- homeassistant/components/homekit/type_media_players.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index bed903e93e5d9e..0acee00921549c 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -227,7 +227,7 @@ def __init__(self, *args): serv_speaker.configure_char(CHAR_ACTIVE, value=1) self.char_mute = serv_speaker.configure_char( - CHAR_MUTE, value=False, setter_callback=self.set_toggle_mute) + CHAR_MUTE, value=False, setter_callback=self.set_mute) volume_control_type = 1 if self.support_volume_level else 2 serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, @@ -280,7 +280,7 @@ def set_play_pause(self, value): params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) - def set_toggle_mute(self, value): + def set_mute(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "toggle_mute" to %s', self.entity_id, value) From d9e455141a5781a6b4ab3aad3b3ab4b752484d47 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 20:57:54 -0400 Subject: [PATCH 60/77] moved sources --- homeassistant/components/homekit/type_media_players.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 0acee00921549c..a99424248d09cc 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -186,10 +186,11 @@ def __init__(self, *args): self.support_select_source = False self.support_volume_level = False + self.sources = [] + # Add additional characteristics if volume or input selection supported self.chars_tv = [] self.chars_speaker = [] - self.sources = [] features = self.hass.states.get(self.entity_id) \ .attributes.get(ATTR_SUPPORTED_FEATURES, 0) From 3283548d421981a1ec38647e9ded525d9a963ae7 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 21:03:43 -0400 Subject: [PATCH 61/77] added comments for updating states from HA --- homeassistant/components/homekit/type_media_players.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index a99424248d09cc..59089e1fa9c771 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -346,6 +346,7 @@ def update_state(self, new_state): self.char_active.set_value(hk_state) self._flag[CHAR_ACTIVE] = False + # Set mute state if CHAR_VOLUME_SELECTOR in self.chars_speaker: current_mute_state = new_state.attributes.get( ATTR_MEDIA_VOLUME_MUTED) @@ -364,6 +365,7 @@ def update_state(self, new_state): self.char_volume.set_value(current_voume_state) self._flag[CHAR_VOLUME] = False + # Set active input if self.support_select_source: source_name = new_state.attributes.get(ATTR_INPUT_SOURCE) if self.sources and not self._flag[CHAR_ACTIVE_IDENTIFIER]: From c1fd16fe569a8961aa6cc4ec408c8ce402773a35 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 21:04:23 -0400 Subject: [PATCH 62/77] call play pause from set_remote_key --- .../components/homekit/type_media_players.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 59089e1fa9c771..ff83af998a7d59 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -273,14 +273,6 @@ def set_on_off(self, value): params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) - def set_play_pause(self, value): - """Move switch state to value if call came from HomeKit.""" - _LOGGER.debug('%s: Set switch state for "play_pause" to %s', - self.entity_id, value) - service = SERVICE_MEDIA_PLAY if value else SERVICE_MEDIA_PAUSE - params = {ATTR_ENTITY_ID: self.entity_id} - self.call_service(DOMAIN, service, params) - def set_mute(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "toggle_mute" to %s', @@ -325,11 +317,12 @@ def set_remote_key(self, value): if value in MEDIA_PLAYER_KEYS: service = MEDIA_PLAYER_KEYS[value] + # Handle Play Pause if service == SERVICE_MEDIA_PLAY_PAUSE: state = self.hass.states.get(self.entity_id).state if state in (STATE_PLAYING, STATE_PAUSED): - self.set_play_pause(state == STATE_PAUSED) - return + service = SERVICE_MEDIA_PLAY if value else + SERVICE_MEDIA_PAUSE params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) From 3c9923e4a195e90360bca2738d9a4aafdff69278 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 21:04:34 -0400 Subject: [PATCH 63/77] dont read volume level --- homeassistant/components/homekit/type_media_players.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index ff83af998a7d59..cb63bef2ac1914 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -349,15 +349,6 @@ def update_state(self, new_state): self.char_mute.set_value(current_mute_state) self._flag[FEATURE_TOGGLE_MUTE] = False - if self.support_volume_level: - current_voume_state = new_state.attributes.get( - ATTR_MEDIA_VOLUME_LEVEL) - if not self._flag[CHAR_VOLUME] and current_voume_state: - _LOGGER.debug('%s: Set current volume to %s', - self.entity_id, current_voume_state) - self.char_volume.set_value(current_voume_state) - self._flag[CHAR_VOLUME] = False - # Set active input if self.support_select_source: source_name = new_state.attributes.get(ATTR_INPUT_SOURCE) From ca72a8d18a7589d1ee119353d03968ec29e76a04 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 21:06:44 -0400 Subject: [PATCH 64/77] use in chars to check volume --- homeassistant/components/homekit/type_media_players.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index cb63bef2ac1914..1e69774e1047ac 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -237,7 +237,7 @@ def __init__(self, *args): self.char_volume_selector = serv_speaker.configure_char( CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) - if self.support_volume_level: + if CHAR_VOLUME in self.chars_speaker: self.char_volume = serv_speaker.configure_char( CHAR_VOLUME, setter_callback=self.set_volume) From c471b9456c121f5a4b7f6bbed158f94fad2b73ff Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 21:14:27 -0400 Subject: [PATCH 65/77] removed setting volume from homekit and parse state --- .../components/homekit/type_media_players.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 1e69774e1047ac..da7dd2b2b99ad8 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -182,7 +182,7 @@ def __init__(self, *args): super().__init__(*args, category=CATEGORY_TELEVISION) self._flag = {CHAR_ACTIVE: False, CHAR_ACTIVE_IDENTIFIER: False, - FEATURE_TOGGLE_MUTE: False, CHAR_VOLUME: False} + FEATURE_TOGGLE_MUTE: False} self.support_select_source = False self.support_volume_level = False @@ -282,15 +282,6 @@ def set_mute(self, value): ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) - def set_volume(self, value): - """Send volume step value if call came from HomeKit.""" - _LOGGER.debug('%s: Set volume to %s', self.entity_id, value) - - self._flag[CHAR_VOLUME] = True - params = {ATTR_ENTITY_ID: self.entity_id, - ATTR_MEDIA_VOLUME_LEVEL: value} - self.call_service(DOMAIN, SERVICE_VOLUME_SET, params) - def set_volume_step(self, value): """Send volume step value if call came from HomeKit.""" _LOGGER.debug('%s: Step volume by %s', From 8a9cba4e9794c49bf70f6eedfa2b72fa8254c30f Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 21:22:26 -0400 Subject: [PATCH 66/77] lint fixes --- tests/components/homekit/test_type_media_players.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 4a62772e31193c..26e6fc77bfec5c 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -8,7 +8,7 @@ MediaPlayer, TelevisionMediaPlayer) from homeassistant.components.media_player.const import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, - ATTR_MEDIA_VOLUME_MUTED, ATTR_MEDIA_VOLUME_LEVEL, DOMAIN) + ATTR_MEDIA_VOLUME_MUTED, DOMAIN) from homeassistant.const import ( ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) @@ -274,5 +274,5 @@ async def test_media_player_television_volume_level(hass, hk_driver, events): assert acc.category == 31 # Television assert acc.char_active.value == 0 - assert acc.char_volume.value is 0 + assert acc.char_volume.value == 0 assert acc.char_mute.value is False From 69c656c76ba50ee037e533bb2d6d5f4a32e81c8f Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Wed, 1 May 2019 23:23:47 -0400 Subject: [PATCH 67/77] fixed syntax --- homeassistant/components/homekit/type_media_players.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index da7dd2b2b99ad8..228a3108051e4a 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -312,8 +312,8 @@ def set_remote_key(self, value): if service == SERVICE_MEDIA_PLAY_PAUSE: state = self.hass.states.get(self.entity_id).state if state in (STATE_PLAYING, STATE_PAUSED): - service = SERVICE_MEDIA_PLAY if value else - SERVICE_MEDIA_PAUSE + service = SERVICE_MEDIA_PLAY if value else \ + SERVICE_MEDIA_PAUSE params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) From 8d6d7834493b2f8dc3e7256037e2ed0d8a9c32bf Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Thu, 2 May 2019 20:52:41 -0400 Subject: [PATCH 68/77] fixes --- .../components/homekit/type_media_players.py | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 228a3108051e4a..4267bb53922e41 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -184,7 +184,6 @@ def __init__(self, *args): self._flag = {CHAR_ACTIVE: False, CHAR_ACTIVE_IDENTIFIER: False, FEATURE_TOGGLE_MUTE: False} self.support_select_source = False - self.support_volume_level = False self.sources = [] @@ -215,8 +214,8 @@ def __init__(self, *args): CHAR_ACTIVE, setter_callback=self.set_on_off) if CHAR_REMOTE_KEY in self.chars_tv: - self.char_remote_key = serv_tv.configure_char( - CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) + serv_tv.configure_char(CHAR_REMOTE_KEY, + setter_callback=self.set_remote_key) if CHAR_VOLUME_SELECTOR in self.chars_speaker: serv_speaker = self.add_preload_service( @@ -230,20 +229,20 @@ def __init__(self, *args): self.char_mute = serv_speaker.configure_char( CHAR_MUTE, value=False, setter_callback=self.set_mute) - volume_control_type = 1 if self.support_volume_level else 2 + volume_control_type = 1 if CHAR_VOLUME in self.chars_speaker else 2 serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=volume_control_type) - self.char_volume_selector = serv_speaker.configure_char( - CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) + serv_speaker.configure_char(CHAR_VOLUME_SELECTOR, + setter_callback=self.set_volume_step) if CHAR_VOLUME in self.chars_speaker: - self.char_volume = serv_speaker.configure_char( - CHAR_VOLUME, setter_callback=self.set_volume) + serv_speaker.configure_char(CHAR_VOLUME, + setter_callback=self.set_volume) if self.support_select_source: - self.sources = self.hass.states.get(self.entity_id).attributes.get( - ATTR_INPUT_SOURCE_LIST) + self.sources = self.hass.states.get(self.entity_id) \ + .attributes.get(ATTR_INPUT_SOURCE_LIST) if not self.sources: return self.char_input_source = serv_tv.configure_char( @@ -282,11 +281,17 @@ def set_mute(self, value): ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) + def set_volume(self, value): + """Send volume step value if call came from HomeKit.""" + _LOGGER.debug('%s: Set volume to %s', self.entity_id, value) + params = {ATTR_ENTITY_ID: self.entity_id, + ATTR_MEDIA_VOLUME_LEVEL: value} + self.call_service(DOMAIN, SERVICE_VOLUME_SET, params) + def set_volume_step(self, value): """Send volume step value if call came from HomeKit.""" _LOGGER.debug('%s: Step volume by %s', self.entity_id, value) - service = SERVICE_VOLUME_DOWN if value else SERVICE_VOLUME_UP params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) @@ -295,7 +300,6 @@ def set_input_source(self, value): """Send input set value if call came from HomeKit.""" _LOGGER.debug('%s: Set active_identifer to %s', self.entity_id, value) - source = self.sources[value] self._flag[CHAR_ACTIVE_IDENTIFIER] = True params = {ATTR_ENTITY_ID: self.entity_id, @@ -305,7 +309,6 @@ def set_input_source(self, value): def set_remote_key(self, value): """Send remote key value if call came from HomeKit.""" _LOGGER.debug('%s: Set remote key to %s', self.entity_id, value) - if value in MEDIA_PLAYER_KEYS: service = MEDIA_PLAYER_KEYS[value] # Handle Play Pause From 59054e41b12afcd44040bfc9021d0c7029109da6 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Thu, 2 May 2019 20:52:58 -0400 Subject: [PATCH 69/77] fixed tests --- .../homekit/test_type_media_players.py | 68 ++----------------- 1 file changed, 5 insertions(+), 63 deletions(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 26e6fc77bfec5c..841924dc0b7c75 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -147,15 +147,14 @@ async def test_media_player_television_set_state(hass, hk_driver, events): 'HDMI 4'] }) await hass.async_block_till_done() - acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, - None) + acc = TelevisionMediaPlayer(hass, hk_driver, 'TelevisionMediaPlayer', + entity_id, 2, {}) await hass.async_add_job(acc.run) assert acc.aid == 2 assert acc.category == 31 # Television assert acc.char_active.value == 0 - assert acc.char_remote_key.value == 0 assert acc.char_input_source.value == 0 assert acc.char_mute.value is False @@ -179,12 +178,8 @@ async def test_media_player_television_set_state(hass, hk_driver, events): # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on') call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off') - call_media_play = async_mock_service(hass, DOMAIN, 'media_play') - call_media_pause = async_mock_service(hass, DOMAIN, 'media_pause') call_toggle_mute = async_mock_service(hass, DOMAIN, 'volume_mute') call_select_source = async_mock_service(hass, DOMAIN, 'select_source') - call_volume_up = async_mock_service(hass, DOMAIN, 'volume_up') - call_volume_down = async_mock_service(hass, DOMAIN, 'volume_down') await hass.async_add_job(acc.char_active.client_update_value, 1) await hass.async_block_till_done() @@ -200,30 +195,12 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 2 assert events[-1].data[ATTR_VALUE] is None - hass.states.async_set(entity_id, STATE_PAUSED) - await hass.async_block_till_done() - await hass.async_add_job(acc.char_remote_key.client_update_value, 11) - await hass.async_block_till_done() - assert call_media_play - assert call_media_play[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 3 - assert events[-1].data[ATTR_VALUE] is None - - hass.states.async_set(entity_id, STATE_PLAYING) - await hass.async_block_till_done() - await hass.async_add_job(acc.char_remote_key.client_update_value, 11) - await hass.async_block_till_done() - assert call_media_pause - assert call_media_pause[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 4 - assert events[-1].data[ATTR_VALUE] is None - await hass.async_add_job(acc.char_mute.client_update_value, True) await hass.async_block_till_done() assert call_toggle_mute assert call_toggle_mute[0].data[ATTR_ENTITY_ID] == entity_id assert call_toggle_mute[0].data[ATTR_MEDIA_VOLUME_MUTED] is True - assert len(events) == 5 + assert len(events) == 3 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_mute.client_update_value, False) @@ -231,7 +208,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_toggle_mute assert call_toggle_mute[1].data[ATTR_ENTITY_ID] == entity_id assert call_toggle_mute[1].data[ATTR_MEDIA_VOLUME_MUTED] is False - assert len(events) == 6 + assert len(events) == 4 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_input_source.client_update_value, 1) @@ -239,40 +216,5 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_select_source assert call_select_source[0].data[ATTR_ENTITY_ID] == entity_id assert call_select_source[0].data[ATTR_INPUT_SOURCE] == 'HDMI 2' - assert len(events) == 7 - assert events[-1].data[ATTR_VALUE] is None - - await hass.async_add_job(acc.char_volume_selector.client_update_value, 0) - await hass.async_block_till_done() - assert call_volume_up - assert call_volume_up[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 8 - assert events[-1].data[ATTR_VALUE] is None - - await hass.async_add_job(acc.char_volume_selector.client_update_value, 1) - await hass.async_block_till_done() - assert call_volume_down - assert call_volume_down[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 9 + assert len(events) == 5 assert events[-1].data[ATTR_VALUE] is None - - -async def test_media_player_television_volume_level(hass, hk_driver, events): - """Test if television accessory and HA are updated accordingly.""" - entity_id = 'media_player.television' - - hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, - ATTR_SUPPORTED_FEATURES: 1420, - ATTR_MEDIA_VOLUME_MUTED: False, - }) - await hass.async_block_till_done() - acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, - None) - await hass.async_add_job(acc.run) - - assert acc.aid == 2 - assert acc.category == 31 # Television - - assert acc.char_active.value == 0 - assert acc.char_volume.value == 0 - assert acc.char_mute.value is False From 41f60473b8465207b5f913287fc94d009cbcf34e Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Thu, 2 May 2019 21:01:14 -0400 Subject: [PATCH 70/77] removed volume flag --- homeassistant/components/homekit/type_media_players.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 4267bb53922e41..0de0f6ce9c31e8 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -199,9 +199,6 @@ def __init__(self, *args): self.chars_speaker.extend((CHAR_NAME, CHAR_ACTIVE, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR)) - if features & SUPPORT_VOLUME_SET: - self.support_volume_level = True - self.chars_speaker.append(CHAR_VOLUME) if features & SUPPORT_SELECT_SOURCE: self.support_select_source = True From 6db4e0e6312f2292f3dae821a1a81768b9cb1339 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Thu, 2 May 2019 22:38:43 -0400 Subject: [PATCH 71/77] missed one --- homeassistant/components/homekit/type_media_players.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 0de0f6ce9c31e8..559ccc30b4cecd 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -6,7 +6,7 @@ from homeassistant.components.media_player import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, ATTR_MEDIA_VOLUME_LEVEL, SERVICE_SELECT_SOURCE, DOMAIN, SUPPORT_PAUSE, - SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, + SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_MEDIA_PAUSE, From bc6172a2312633be9f85481bee00bfeceb644456 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Fri, 3 May 2019 09:05:32 -0400 Subject: [PATCH 72/77] added code coverage --- .../components/homekit/type_media_players.py | 20 +++--- .../homekit/test_type_media_players.py | 68 +++++++++++++++++-- 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 559ccc30b4cecd..f95db45ee8327b 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -6,7 +6,7 @@ from homeassistant.components.media_player import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_MUTED, ATTR_MEDIA_VOLUME_LEVEL, SERVICE_SELECT_SOURCE, DOMAIN, SUPPORT_PAUSE, - SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + SUPPORT_PLAY, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_MEDIA_PAUSE, @@ -199,6 +199,8 @@ def __init__(self, *args): self.chars_speaker.extend((CHAR_NAME, CHAR_ACTIVE, CHAR_VOLUME_CONTROL_TYPE, CHAR_VOLUME_SELECTOR)) + if features & SUPPORT_VOLUME_SET: + self.chars_speaker.append(CHAR_VOLUME) if features & SUPPORT_SELECT_SOURCE: self.support_select_source = True @@ -211,8 +213,8 @@ def __init__(self, *args): CHAR_ACTIVE, setter_callback=self.set_on_off) if CHAR_REMOTE_KEY in self.chars_tv: - serv_tv.configure_char(CHAR_REMOTE_KEY, - setter_callback=self.set_remote_key) + self.char_remote_key = serv_tv.configure_char( + CHAR_REMOTE_KEY, setter_callback=self.set_remote_key) if CHAR_VOLUME_SELECTOR in self.chars_speaker: serv_speaker = self.add_preload_service( @@ -230,12 +232,12 @@ def __init__(self, *args): serv_speaker.configure_char(CHAR_VOLUME_CONTROL_TYPE, value=volume_control_type) - serv_speaker.configure_char(CHAR_VOLUME_SELECTOR, - setter_callback=self.set_volume_step) + self.char_volume_selector = serv_speaker.configure_char( + CHAR_VOLUME_SELECTOR, setter_callback=self.set_volume_step) if CHAR_VOLUME in self.chars_speaker: - serv_speaker.configure_char(CHAR_VOLUME, - setter_callback=self.set_volume) + self.char_volume = serv_speaker.configure_char( + CHAR_VOLUME, setter_callback=self.set_volume) if self.support_select_source: self.sources = self.hass.states.get(self.entity_id) \ @@ -312,8 +314,8 @@ def set_remote_key(self, value): if service == SERVICE_MEDIA_PLAY_PAUSE: state = self.hass.states.get(self.entity_id).state if state in (STATE_PLAYING, STATE_PAUSED): - service = SERVICE_MEDIA_PLAY if value else \ - SERVICE_MEDIA_PAUSE + service = SERVICE_MEDIA_PLAY if state == STATE_PAUSED \ + else SERVICE_MEDIA_PAUSE params = {ATTR_ENTITY_ID: self.entity_id} self.call_service(DOMAIN, service, params) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 841924dc0b7c75..257ef18b1fef08 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -147,14 +147,15 @@ async def test_media_player_television_set_state(hass, hk_driver, events): 'HDMI 4'] }) await hass.async_block_till_done() - acc = TelevisionMediaPlayer(hass, hk_driver, 'TelevisionMediaPlayer', - entity_id, 2, {}) + acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, + None) await hass.async_add_job(acc.run) assert acc.aid == 2 assert acc.category == 31 # Television assert acc.char_active.value == 0 + assert acc.char_remote_key.value == 0 assert acc.char_input_source.value == 0 assert acc.char_mute.value is False @@ -178,8 +179,12 @@ async def test_media_player_television_set_state(hass, hk_driver, events): # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on') call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off') + call_media_play = async_mock_service(hass, DOMAIN, 'media_play') + call_media_pause = async_mock_service(hass, DOMAIN, 'media_pause') call_toggle_mute = async_mock_service(hass, DOMAIN, 'volume_mute') call_select_source = async_mock_service(hass, DOMAIN, 'select_source') + call_volume_up = async_mock_service(hass, DOMAIN, 'volume_up') + call_volume_down = async_mock_service(hass, DOMAIN, 'volume_down') await hass.async_add_job(acc.char_active.client_update_value, 1) await hass.async_block_till_done() @@ -195,12 +200,30 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 2 assert events[-1].data[ATTR_VALUE] is None + hass.states.async_set(entity_id, STATE_PLAYING) + await hass.async_block_till_done() + await hass.async_add_job(acc.char_remote_key.client_update_value, 11) + await hass.async_block_till_done() + assert call_media_pause + assert call_media_pause[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 3 + assert events[-1].data[ATTR_VALUE] is None + + hass.states.async_set(entity_id, STATE_PAUSED) + await hass.async_block_till_done() + await hass.async_add_job(acc.char_remote_key.client_update_value, 11) + await hass.async_block_till_done() + assert call_media_play + assert call_media_play[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 4 + assert events[-1].data[ATTR_VALUE] is None + await hass.async_add_job(acc.char_mute.client_update_value, True) await hass.async_block_till_done() assert call_toggle_mute assert call_toggle_mute[0].data[ATTR_ENTITY_ID] == entity_id assert call_toggle_mute[0].data[ATTR_MEDIA_VOLUME_MUTED] is True - assert len(events) == 3 + assert len(events) == 5 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_mute.client_update_value, False) @@ -208,7 +231,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_toggle_mute assert call_toggle_mute[1].data[ATTR_ENTITY_ID] == entity_id assert call_toggle_mute[1].data[ATTR_MEDIA_VOLUME_MUTED] is False - assert len(events) == 4 + assert len(events) == 6 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_input_source.client_update_value, 1) @@ -216,5 +239,40 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_select_source assert call_select_source[0].data[ATTR_ENTITY_ID] == entity_id assert call_select_source[0].data[ATTR_INPUT_SOURCE] == 'HDMI 2' - assert len(events) == 5 + assert len(events) == 7 assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.char_volume_selector.client_update_value, 0) + await hass.async_block_till_done() + assert call_volume_up + assert call_volume_up[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 8 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.char_volume_selector.client_update_value, 1) + await hass.async_block_till_done() + assert call_volume_down + assert call_volume_down[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 9 + assert events[-1].data[ATTR_VALUE] is None + + +async def test_media_player_television_volume_level(hass, hk_driver, events): + """Test if television accessory and HA are updated accordingly.""" + entity_id = 'media_player.television' + + hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, + ATTR_SUPPORTED_FEATURES: 1420, + ATTR_MEDIA_VOLUME_MUTED: False, + }) + await hass.async_block_till_done() + acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, + None) + await hass.async_add_job(acc.run) + + assert acc.aid == 2 + assert acc.category == 31 # Television + + assert acc.char_active.value == 0 + assert acc.char_volume.value == 0 + assert acc.char_mute.value is False From 20b415a108013a77dc0fa406ded566a15f28e381 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Fri, 3 May 2019 09:54:51 -0400 Subject: [PATCH 73/77] added volume level set test --- tests/components/homekit/test_type_media_players.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 257ef18b1fef08..4598e94c8c466d 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -7,7 +7,7 @@ from homeassistant.components.homekit.type_media_players import ( MediaPlayer, TelevisionMediaPlayer) from homeassistant.components.media_player.const import ( - ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, + ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_VOLUME_LEVEL, ATTR_MEDIA_VOLUME_MUTED, DOMAIN) from homeassistant.const import ( ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, STATE_IDLE, @@ -276,3 +276,14 @@ async def test_media_player_television_volume_level(hass, hk_driver, events): assert acc.char_active.value == 0 assert acc.char_volume.value == 0 assert acc.char_mute.value is False + + # Set from HomeKit + call_volume_set = async_mock_service(hass, DOMAIN, 'volume_set') + + await hass.async_add_job(acc.char_volume.client_update_value, 20) + await hass.async_block_till_done() + assert call_volume_set[0] + assert call_volume_set[0].data[ATTR_ENTITY_ID] == entity_id + assert call_volume_set[0].data[ATTR_MEDIA_VOLUME_LEVEL] == 20 + assert len(events) == 1 + assert events[-1].data[ATTR_VALUE] is None From 2aaccacc22d9f365ef23be3fc55ed5f5aaaabb3c Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Fri, 3 May 2019 10:49:21 -0400 Subject: [PATCH 74/77] test lack of input sources --- tests/components/homekit/test_type_media_players.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 4598e94c8c466d..6a29e254a7f62a 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -13,6 +13,7 @@ ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) +from pytest import raises from tests.common import async_mock_service @@ -262,7 +263,7 @@ async def test_media_player_television_volume_level(hass, hk_driver, events): entity_id = 'media_player.television' hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, - ATTR_SUPPORTED_FEATURES: 1420, + ATTR_SUPPORTED_FEATURES: 3468, ATTR_MEDIA_VOLUME_MUTED: False, }) await hass.async_block_till_done() @@ -277,6 +278,9 @@ async def test_media_player_television_volume_level(hass, hk_driver, events): assert acc.char_volume.value == 0 assert acc.char_mute.value is False + with raises(AttributeError, match="no attribute 'char_input_source'"): + acc.char_input_source + # Set from HomeKit call_volume_set = async_mock_service(hass, DOMAIN, 'volume_set') From d0651aaf2ab35f42e3a8370ed8b2ef9e3f372802 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sat, 4 May 2019 09:49:26 -0400 Subject: [PATCH 75/77] more changes --- .../components/homekit/type_media_players.py | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index f95db45ee8327b..c73eadc6f7c626 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -28,7 +28,7 @@ _LOGGER = logging.getLogger(__name__) -REMOTE_KEYS = { +MEDIA_PLAYER_KEYS = { 0: "Rewind", 1: "FastForward", 2: "NextTrack", @@ -40,11 +40,8 @@ 8: "Select", 9: "Back", 10: "Exit", - 15: "Information", -} - -MEDIA_PLAYER_KEYS = { 11: SERVICE_MEDIA_PLAY_PAUSE, + 15: "Information", } MODE_FRIENDLY_NAME = { @@ -182,7 +179,7 @@ def __init__(self, *args): super().__init__(*args, category=CATEGORY_TELEVISION) self._flag = {CHAR_ACTIVE: False, CHAR_ACTIVE_IDENTIFIER: False, - FEATURE_TOGGLE_MUTE: False} + CHAR_MUTE: False} self.support_select_source = False self.sources = [] @@ -275,7 +272,7 @@ def set_mute(self, value): """Move switch state to value if call came from HomeKit.""" _LOGGER.debug('%s: Set switch state for "toggle_mute" to %s', self.entity_id, value) - self._flag[FEATURE_TOGGLE_MUTE] = True + self._flag[CHAR_MUTE] = True params = {ATTR_ENTITY_ID: self.entity_id, ATTR_MEDIA_VOLUME_MUTED: value} self.call_service(DOMAIN, SERVICE_VOLUME_MUTE, params) @@ -308,8 +305,8 @@ def set_input_source(self, value): def set_remote_key(self, value): """Send remote key value if call came from HomeKit.""" _LOGGER.debug('%s: Set remote key to %s', self.entity_id, value) - if value in MEDIA_PLAYER_KEYS: - service = MEDIA_PLAYER_KEYS[value] + service = MEDIA_PLAYER_KEYS[value] + if service: # Handle Play Pause if service == SERVICE_MEDIA_PLAY_PAUSE: state = self.hass.states.get(self.entity_id).state @@ -326,7 +323,6 @@ def update_state(self, new_state): # Power state television hk_state = current_state not in (STATE_OFF, STATE_UNKNOWN) if not self._flag[CHAR_ACTIVE]: - hk_state = 1 if hk_state else 0 _LOGGER.debug('%s: Set current active state to %s', self.entity_id, hk_state) self.char_active.set_value(hk_state) @@ -336,11 +332,11 @@ def update_state(self, new_state): if CHAR_VOLUME_SELECTOR in self.chars_speaker: current_mute_state = new_state.attributes.get( ATTR_MEDIA_VOLUME_MUTED) - if not self._flag[FEATURE_TOGGLE_MUTE]: + if not self._flag[CHAR_MUTE]: _LOGGER.debug('%s: Set current mute state to %s', self.entity_id, current_mute_state) self.char_mute.set_value(current_mute_state) - self._flag[FEATURE_TOGGLE_MUTE] = False + self._flag[CHAR_MUTE] = False # Set active input if self.support_select_source: @@ -352,5 +348,7 @@ def update_state(self, new_state): index = self.sources.index(source_name) self.char_input_source.set_value(index) else: + _LOGGER.warning('%s: Sources out of sync. Please %s', + self.entity_id, 'restart HomeAssistant.') self.char_input_source.set_value(0) self._flag[CHAR_ACTIVE_IDENTIFIER] = False From 6c05622cea469a8f13437b1a8179a019ad9d4524 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Sat, 4 May 2019 12:18:10 -0400 Subject: [PATCH 76/77] added more tests --- .../components/homekit/type_media_players.py | 30 ++++--- .../homekit/test_type_media_players.py | 82 +++++++++++-------- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index c73eadc6f7c626..211147155d71e7 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -29,19 +29,19 @@ _LOGGER = logging.getLogger(__name__) MEDIA_PLAYER_KEYS = { - 0: "Rewind", - 1: "FastForward", - 2: "NextTrack", - 3: "PreviousTrack", - 4: "ArrowUp", - 5: "ArrowDown", - 6: "ArrowLeft", - 7: "ArrowRight", - 8: "Select", - 9: "Back", - 10: "Exit", + # 0: "Rewind", + # 1: "FastForward", + # 2: "NextTrack", + # 3: "PreviousTrack", + # 4: "ArrowUp", + # 5: "ArrowDown", + # 6: "ArrowLeft", + # 7: "ArrowRight", + # 8: "Select", + # 9: "Back", + # 10: "Exit", 11: SERVICE_MEDIA_PLAY_PAUSE, - 15: "Information", + # 15: "Information", } MODE_FRIENDLY_NAME = { @@ -238,9 +238,7 @@ def __init__(self, *args): if self.support_select_source: self.sources = self.hass.states.get(self.entity_id) \ - .attributes.get(ATTR_INPUT_SOURCE_LIST) - if not self.sources: - return + .attributes.get(ATTR_INPUT_SOURCE_LIST, []) self.char_input_source = serv_tv.configure_char( CHAR_ACTIVE_IDENTIFIER, setter_callback=self.set_input_source) for index, source in enumerate(self.sources): @@ -305,7 +303,7 @@ def set_input_source(self, value): def set_remote_key(self, value): """Send remote key value if call came from HomeKit.""" _LOGGER.debug('%s: Set remote key to %s', self.entity_id, value) - service = MEDIA_PLAYER_KEYS[value] + service = MEDIA_PLAYER_KEYS.get(value) if service: # Handle Play Pause if service == SERVICE_MEDIA_PLAY_PAUSE: diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 6a29e254a7f62a..03fd4ebf32a789 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -13,8 +13,6 @@ ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, STATE_IDLE, STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING) -from pytest import raises - from tests.common import async_mock_service @@ -140,13 +138,10 @@ async def test_media_player_television_set_state(hass, hk_driver, events): """Test if television accessory and HA are updated accordingly.""" entity_id = 'media_player.television' - hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, - ATTR_SUPPORTED_FEATURES: 3469, - ATTR_MEDIA_VOLUME_MUTED: False, - ATTR_INPUT_SOURCE_LIST: - ['HDMI 1', 'HDMI 2', 'HDMI 3', - 'HDMI 4'] - }) + hass.states.async_set(entity_id, None, { + ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, ATTR_SUPPORTED_FEATURES: 3469, + ATTR_MEDIA_VOLUME_MUTED: False, ATTR_INPUT_SOURCE_LIST: [ + 'HDMI 1', 'HDMI 2', 'HDMI 3', 'HDMI 4']}) await hass.async_block_till_done() acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, None) @@ -182,10 +177,13 @@ async def test_media_player_television_set_state(hass, hk_driver, events): call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off') call_media_play = async_mock_service(hass, DOMAIN, 'media_play') call_media_pause = async_mock_service(hass, DOMAIN, 'media_pause') + call_media_play_pause = async_mock_service(hass, DOMAIN, + 'media_play_pause') call_toggle_mute = async_mock_service(hass, DOMAIN, 'volume_mute') call_select_source = async_mock_service(hass, DOMAIN, 'select_source') call_volume_up = async_mock_service(hass, DOMAIN, 'volume_up') call_volume_down = async_mock_service(hass, DOMAIN, 'volume_down') + call_volume_set = async_mock_service(hass, DOMAIN, 'volume_set') await hass.async_add_job(acc.char_active.client_update_value, 1) await hass.async_block_till_done() @@ -201,13 +199,25 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert len(events) == 2 assert events[-1].data[ATTR_VALUE] is None + await hass.async_add_job(acc.char_remote_key.client_update_value, 11) + await hass.async_block_till_done() + assert call_media_play_pause + assert call_media_play_pause[0].data[ATTR_ENTITY_ID] == entity_id + assert len(events) == 3 + assert events[-1].data[ATTR_VALUE] is None + hass.states.async_set(entity_id, STATE_PLAYING) await hass.async_block_till_done() await hass.async_add_job(acc.char_remote_key.client_update_value, 11) await hass.async_block_till_done() assert call_media_pause assert call_media_pause[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 3 + assert len(events) == 4 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.char_remote_key.client_update_value, 10) + await hass.async_block_till_done() + assert len(events) == 4 assert events[-1].data[ATTR_VALUE] is None hass.states.async_set(entity_id, STATE_PAUSED) @@ -216,7 +226,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): await hass.async_block_till_done() assert call_media_play assert call_media_play[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 4 + assert len(events) == 5 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_mute.client_update_value, True) @@ -224,7 +234,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_toggle_mute assert call_toggle_mute[0].data[ATTR_ENTITY_ID] == entity_id assert call_toggle_mute[0].data[ATTR_MEDIA_VOLUME_MUTED] is True - assert len(events) == 5 + assert len(events) == 6 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_mute.client_update_value, False) @@ -232,7 +242,7 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_toggle_mute assert call_toggle_mute[1].data[ATTR_ENTITY_ID] == entity_id assert call_toggle_mute[1].data[ATTR_MEDIA_VOLUME_MUTED] is False - assert len(events) == 6 + assert len(events) == 7 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_input_source.client_update_value, 1) @@ -240,21 +250,29 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert call_select_source assert call_select_source[0].data[ATTR_ENTITY_ID] == entity_id assert call_select_source[0].data[ATTR_INPUT_SOURCE] == 'HDMI 2' - assert len(events) == 7 + assert len(events) == 8 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_volume_selector.client_update_value, 0) await hass.async_block_till_done() assert call_volume_up assert call_volume_up[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 8 + assert len(events) == 9 assert events[-1].data[ATTR_VALUE] is None await hass.async_add_job(acc.char_volume_selector.client_update_value, 1) await hass.async_block_till_done() assert call_volume_down assert call_volume_down[0].data[ATTR_ENTITY_ID] == entity_id - assert len(events) == 9 + assert len(events) == 10 + assert events[-1].data[ATTR_VALUE] is None + + await hass.async_add_job(acc.char_volume.client_update_value, 20) + await hass.async_block_till_done() + assert call_volume_set[0] + assert call_volume_set[0].data[ATTR_ENTITY_ID] == entity_id + assert call_volume_set[0].data[ATTR_MEDIA_VOLUME_LEVEL] == 20 + assert len(events) == 11 assert events[-1].data[ATTR_VALUE] is None @@ -262,10 +280,8 @@ async def test_media_player_television_volume_level(hass, hk_driver, events): """Test if television accessory and HA are updated accordingly.""" entity_id = 'media_player.television' - hass.states.async_set(entity_id, None, {ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, - ATTR_SUPPORTED_FEATURES: 3468, - ATTR_MEDIA_VOLUME_MUTED: False, - }) + hass.states.async_set(entity_id, None, { + ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, ATTR_SUPPORTED_FEATURES: 16769}) await hass.async_block_till_done() acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, None) @@ -275,19 +291,21 @@ async def test_media_player_television_volume_level(hass, hk_driver, events): assert acc.category == 31 # Television assert acc.char_active.value == 0 - assert acc.char_volume.value == 0 - assert acc.char_mute.value is False + assert acc.char_remote_key.value == 0 + assert acc.support_select_source is False + assert hasattr(acc, 'char_mute') is False + assert hasattr(acc, 'char_volume') is False + assert hasattr(acc, 'char_volume_selector') is False + assert hasattr(acc, 'char_input_source') is False - with raises(AttributeError, match="no attribute 'char_input_source'"): - acc.char_input_source + hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True}) + await hass.async_block_till_done() + assert acc.char_active.value == 1 - # Set from HomeKit - call_volume_set = async_mock_service(hass, DOMAIN, 'volume_set') + hass.states.async_set(entity_id, STATE_OFF) + await hass.async_block_till_done() + assert acc.char_active.value == 0 - await hass.async_add_job(acc.char_volume.client_update_value, 20) + hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 3'}) await hass.async_block_till_done() - assert call_volume_set[0] - assert call_volume_set[0].data[ATTR_ENTITY_ID] == entity_id - assert call_volume_set[0].data[ATTR_MEDIA_VOLUME_LEVEL] == 20 - assert len(events) == 1 - assert events[-1].data[ATTR_VALUE] is None + assert acc.char_active.value == 1 From 10a39679678011fc9be507621d464d24a6b21961 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Sun, 5 May 2019 12:15:39 +0200 Subject: [PATCH 77/77] Last changes --- .../components/homekit/type_media_players.py | 6 ++-- .../homekit/test_get_accessories.py | 24 ++++++++++++--- .../homekit/test_type_media_players.py | 29 ++++++++++--------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/homekit/type_media_players.py b/homeassistant/components/homekit/type_media_players.py index 211147155d71e7..b0c4be35e1b36d 100644 --- a/homeassistant/components/homekit/type_media_players.py +++ b/homeassistant/components/homekit/type_media_players.py @@ -292,7 +292,7 @@ def set_volume_step(self, value): def set_input_source(self, value): """Send input set value if call came from HomeKit.""" - _LOGGER.debug('%s: Set active_identifer to %s', + _LOGGER.debug('%s: Set current input to %s', self.entity_id, value) source = self.sources[value] self._flag[CHAR_ACTIVE_IDENTIFIER] = True @@ -346,7 +346,7 @@ def update_state(self, new_state): index = self.sources.index(source_name) self.char_input_source.set_value(index) else: - _LOGGER.warning('%s: Sources out of sync. Please %s', - self.entity_id, 'restart HomeAssistant.') + _LOGGER.warning('%s: Sources out of sync. ' + 'Restart HomeAssistant', self.entity_id) self.char_input_source.set_value(0) self._flag[CHAR_ACTIVE_IDENTIFIER] = False diff --git a/tests/components/homekit/test_get_accessories.py b/tests/components/homekit/test_get_accessories.py index fb46cf33404c21..a04f5906fefea8 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -59,10 +59,6 @@ def test_customize_options(config, name): ('Fan', 'fan.test', 'on', {}, {}), ('Light', 'light.test', 'on', {}, {}), ('Lock', 'lock.test', 'locked', {}, {ATTR_CODE: '1234'}), - ('MediaPlayer', 'media_player.test', 'on', - {ATTR_SUPPORTED_FEATURES: media_player_c.SUPPORT_TURN_ON | - media_player_c.SUPPORT_TURN_OFF}, {CONF_FEATURE_LIST: - {FEATURE_ON_OFF: None}}), ('SecuritySystem', 'alarm_control_panel.test', 'armed_away', {}, {ATTR_CODE: '1234'}), ('Thermostat', 'climate.test', 'auto', {}, {}), @@ -101,6 +97,26 @@ def test_type_covers(type_name, entity_id, state, attrs): assert mock_type.called +@pytest.mark.parametrize('type_name, entity_id, state, attrs, config', [ + ('MediaPlayer', 'media_player.test', 'on', + {ATTR_SUPPORTED_FEATURES: media_player_c.SUPPORT_TURN_ON | + media_player_c.SUPPORT_TURN_OFF}, {CONF_FEATURE_LIST: + {FEATURE_ON_OFF: None}}), + ('TelevisionMediaPlayer', 'media_player.tv', 'on', + {ATTR_DEVICE_CLASS: 'tv'}, {}), +]) +def test_type_media_player(type_name, entity_id, state, attrs, config): + """Test if media_player types are associated correctly.""" + mock_type = Mock() + with patch.dict(TYPES, {type_name: mock_type}): + entity_state = State(entity_id, state, attrs) + get_accessory(None, None, entity_state, 2, config) + assert mock_type.called + + if config: + assert mock_type.call_args[0][-1] == config + + @pytest.mark.parametrize('type_name, entity_id, state, attrs', [ ('BinarySensor', 'binary_sensor.opening', 'on', {ATTR_DEVICE_CLASS: 'opening'}), diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 03fd4ebf32a789..3c00867a2cfa3e 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -134,10 +134,12 @@ async def test_media_player_set_state(hass, hk_driver, events): assert events[-1].data[ATTR_VALUE] is None -async def test_media_player_television_set_state(hass, hk_driver, events): +async def test_media_player_television(hass, hk_driver, events, caplog): """Test if television accessory and HA are updated accordingly.""" entity_id = 'media_player.television' + # Supports 'select_source', 'volume_step', 'turn_on', 'turn_off', + # 'volume_mute', 'volume_set', 'pause' hass.states.async_set(entity_id, None, { ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, ATTR_SUPPORTED_FEATURES: 3469, ATTR_MEDIA_VOLUME_MUTED: False, ATTR_INPUT_SOURCE_LIST: [ @@ -172,6 +174,11 @@ async def test_media_player_television_set_state(hass, hk_driver, events): await hass.async_block_till_done() assert acc.char_input_source.value == 2 + hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 5'}) + await hass.async_block_till_done() + assert acc.char_input_source.value == 0 + assert caplog.records[-2].levelname == 'WARNING' + # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on') call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off') @@ -276,27 +283,21 @@ async def test_media_player_television_set_state(hass, hk_driver, events): assert events[-1].data[ATTR_VALUE] is None -async def test_media_player_television_volume_level(hass, hk_driver, events): - """Test if television accessory and HA are updated accordingly.""" +async def test_media_player_television_basic(hass, hk_driver, events, caplog): + """Test if basic television accessory and HA are updated accordingly.""" entity_id = 'media_player.television' + # Supports turn_on', 'turn_off' hass.states.async_set(entity_id, None, { - ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, ATTR_SUPPORTED_FEATURES: 16769}) + ATTR_DEVICE_CLASS: DEVICE_CLASS_TV, ATTR_SUPPORTED_FEATURES: 384}) await hass.async_block_till_done() acc = TelevisionMediaPlayer(hass, hk_driver, 'MediaPlayer', entity_id, 2, None) await hass.async_add_job(acc.run) - assert acc.aid == 2 - assert acc.category == 31 # Television - - assert acc.char_active.value == 0 - assert acc.char_remote_key.value == 0 + assert acc.chars_tv == [] + assert acc.chars_speaker == [] assert acc.support_select_source is False - assert hasattr(acc, 'char_mute') is False - assert hasattr(acc, 'char_volume') is False - assert hasattr(acc, 'char_volume_selector') is False - assert hasattr(acc, 'char_input_source') is False hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True}) await hass.async_block_till_done() @@ -309,3 +310,5 @@ async def test_media_player_television_volume_level(hass, hk_driver, events): hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: 'HDMI 3'}) await hass.async_block_till_done() assert acc.char_active.value == 1 + + assert 'Error' not in caplog.messages[-1]