Enforce MediaPlayerState in hdmi_cec media player (#78522)

pull/78549/head
epenet 2022-09-15 17:48:05 +02:00 committed by GitHub
parent 7d11509011
commit b29605060a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 66 deletions

View File

@ -17,11 +17,6 @@ from pycec.const import (
KEY_MUTE_TOGGLE,
KEY_VOLUME_DOWN,
KEY_VOLUME_UP,
POWER_OFF,
POWER_ON,
STATUS_PLAY,
STATUS_STILL,
STATUS_STOP,
)
from pycec.network import HDMINetwork, PhysicalAddress
from pycec.tcp import TcpAdapter
@ -35,12 +30,6 @@ from homeassistant.const import (
CONF_PLATFORM,
EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP,
STATE_IDLE,
STATE_OFF,
STATE_ON,
STATE_PAUSED,
STATE_PLAYING,
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import discovery, event
@ -382,7 +371,6 @@ class CecEntity(Entity):
def __init__(self, device, logical) -> None:
"""Initialize the device."""
self._device = device
self._state: str | None = None
self._logical_address = logical
self.entity_id = "%s.%d" % (DOMAIN, self._logical_address)
self._set_attr_name()
@ -405,27 +393,9 @@ class CecEntity(Entity):
self._attr_name = f"{self._device.type_name} {self._logical_address} ({self._device.osd_name})"
def _hdmi_cec_unavailable(self, callback_event):
# Change state to unavailable. Without this, entity would remain in
# its last state, since the state changes are pushed.
self._state = STATE_UNAVAILABLE
self._attr_available = False
self.schedule_update_ha_state(False)
def update(self):
"""Update device status."""
device = self._device
if device.power_status in [POWER_OFF, 3]:
self._state = STATE_OFF
elif device.status == STATUS_PLAY:
self._state = STATE_PLAYING
elif device.status == STATUS_STOP:
self._state = STATE_IDLE
elif device.status == STATUS_STILL:
self._state = STATE_PAUSED
elif device.power_status in [POWER_ON, 4]:
self._state = STATE_ON
else:
_LOGGER.warning("Unknown state: %d", device.power_status)
async def async_added_to_hass(self):
"""Register HDMI callbacks after initialization."""
self._device.set_update_callback(self._update)
@ -435,6 +405,7 @@ class CecEntity(Entity):
def _update(self, device=None):
"""Device status changed, schedule an update."""
self._attr_available = True
self.schedule_update_ha_state(True)
@property

View File

@ -89,7 +89,7 @@ class CecPlayerEntity(CecEntity, MediaPlayerEntity):
def turn_on(self) -> None:
"""Turn device on."""
self._device.turn_on()
self._state = MediaPlayerState.ON
self._attr_state = MediaPlayerState.ON
def clear_playlist(self) -> None:
"""Clear players playlist."""
@ -98,12 +98,12 @@ class CecPlayerEntity(CecEntity, MediaPlayerEntity):
def turn_off(self) -> None:
"""Turn device off."""
self._device.turn_off()
self._state = MediaPlayerState.OFF
self._attr_state = MediaPlayerState.OFF
def media_stop(self) -> None:
"""Stop playback."""
self.send_keypress(KEY_STOP)
self._state = MediaPlayerState.IDLE
self._attr_state = MediaPlayerState.IDLE
def play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None:
"""Not supported."""
@ -124,7 +124,7 @@ class CecPlayerEntity(CecEntity, MediaPlayerEntity):
def media_pause(self) -> None:
"""Pause playback."""
self.send_keypress(KEY_PAUSE)
self._state = MediaPlayerState.PAUSED
self._attr_state = MediaPlayerState.PAUSED
def select_source(self, source: str) -> None:
"""Not supported."""
@ -133,7 +133,7 @@ class CecPlayerEntity(CecEntity, MediaPlayerEntity):
def media_play(self) -> None:
"""Start playback."""
self.send_keypress(KEY_PLAY)
self._state = MediaPlayerState.PLAYING
self._attr_state = MediaPlayerState.PLAYING
def volume_up(self) -> None:
"""Increase volume."""
@ -145,25 +145,20 @@ class CecPlayerEntity(CecEntity, MediaPlayerEntity):
_LOGGER.debug("%s: volume down", self._logical_address)
self.send_keypress(KEY_VOLUME_DOWN)
@property
def state(self) -> str | None:
"""Cache state of device."""
return self._state
def update(self) -> None:
"""Update device status."""
device = self._device
if device.power_status in [POWER_OFF, 3]:
self._state = MediaPlayerState.OFF
self._attr_state = MediaPlayerState.OFF
elif not self.support_pause:
if device.power_status in [POWER_ON, 4]:
self._state = MediaPlayerState.ON
self._attr_state = MediaPlayerState.ON
elif device.status == STATUS_PLAY:
self._state = MediaPlayerState.PLAYING
self._attr_state = MediaPlayerState.PLAYING
elif device.status == STATUS_STOP:
self._state = MediaPlayerState.IDLE
self._attr_state = MediaPlayerState.IDLE
elif device.status == STATUS_STILL:
self._state = MediaPlayerState.PAUSED
self._attr_state = MediaPlayerState.PAUSED
else:
_LOGGER.warning("Unknown state: %s", device.status)

View File

@ -4,8 +4,9 @@ from __future__ import annotations
import logging
from typing import Any
from pycec.const import POWER_OFF, POWER_ON
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN, SwitchEntity
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
@ -44,16 +45,21 @@ class CecSwitchEntity(CecEntity, SwitchEntity):
def turn_on(self, **kwargs: Any) -> None:
"""Turn device on."""
self._device.turn_on()
self._state = STATE_ON
self._attr_is_on = True
self.schedule_update_ha_state(force_refresh=False)
def turn_off(self, **kwargs: Any) -> None:
"""Turn device off."""
self._device.turn_off()
self._state = STATE_OFF
self._attr_is_on = False
self.schedule_update_ha_state(force_refresh=False)
@property
def is_on(self) -> bool:
"""Return True if entity is on."""
return self._state == STATE_ON
def update(self) -> None:
"""Update device status."""
device = self._device
if device.power_status in {POWER_OFF, 3}:
self._attr_is_on = False
elif device.power_status in {POWER_ON, 4}:
self._attr_is_on = True
else:
_LOGGER.warning("Unknown state: %d", device.power_status)

View File

@ -1,15 +1,9 @@
"""Tests for the HDMI-CEC switch platform."""
from pycec.const import POWER_OFF, POWER_ON, STATUS_PLAY, STATUS_STILL, STATUS_STOP
from pycec.network import PhysicalAddress
import pytest
from homeassistant.components.hdmi_cec import (
EVENT_HDMI_CEC_UNAVAILABLE,
POWER_OFF,
POWER_ON,
STATUS_PLAY,
STATUS_STILL,
STATUS_STOP,
PhysicalAddress,
)
from homeassistant.components.hdmi_cec import EVENT_HDMI_CEC_UNAVAILABLE
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.const import (
ATTR_ENTITY_ID,
@ -20,7 +14,7 @@ from homeassistant.const import (
STATE_UNAVAILABLE,
)
from tests.components.hdmi_cec import MockHDMIDevice
from . import MockHDMIDevice
@pytest.mark.parametrize("config", [{}, {"platform": "switch"}])
@ -236,9 +230,6 @@ async def test_icon(
assert state.attributes["icon"] == expected_icon
@pytest.mark.xfail(
reason="The code only sets the state to unavailable, doesn't set the `_attr_available` to false."
)
async def test_unavailable_status(hass, create_hdmi_network, create_cec_entity):
"""Test entity goes into unavailable status when expected."""
hdmi_network = await create_hdmi_network()