Coverage for custom_components/supernotify/sensor.py: 97%
39 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-09-25 14:29 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-09-25 14:29 +0000
1"""Sensor platform: the notification/failure counters as real, restorable entities.
3The two SupernotifyCounterSensor entities are created by SupernotifyEngine itself (so they exist,
4and count, even before this platform loads, or without a config entry at all) and just handed to
5Home Assistant here. They are the single home of the counts - the engine has no separate copy -
6and being RestoreSensors, the counts survive a Home Assistant restart.
7"""
9from __future__ import annotations
11from typing import TYPE_CHECKING
13from homeassistant.components.sensor import RestoreSensor, SensorStateClass
14from homeassistant.const import EntityCategory
16from . import DOMAIN
17from .hass_api import ha_device_info
19if TYPE_CHECKING:
20 from homeassistant.core import HomeAssistant
21 from homeassistant.helpers.device_registry import DeviceInfo
22 from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
24 from . import SupernotifyConfigEntry
27async def async_setup_entry(
28 hass: HomeAssistant,
29 entry: SupernotifyConfigEntry,
30 async_add_entities: AddConfigEntryEntitiesCallback,
31) -> None:
32 """Add the engine's sent/failure counters as restorable sensor entities."""
33 _ = hass
34 async_add_entities(entry.runtime_data.counter_sensors)
37class SupernotifyCounterSensor(RestoreSensor):
38 """A monotonically increasing counter, restored across restarts."""
40 _attr_has_entity_name = True
41 _attr_entity_category = EntityCategory.DIAGNOSTIC
42 _attr_state_class = SensorStateClass.TOTAL_INCREASING
43 _attr_native_value = 0
44 _attr_should_poll = False
46 def __init__(self, unique_id: str, translation_key: str) -> None:
47 self._attr_unique_id = unique_id
48 self._attr_translation_key = translation_key
49 # Kept as the entity_id the counters have always had, rather than the one HA would derive
50 # from the device and entity name - see SupernotifyScenarioSwitch for why this is
51 # tolerated
52 self.entity_id = f"sensor.{DOMAIN}_{unique_id}"
54 @property
55 def device_info(self) -> DeviceInfo | None:
56 """The single SuperNotify device - the platform, and so the config entry, is only known
57 once the entity has been handed to Home Assistant"""
58 if self.platform is None or self.platform.config_entry is None:
59 return None
60 return ha_device_info(self.platform.config_entry.entry_id)
62 @property
63 def count(self) -> int:
64 return int(self._attr_native_value)
66 async def async_added_to_hass(self) -> None:
67 await super().async_added_to_hass()
68 last_data = await self.async_get_last_sensor_data()
69 if last_data is not None and isinstance(last_data.native_value, (int, float)):
70 self._attr_native_value = int(last_data.native_value)
71 self.async_write_ha_state()
73 def increment(self) -> None:
74 self._attr_native_value = self.count + 1
75 self.refresh()
77 def refresh(self) -> None:
78 """Publish the current count, if the entity has been added to Home Assistant yet"""
79 if self.hass is not None:
80 self.async_write_ha_state()