Skip to content

Commit 96b3629

Browse files
committed
Give the measurements a state class, so they build long-term statistics
Temperatures had a device class and a unit but no state class, which is what Home Assistant needs to keep statistics. They were recorded as history and would have vanished with the recorder's retention -- ten days by default -- without ever becoming a trend. The temperatures and the two supply rails are measurements and now say so. The rest stay plain states: a firmware revision and a mode number are numbers, but their average is meaningless and would only clutter the statistics.
1 parent cbb27d3 commit 96b3629

4 files changed

Lines changed: 56 additions & 3 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ and a generic writable entity over that surface would be a foot-gun.
5656
Values are **pushed**: once subscribed, the appliance reports changes as they
5757
happen, including changes made at the panel or from the app.
5858

59+
Temperatures and the supply rails carry a state class, so they build long-term
60+
statistics rather than disappearing with the recorder's retention. The rest are
61+
states, not measurements — averaging a firmware revision or a mode number says
62+
nothing — so they appear in history only.
63+
5964
## Installation
6065

6166
[![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=omc69&repository=Truma-Aventa2-HomeAssistant-Integration&category=integration)

custom_components/truma_aventa/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@
3030
"bleak-retry-connector>=3.5.0",
3131
"cbor2>=5.6.0"
3232
],
33-
"version": "0.9.7"
33+
"version": "0.9.8"
3434
}

custom_components/truma_aventa/sensor.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,16 @@
2020
import re
2121
from typing import Any, Final
2222

23-
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
24-
from homeassistant.const import EntityCategory, UnitOfTemperature
23+
from homeassistant.components.sensor import (
24+
SensorDeviceClass,
25+
SensorEntity,
26+
SensorStateClass,
27+
)
28+
from homeassistant.const import (
29+
EntityCategory,
30+
UnitOfElectricPotential,
31+
UnitOfTemperature,
32+
)
2533
from homeassistant.core import HomeAssistant, callback
2634
from homeassistant.helpers.device_registry import DeviceInfo
2735
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -47,6 +55,9 @@
4755
}
4856
)
4957

58+
#: Supply rails, reported in millivolts.
59+
_VOLTAGES: Final = frozenset({"Eol.Vcc12", "Eol.Vcc5"})
60+
5061
#: Our own pairing identity, which the bus reports back to us like any other
5162
#: parameter. It says nothing about the appliance and it is the one value here
5263
#: worth keeping out of a state machine, so it is left out.
@@ -172,6 +183,16 @@ def __init__(
172183
self._attr_device_class = SensorDeviceClass.TEMPERATURE
173184
self._attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
174185
self._attr_suggested_display_precision = 1
186+
# Without a state class there are no long-term statistics, and a
187+
# temperature is gone with the recorder's retention rather than
188+
# becoming a year's trend.
189+
self._attr_state_class = SensorStateClass.MEASUREMENT
190+
elif parameter in _VOLTAGES:
191+
self._attr_device_class = SensorDeviceClass.VOLTAGE
192+
self._attr_native_unit_of_measurement = (
193+
UnitOfElectricPotential.MILLIVOLT
194+
)
195+
self._attr_state_class = SensorStateClass.MEASUREMENT
175196
self._attr_device_info = self._build_device_info(coordinator, identity)
176197

177198
def _build_device_info(

tests/test_sensor.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
1919

20+
from homeassistant.components.sensor import SensorStateClass
21+
2022
from custom_components.truma_aventa.const import DOMAIN
2123
from custom_components.truma_aventa.sensor import (
2224
TrumaParameterSensor,
@@ -34,6 +36,8 @@
3436
"0101/Identify.SwMaj": 3,
3537
"0101/Identify.SwMin": 5,
3638
"0101/Temperature.Internal": 249,
39+
"0101/Eol.Vcc12": 12040,
40+
"0101/Identify.SwBgFx": 26,
3741
"0200/Identify.UniqueID": "0a69818a.device.id.ii.inetx",
3842
"0200/RoomClimate.TgtTemp": 220,
3943
# The air conditioning answers on two addresses and carries its name on
@@ -201,3 +205,26 @@ def test_a_name_on_a_later_address_still_counts(coordinator: _Coordinator) -> No
201205
sensor = _sensor(coordinator, "AirCooling.Temp")
202206
assert sensor.device_info["name"] == "Aventa comfort 2. G"
203207
assert sensor.name == "AirCooling Temp"
208+
209+
210+
# --- long-term statistics --------------------------------------------------
211+
212+
213+
def test_a_temperature_produces_statistics(coordinator: _Coordinator) -> None:
214+
"""Without a state class there is history for ten days and nothing after."""
215+
sensor = _sensor(coordinator, "Temperature.Internal")
216+
assert sensor.state_class is SensorStateClass.MEASUREMENT
217+
218+
219+
def test_a_supply_rail_produces_statistics(coordinator: _Coordinator) -> None:
220+
"""The rails are millivolts and worth a trend."""
221+
sensor = _sensor(coordinator, "Eol.Vcc12")
222+
assert sensor.state_class is SensorStateClass.MEASUREMENT
223+
assert sensor.native_value == 12040
224+
225+
226+
def test_a_number_that_is_not_a_measurement_gets_no_state_class(
227+
coordinator: _Coordinator,
228+
) -> None:
229+
"""A firmware revision is numeric and averaging it means nothing."""
230+
assert _sensor(coordinator, "Identify.SwBgFx").state_class is None

0 commit comments

Comments
 (0)