Enforce MediaPlayerState in hdmi_cec media player (#78522)
parent
7d11509011
commit
b29605060a
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue