From bbfbdee65e4ee67b25bbdc7238788d2bcfb84c86 Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 2 Oct 2026 11:44:53 +0200 Subject: [PATCH] Fix Philips TV state on TVs where screenstate is always off (#183207) Co-authored-by: Claude Opus 5.5 --- .../components/philips_js/media_player.py | 15 ++++++++- .../philips_js/test_media_player.py | 33 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/philips_js/media_player.py b/homeassistant/components/philips_js/media_player.py index a8336a287b2c..43eac33fcdbb 100644 --- a/homeassistant/components/philips_js/media_player.py +++ b/homeassistant/components/philips_js/media_player.py @@ -456,11 +456,24 @@ class PhilipsTVMediaPlayer(PhilipsJsEntity, MediaPlayerEntity): self.media_content_type, self.media_content_id, None ) + @property + def _ambilight_idle(self) -> bool: + """Return True if ambilight reports no active configuration. + + Some TVs without a powerstate endpoint always report the screen as off, + but only return an ambilight configuration while the TV is on. + """ + if not self._tv.json_feature_supported("ambilight", "Ambilight"): + return True + return self._tv.ambilight_current_configuration is None + @callback def _update_from_coordinator(self): if self._tv.on: if self._tv.powerstate in ("Standby", "StandbyKeep") or ( - self._tv.powerstate is None and self._tv.screenstate == TV_STATE_OFF + self._tv.powerstate is None + and self._tv.screenstate == TV_STATE_OFF + and self._ambilight_idle ): self._attr_state = MediaPlayerState.OFF else: diff --git a/tests/components/philips_js/test_media_player.py b/tests/components/philips_js/test_media_player.py index 3a4425736347..a616a9f6a8b6 100644 --- a/tests/components/philips_js/test_media_player.py +++ b/tests/components/philips_js/test_media_player.py @@ -39,3 +39,36 @@ async def test_state( assert (state := hass.states.get(MOCK_ENTITY_ID)) assert state.state == expected_state + + +@pytest.mark.parametrize( + ("ambilight_configuration", "expected_state"), + [ + pytest.param(None, STATE_OFF, id="ambilight-idle"), + pytest.param( + {"styleName": "FOLLOW_VIDEO", "isExpert": False}, + STATE_ON, + id="ambilight-active", + ), + ], +) +async def test_state_screenstate_always_off( + hass: HomeAssistant, + mock_tv: PhilipsTV, + mock_config_entry: MockConfigEntry, + ambilight_configuration: dict[str, str | bool] | None, + expected_state: str, +) -> None: + """Test ambilight decides the state when screenstate is always off.""" + mock_tv.json_feature_supported.side_effect = lambda feature, value: ( + (feature, value) == ("ambilight", "Ambilight") + ) + mock_tv.powerstate = None + mock_tv.screenstate = TV_STATE_OFF + mock_tv.ambilight_current_configuration = ambilight_configuration + + assert await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert (state := hass.states.get(MOCK_ENTITY_ID)) + assert state.state == expected_state