Coverage for custom_components/supernotify/sensor.py: 98%
40 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-08 17:42 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-08 17:42 +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
26# Entities are pushed, never polled, and their actions only change local state
27PARALLEL_UPDATES = 0
30async def async_setup_entry(
31 hass: HomeAssistant,
32 entry: SupernotifyConfigEntry,
33 async_add_entities: AddConfigEntryEntitiesCallback,
34) -> None:
35 """Add the engine's sent/failure counters as restorable sensor entities."""
36 _ = hass
37 async_add_entities(entry.runtime_data.counter_sensors)
40class SupernotifyCounterSensor(RestoreSensor):
41 """A monotonically increasing counter, restored across restarts."""
43 _attr_has_entity_name = True
44 _attr_entity_category = EntityCategory.DIAGNOSTIC
45 _attr_state_class = SensorStateClass.TOTAL_INCREASING
46 _attr_native_value = 0
47 _attr_should_poll = False
49 def __init__(self, unique_id: str, translation_key: str) -> None:
50 self._attr_unique_id = unique_id
51 self._attr_translation_key = translation_key
52 # Kept as the entity_id the counters have always had, rather than the one HA would derive
53 # from the device and entity name - see SupernotifyScenarioSwitch for why this is
54 # tolerated
55 self.entity_id = f"sensor.{DOMAIN}_{unique_id}"
57 @property
58 def device_info(self) -> DeviceInfo | None:
59 """The single SuperNotify device - the platform, and so the config entry, is only known
60 once the entity has been handed to Home Assistant"""
61 if self.platform is None or self.platform.config_entry is None:
62 return None
63 return ha_device_info(self.platform.config_entry.entry_id)
65 @property
66 def count(self) -> int:
67 return self._attr_native_value if isinstance(self._attr_native_value, int) else 0
69 async def async_added_to_hass(self) -> None:
70 await super().async_added_to_hass()
71 last_data = await self.async_get_last_sensor_data()
72 if last_data is not None and isinstance(last_data.native_value, (int, float)):
73 self._attr_native_value = int(last_data.native_value)
74 self.async_write_ha_state()
76 def increment(self) -> None:
77 self._attr_native_value = self.count + 1
78 self.refresh()
80 def refresh(self) -> None:
81 """Publish the current count, if the entity has been added to Home Assistant yet"""
82 if self.hass is not None:
83 self.async_write_ha_state()