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

1"""Sensor platform: the notification/failure counters as real, restorable entities. 

2 

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""" 

8 

9from __future__ import annotations 

10 

11from typing import TYPE_CHECKING 

12 

13from homeassistant.components.sensor import RestoreSensor, SensorStateClass 

14from homeassistant.const import EntityCategory 

15 

16from . import DOMAIN 

17from .hass_api import ha_device_info 

18 

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 

23 

24 from . import SupernotifyConfigEntry 

25 

26 

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) 

35 

36 

37class SupernotifyCounterSensor(RestoreSensor): 

38 """A monotonically increasing counter, restored across restarts.""" 

39 

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 

45 

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}" 

53 

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) 

61 

62 @property 

63 def count(self) -> int: 

64 return int(self._attr_native_value) 

65 

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() 

72 

73 def increment(self) -> None: 

74 self._attr_native_value = self.count + 1 

75 self.refresh() 

76 

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()