Only reflect unavailable state in DSMR when disconnected (#84862)

* Only reflect unavailable state in DSMR when disonnected

* Addressreview comment
This commit is contained in:
Franck Nijhof 2022-12-30 19:08:11 +01:00 committed by GitHub
parent f8fa676ac8
commit 02f64ada2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 8 deletions

View file

@ -401,7 +401,7 @@ async def async_setup_entry(
)
@Throttle(min_time_between_updates)
def update_entities_telegram(telegram: dict[str, DSMRObject]) -> None:
def update_entities_telegram(telegram: dict[str, DSMRObject] | None) -> None:
"""Update entities with latest telegram and trigger state update."""
# Make all device entities aware of new telegram
for entity in entities:
@ -445,6 +445,11 @@ async def async_setup_entry(
while hass.state == CoreState.not_running or hass.is_running:
# Start DSMR asyncio.Protocol reader
# Reflect connected state in devices state by setting an
# empty telegram resulting in `unknown` states
update_entities_telegram({})
try:
transport, protocol = await hass.loop.create_task(reader_factory())
@ -472,8 +477,8 @@ async def async_setup_entry(
protocol = None
# Reflect disconnect state in devices state by setting an
# empty telegram resulting in `unknown` states
update_entities_telegram({})
# None telegram resulting in `unavailable` states
update_entities_telegram(None)
# throttle reconnect attempts
await asyncio.sleep(
@ -487,11 +492,19 @@ async def async_setup_entry(
transport = None
protocol = None
# Reflect disconnect state in devices state by setting an
# None telegram resulting in `unavailable` states
update_entities_telegram(None)
# throttle reconnect attempts
await asyncio.sleep(
entry.data.get(CONF_RECONNECT_INTERVAL, DEFAULT_RECONNECT_INTERVAL)
)
except CancelledError:
# Reflect disconnect state in devices state by setting an
# None telegram resulting in `unavailable` states
update_entities_telegram(None)
if stop_listener and (
hass.state == CoreState.not_running or hass.is_running
):
@ -534,7 +547,7 @@ class DSMREntity(SensorEntity):
"""Initialize entity."""
self.entity_description = entity_description
self._entry = entry
self.telegram: dict[str, DSMRObject] = {}
self.telegram: dict[str, DSMRObject] | None = {}
device_serial = entry.data[CONF_SERIAL_ID]
device_name = DEVICE_NAME_ELECTRICITY
@ -551,16 +564,21 @@ class DSMREntity(SensorEntity):
self._attr_unique_id = f"{device_serial}_{entity_description.key}"
@callback
def update_data(self, telegram: dict[str, DSMRObject]) -> None:
def update_data(self, telegram: dict[str, DSMRObject] | None) -> None:
"""Update data."""
self.telegram = telegram
if self.hass and self.entity_description.obis_reference in self.telegram:
if self.hass and (
telegram is None or self.entity_description.obis_reference in telegram
):
self.async_write_ha_state()
def get_dsmr_object_attr(self, attribute: str) -> str | None:
"""Read attribute from last received telegram for this DSMR object."""
# Make sure telegram contains an object for this entities obis
if self.entity_description.obis_reference not in self.telegram:
if (
self.telegram is None
or self.entity_description.obis_reference not in self.telegram
):
return None
# Get the attribute value if the object has it
@ -571,7 +589,7 @@ class DSMREntity(SensorEntity):
@property
def available(self) -> bool:
"""Entity is only available if there is a telegram."""
return bool(self.telegram)
return self.telegram is not None
@property
def native_value(self) -> StateType:

View file

@ -24,6 +24,7 @@ from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
ENERGY_KILO_WATT_HOUR,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
VOLUME_CUBIC_METERS,
UnitOfPower,
)
@ -783,6 +784,10 @@ async def test_reconnect(hass, dsmr_connection_fixture):
assert connection_factory.call_count == 1
state = hass.states.get("sensor.electricity_meter_power_consumption")
assert state
assert state.state == STATE_UNKNOWN
# indicate disconnect, release wait lock and allow reconnect to happen
closed.set()
# wait for lock set to resolve