1- """Common code for Victron Venus integration."""
1+ """Base entity for entities in victron_gx integration."""
22
33from abc import abstractmethod
4- import logging
54from typing import Any
65
7- from victron_mqtt import (
8- Device as VictronVenusDevice ,
9- Metric as VictronVenusMetric ,
10- MetricKind ,
11- MetricNature ,
12- MetricType ,
13- )
6+ from victron_mqtt import Device as VictronVenusDevice , Metric as VictronVenusMetric
147
15- from homeassistant .components .sensor import SensorDeviceClass , SensorStateClass
168from homeassistant .const import EntityCategory
179from homeassistant .core import callback
1810from homeassistant .helpers .device_registry import DeviceInfo
1911from homeassistant .helpers .entity import Entity
2012
21- from .const import ENTITIES_CATEGORY_DIAGNOSTIC , ENTITIES_DISABLE_BY_DEFAULT , ENTITY_PREFIX
13+ # Entities that should be marked as diagnostic
14+ ENTITIES_CATEGORY_DIAGNOSTIC = ["system_heartbeat" , "solarcharger_device_off_reason" ]
15+ # Entities that should be disabled by default
16+ ENTITIES_DISABLE_BY_DEFAULT = ["system_heartbeat" , "solarcharger_device_off_reason" ]
2217
23- _LOGGER = logging . getLogger ( __name__ )
18+ ENTITY_PREFIX = "victron_mqtt"
2419
2520
2621class VictronBaseEntity (Entity ):
27- """Implementation of a Victron Venus base entity."""
22+ """Implementation of a Victron GX base entity."""
2823
2924 _attr_should_poll = False
3025 _attr_has_entity_name = True
@@ -42,7 +37,6 @@ def __init__(
4237 self ._device = device
4338 self ._metric = metric
4439 self ._attr_device_info = device_info
45- self ._metric = metric
4640 if simple_naming :
4741 entity_id = f"{ entity_platform } .{ ENTITY_PREFIX } _{ metric .unique_id } "
4842 else :
@@ -51,19 +45,9 @@ def __init__(
5145 self ._attr_suggested_display_precision = metric .precision
5246 self ._attr_translation_key = metric .generic_short_id .replace ("{" , "" ).replace (
5347 "}" , ""
54- ) # same as in merge_topics.py
48+ )
5549 self ._attr_translation_placeholders = metric .key_values
5650
57- # Some attributes are relevant only for certain metric kinds
58- if metric .metric_kind in [MetricKind .SENSOR , MetricKind .NUMBER ]:
59- self ._attr_device_class = self ._map_metric_to_device_class (metric )
60- self ._attr_state_class = self ._map_metric_to_stateclass (metric )
61- # Only set native_unit_of_measurement when a device_class is present.
62- # Entities without a device_class get their display unit from
63- # the translation files instead (set by merge_topics.py).
64- if self ._attr_device_class is not None :
65- self ._attr_native_unit_of_measurement = metric .unit_of_measurement
66-
6751 self ._attr_entity_category = (
6852 EntityCategory .DIAGNOSTIC
6953 if metric .generic_short_id in ENTITIES_CATEGORY_DIAGNOSTIC
@@ -73,76 +57,22 @@ def __init__(
7357 metric .generic_short_id not in ENTITIES_DISABLE_BY_DEFAULT
7458 )
7559
76-
77- def __repr__ (self ) -> str :
78- """Return a string representation of the entity."""
79- return (
80- f"VictronBaseEntity(device={ self ._device .name } , "
81- f"unique_id={ self ._attr_unique_id } , "
82- f"metric={ self ._metric .short_id } , "
83- f"translation_key={ self ._attr_translation_key } , "
84- f"translation_placeholders={ self ._attr_translation_placeholders } )"
85- )
86-
8760 @callback
8861 @abstractmethod
89- def _on_update_task (self , value : Any ) -> None :
62+ def _on_update_cb (self , value : Any ) -> None :
9063 """Handle the metric update. Must be implemented by subclasses."""
9164
9265 @callback
9366 def _on_update (self , _ : VictronVenusMetric , value : Any ) -> None :
94- self ._on_update_task (value )
67+ self ._on_update_cb (value )
9568
9669 async def async_added_to_hass (self ) -> None :
9770 """Run when entity about to be added to hass."""
9871 await super ().async_added_to_hass ()
99- # Now we can safely register for updates as the entity is fully registered with Home Assistant
10072 self ._metric .on_update = self ._on_update
10173
10274 async def async_will_remove_from_hass (self ) -> None :
10375 """Run when entity will be removed from hass."""
104- # Remove our update callback by setting a no-op function
76+ # Unregister update callback
10577 self ._metric .on_update = None
10678 await super ().async_will_remove_from_hass ()
107-
108- def _map_metric_to_device_class (
109- self , metric : VictronVenusMetric
110- ) -> SensorDeviceClass | None :
111- match metric .metric_type :
112- case MetricType .POWER :
113- return SensorDeviceClass .POWER
114- case MetricType .APPARENT_POWER :
115- return SensorDeviceClass .APPARENT_POWER
116- case MetricType .ENERGY :
117- return SensorDeviceClass .ENERGY
118- case MetricType .VOLTAGE :
119- return SensorDeviceClass .VOLTAGE
120- case MetricType .CURRENT :
121- return SensorDeviceClass .CURRENT
122- case MetricType .FREQUENCY :
123- return SensorDeviceClass .FREQUENCY
124- case MetricType .ELECTRIC_STORAGE_PERCENTAGE :
125- return SensorDeviceClass .BATTERY
126- case MetricType .TEMPERATURE :
127- return SensorDeviceClass .TEMPERATURE
128- case MetricType .SPEED :
129- return SensorDeviceClass .SPEED
130- case MetricType .LIQUID_VOLUME :
131- return SensorDeviceClass .VOLUME_STORAGE
132- case MetricType .DURATION :
133- return SensorDeviceClass .DURATION
134- case MetricType .TIME :
135- # Sadly, there is no SensorDeviceClass for time
136- return None
137- case _:
138- return None
139-
140- def _map_metric_to_stateclass (
141- self , metric : VictronVenusMetric
142- ) -> SensorStateClass | None :
143- if metric .metric_nature == MetricNature .CUMULATIVE :
144- return SensorStateClass .TOTAL
145- if metric .metric_nature == MetricNature .INSTANTANEOUS :
146- return SensorStateClass .MEASUREMENT
147-
148- return None
0 commit comments