Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions homeassistant/components/homekit/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
ATTR_MANUFACTURER = "manufacturer"
ATTR_MODEL = "model"
ATTR_SOFTWARE_VERSION = "sw_version"
ATTR_KEY_NAME = "key_name"

# #### Config ####
CONF_ADVERTISE_IP = "advertise_ip"
Expand Down Expand Up @@ -79,6 +80,7 @@

# #### 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"
Expand Down Expand Up @@ -228,6 +230,21 @@
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
Expand Down
72 changes: 48 additions & 24 deletions homeassistant/components/homekit/type_media_players.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

from .accessories import TYPES, HomeAccessory
from .const import (
ATTR_KEY_NAME,
CHAR_ACTIVE,
CHAR_ACTIVE_IDENTIFIER,
CHAR_CONFIGURED_NAME,
Expand All @@ -56,10 +57,24 @@
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,
Expand All @@ -70,19 +85,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",
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
Expand Down Expand Up @@ -363,19 +378,28 @@ 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.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(
Comment thread
nickw444 marked this conversation as resolved.
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):
Expand Down
19 changes: 19 additions & 0 deletions tests/components/homekit/test_type_media_players.py
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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)

Comment thread
nickw444 marked this conversation as resolved.
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."""
Expand Down