Skip to content

Commit 0ba55c3

Browse files
oddstr13frenck
authored andcommitted
Fix ESPHome entities unavailable if deep sleep enabled after entry setup (home-assistant#144970)
1 parent 19b7cfb commit 0ba55c3

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

homeassistant/components/esphome/entity.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ def __init__(
223223
self._states = cast(dict[int, _StateT], entry_data.state[state_type])
224224
assert entry_data.device_info is not None
225225
device_info = entry_data.device_info
226-
self._device_info = device_info
227226
self._on_entry_data_changed()
228227
self._key = entity_info.key
229228
self._state_type = state_type
@@ -311,6 +310,11 @@ def _on_state_update(self) -> None:
311310
@callback
312311
def _on_entry_data_changed(self) -> None:
313312
entry_data = self._entry_data
313+
# Update the device info since it can change
314+
# when the device is reconnected
315+
if TYPE_CHECKING:
316+
assert entry_data.device_info is not None
317+
self._device_info = entry_data.device_info
314318
self._api_version = entry_data.api_version
315319
self._client = entry_data.client
316320
if self._device_info.has_deep_sleep:

tests/components/esphome/test_entity.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
"""Test ESPHome binary sensors."""
22

33
import asyncio
4+
from dataclasses import asdict
45
from typing import Any
56
from unittest.mock import AsyncMock
67

78
from aioesphomeapi import (
89
APIClient,
910
BinarySensorInfo,
1011
BinarySensorState,
12+
DeviceInfo,
1113
SensorInfo,
1214
SensorState,
1315
build_unique_id,
@@ -665,3 +667,63 @@ async def test_entity_id_preserved_on_upgrade_when_in_storage(
665667
)
666668
state = hass.states.get("binary_sensor.user_named")
667669
assert state is not None
670+
671+
672+
async def test_deep_sleep_added_after_setup(
673+
hass: HomeAssistant,
674+
mock_client: APIClient,
675+
mock_esphome_device: MockESPHomeDeviceType,
676+
) -> None:
677+
"""Test deep sleep added after setup."""
678+
mock_device = await mock_esphome_device(
679+
mock_client=mock_client,
680+
entity_info=[
681+
BinarySensorInfo(
682+
object_id="test",
683+
key=1,
684+
name="test",
685+
unique_id="test",
686+
),
687+
],
688+
user_service=[],
689+
states=[
690+
BinarySensorState(key=1, state=True, missing_state=False),
691+
],
692+
device_info={"has_deep_sleep": False},
693+
)
694+
695+
entity_id = "binary_sensor.test_test"
696+
state = hass.states.get(entity_id)
697+
assert state is not None
698+
assert state.state == STATE_ON
699+
700+
await mock_device.mock_disconnect(expected_disconnect=True)
701+
702+
# No deep sleep, should be unavailable
703+
state = hass.states.get(entity_id)
704+
assert state is not None
705+
assert state.state == STATE_UNAVAILABLE
706+
707+
await mock_device.mock_connect()
708+
709+
# reconnect, should be available
710+
state = hass.states.get(entity_id)
711+
assert state is not None
712+
assert state.state == STATE_ON
713+
714+
await mock_device.mock_disconnect(expected_disconnect=True)
715+
new_device_info = DeviceInfo(
716+
**{**asdict(mock_device.device_info), "has_deep_sleep": True}
717+
)
718+
mock_device.client.device_info = AsyncMock(return_value=new_device_info)
719+
mock_device.device_info = new_device_info
720+
721+
await mock_device.mock_connect()
722+
723+
# Now disconnect that deep sleep is set in device info
724+
await mock_device.mock_disconnect(expected_disconnect=True)
725+
726+
# Deep sleep, should be available
727+
state = hass.states.get(entity_id)
728+
assert state is not None
729+
assert state.state == STATE_ON

0 commit comments

Comments
 (0)