From 83300bc68495c800f4f98b418b1e9d4d0497a997 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Tue, 29 Sep 2026 23:32:14 -0700 Subject: [PATCH] =?UTF-8?q?Fix=20alert=20not=20firing=20when=20the=20watch?= =?UTF-8?q?ed=20entity=20is=20already=20in=20the=20alert=20=E2=80=A6=20(#1?= =?UTF-8?q?81218)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastian Messmer <2373925+smessmer@users.noreply.github.com> --- homeassistant/components/alert/entity.py | 12 +++++++++++ tests/components/alert/test_init.py | 26 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/homeassistant/components/alert/entity.py b/homeassistant/components/alert/entity.py index 1e47742794d8..4e70ee8944b4 100644 --- a/homeassistant/components/alert/entity.py +++ b/homeassistant/components/alert/entity.py @@ -72,12 +72,24 @@ class AlertEntity(Entity): self._ack = False self._cancel: Callable[[], None] | None = None self._send_done_message = False + self._watched_entity_id = watched_entity_id self.entity_id = f"{DOMAIN}.{entity_id}" async_track_state_change_event( hass, [watched_entity_id], self.watched_entity_change ) + @override + async def async_added_to_hass(self) -> None: + """Start alerting if the watched entity is already in the alert state.""" + await super().async_added_to_hass() + if ( + (state := self.hass.states.get(self._watched_entity_id)) is not None + and state.state == self._alert_state + and not self._firing + ): + await self.begin_alerting() + @property @override def state(self) -> str: diff --git a/tests/components/alert/test_init.py b/tests/components/alert/test_init.py index cdeee9fa39c6..e3408ec8cf7f 100644 --- a/tests/components/alert/test_init.py +++ b/tests/components/alert/test_init.py @@ -94,6 +94,32 @@ async def test_fire(hass: HomeAssistant, mock_notifier: list[ServiceCall]) -> No assert hass.states.get(ENTITY_ID).state == STATE_ON +async def test_fire_when_already_in_alert_state( + hass: HomeAssistant, mock_notifier: list[ServiceCall] +) -> None: + """Test the alert fires if the watched entity is already in the alert state. + + This is the case after a restart when the watched entity's state is + restored before the alert subscribes to state changes. + """ + hass.states.async_set("sensor.test", STATE_ON) + assert await async_setup_component(hass, DOMAIN, TEST_CONFIG) + await hass.async_block_till_done() + assert hass.states.get(ENTITY_ID).state == STATE_ON + assert len(mock_notifier) == 1 + + +async def test_idle_when_already_not_in_alert_state( + hass: HomeAssistant, mock_notifier: list[ServiceCall] +) -> None: + """Test the alert stays idle if the watched entity is not in the alert state.""" + hass.states.async_set("sensor.test", STATE_OFF) + assert await async_setup_component(hass, DOMAIN, TEST_CONFIG) + await hass.async_block_till_done() + assert hass.states.get(ENTITY_ID).state == STATE_IDLE + assert len(mock_notifier) == 0 + + async def test_silence(hass: HomeAssistant, mock_notifier: list[ServiceCall]) -> None: """Test silencing the alert.""" assert await async_setup_component(hass, DOMAIN, TEST_CONFIG)