Fire events on homekit TV remote key press (#29588)

* Fire events on homekit TV remote key press

* Changes from code review

* black

* isort

* flake8

* Update tests/components/homekit/test_type_media_players.py

Co-authored-by: J. Nick Koston <nick@koston.org>

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Nick Whyte 2020-05-19 23:11:04 +10:00 committed by GitHub
parent 2b38df2766
commit a51372f7b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 24 deletions

View File

@ -27,6 +27,7 @@ ATTR_INTERGRATION = "platform"
ATTR_MANUFACTURER = "manufacturer"
ATTR_MODEL = "model"
ATTR_SOFTWARE_VERSION = "sw_version"
ATTR_KEY_NAME = "key_name"
# #### Config ####
CONF_ADVERTISE_IP = "advertise_ip"
@ -79,6 +80,7 @@ FEATURE_TOGGLE_MUTE = "toggle_mute"
# #### HomeKit Component Event ####
EVENT_HOMEKIT_CHANGED = "homekit_state_change"
EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED = "homekit_tv_remote_key_pressed"
# #### HomeKit Component Services ####
SERVICE_HOMEKIT_START = "start"
@ -228,6 +230,21 @@ THRESHOLD_CO2 = 1000
DEFAULT_MIN_TEMP_WATER_HEATER = 40 # °C
DEFAULT_MAX_TEMP_WATER_HEATER = 60 # °C
# #### Media Player Key Names ####
KEY_ARROW_DOWN = "arrow_down"
KEY_ARROW_LEFT = "arrow_left"
KEY_ARROW_RIGHT = "arrow_right"
KEY_ARROW_UP = "arrow_up"
KEY_BACK = "back"
KEY_EXIT = "exit"
KEY_FAST_FORWARD = "fast_forward"
KEY_INFORMATION = "information"
KEY_NEXT_TRACK = "next_track"
KEY_PREVIOUS_TRACK = "previous_track"
KEY_REWIND = "rewind"
KEY_SELECT = "select"
KEY_PLAY_PAUSE = "play_pause"
# #### Door states ####
HK_DOOR_OPEN = 0
HK_DOOR_CLOSED = 1

View File

@ -40,6 +40,7 @@ from homeassistant.core import callback
from .accessories import TYPES, HomeAccessory
from .const import (
ATTR_KEY_NAME,
CHAR_ACTIVE,
CHAR_ACTIVE_IDENTIFIER,
CHAR_CONFIGURED_NAME,
@ -56,10 +57,24 @@ from .const import (
CHAR_VOLUME_CONTROL_TYPE,
CHAR_VOLUME_SELECTOR,
CONF_FEATURE_LIST,
EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED,
FEATURE_ON_OFF,
FEATURE_PLAY_PAUSE,
FEATURE_PLAY_STOP,
FEATURE_TOGGLE_MUTE,
KEY_ARROW_DOWN,
KEY_ARROW_LEFT,
KEY_ARROW_RIGHT,
KEY_ARROW_UP,
KEY_BACK,
KEY_EXIT,
KEY_FAST_FORWARD,
KEY_INFORMATION,
KEY_NEXT_TRACK,
KEY_PLAY_PAUSE,
KEY_PREVIOUS_TRACK,
KEY_REWIND,
KEY_SELECT,
SERV_INPUT_SOURCE,
SERV_SWITCH,
SERV_TELEVISION,
@ -70,19 +85,19 @@ from .util import get_media_player_features
_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",
11: SERVICE_MEDIA_PLAY_PAUSE,
# 15: "Information",
0: KEY_REWIND,
1: KEY_FAST_FORWARD,
2: KEY_NEXT_TRACK,
3: KEY_PREVIOUS_TRACK,
4: KEY_ARROW_UP,
5: KEY_ARROW_DOWN,
6: KEY_ARROW_LEFT,
7: KEY_ARROW_RIGHT,
8: KEY_SELECT,
9: KEY_BACK,
10: KEY_EXIT,
11: KEY_PLAY_PAUSE,
15: KEY_INFORMATION,
}
# Names may not contain special characters
@ -363,19 +378,28 @@ class TelevisionMediaPlayer(HomeAccessory):
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.get(value)
if service:
# 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):
service = (
SERVICE_MEDIA_PLAY
if state == STATE_PAUSED
else SERVICE_MEDIA_PAUSE
)
key_name = MEDIA_PLAYER_KEYS.get(value)
if key_name is None:
_LOGGER.warning("%s: Unhandled key press for %s", self.entity_id, value)
return
if key_name == KEY_PLAY_PAUSE:
# Handle Play Pause by directly updating the media player entity.
state = self.hass.states.get(self.entity_id).state
if state in (STATE_PLAYING, STATE_PAUSED):
service = (
SERVICE_MEDIA_PLAY if state == STATE_PAUSED else SERVICE_MEDIA_PAUSE
)
else:
service = SERVICE_MEDIA_PLAY_PAUSE
params = {ATTR_ENTITY_ID: self.entity_id}
self.call_service(DOMAIN, service, params)
else:
# Other keys can be handled by listening to the event bus
self.hass.bus.fire(
EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED,
{ATTR_KEY_NAME: key_name, ATTR_ENTITY_ID: self.entity_id},
)
@callback
def async_update_state(self, new_state):

View File

@ -1,12 +1,15 @@
"""Test different accessory types: Media Players."""
from homeassistant.components.homekit.const import (
ATTR_KEY_NAME,
ATTR_VALUE,
CONF_FEATURE_LIST,
EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED,
FEATURE_ON_OFF,
FEATURE_PLAY_PAUSE,
FEATURE_PLAY_STOP,
FEATURE_TOGGLE_MUTE,
KEY_ARROW_RIGHT,
)
from homeassistant.components.homekit.type_media_players import (
MediaPlayer,
@ -342,6 +345,22 @@ async def test_media_player_television(hass, hk_driver, events, caplog):
assert len(events) == 11
assert events[-1].data[ATTR_VALUE] is None
events = []
def listener(event):
events.append(event)
hass.bus.async_listen(EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED, listener)
await hass.async_add_executor_job(acc.char_remote_key.client_update_value, 20)
await hass.async_block_till_done()
await hass.async_add_executor_job(acc.char_remote_key.client_update_value, 7)
await hass.async_block_till_done()
assert len(events) == 1
assert events[0].data[ATTR_KEY_NAME] == KEY_ARROW_RIGHT
async def test_media_player_television_basic(hass, hk_driver, events, caplog):
"""Test if basic television accessory and HA are updated accordingly."""