From f26561beb757996c72385368d76f438fb08e7876 Mon Sep 17 00:00:00 2001 From: joshuaterk Date: Sat, 30 May 2026 21:06:22 -0400 Subject: [PATCH] Fix monetary rate sensor state class --- custom_components/dte_rates/sensor.py | 3 +-- docs/README.md | 1 + docs/research/issue-5-entity-type.md | 27 +++++++++++++++++++++++++++ tests/test_sensor.py | 17 +++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 docs/research/issue-5-entity-type.md diff --git a/custom_components/dte_rates/sensor.py b/custom_components/dte_rates/sensor.py index e43405b..140d948 100644 --- a/custom_components/dte_rates/sensor.py +++ b/custom_components/dte_rates/sensor.py @@ -3,7 +3,7 @@ from collections import defaultdict from decimal import Decimal -from homeassistant.components.sensor import SensorDeviceClass, SensorEntity, SensorStateClass +from homeassistant.components.sensor import SensorDeviceClass, SensorEntity from homeassistant.components import persistent_notification from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback @@ -76,7 +76,6 @@ async def async_setup_entry( class _DteBaseRateSensor(CoordinatorEntity, SensorEntity): _attr_native_unit_of_measurement = "USD/kWh" _attr_device_class = SensorDeviceClass.MONETARY - _attr_state_class = SensorStateClass.MEASUREMENT def __init__(self, coordinator, entry: ConfigEntry) -> None: super().__init__(coordinator) diff --git a/docs/README.md b/docs/README.md index f2f1202..64d7e28 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,3 +12,4 @@ Current research notes: - `research/rider18-export-rates.md` - Rider 18 export-rate source mapping and PSCR formula decisions. - `research/issue-3-rate-modifiers.md` - PSCR/tax modifier defaults and calculation scope for real out-of-pocket rates. +- `research/issue-5-entity-type.md` - Home Assistant monetary sensor state-class warning and entity metadata decision. diff --git a/docs/research/issue-5-entity-type.md b/docs/research/issue-5-entity-type.md new file mode 100644 index 0000000..151961b --- /dev/null +++ b/docs/research/issue-5-entity-type.md @@ -0,0 +1,27 @@ +# Issue 5 Entity Type Warning + +## Source + +- GitHub issue: https://github.com/javaDevJT/DTE-Rates-for-Home-Assistant/issues/5 +- Title: Entity type issue +- Created: 2026-05-29 + +## Report + +Home Assistant logs warnings for `DteImportRateSensor` and `DteExportRateSensor`: + +`device_class: monetary` was combined with `state_class: measurement`. + +Current Home Assistant sensor validation rejects that combination. Monetary sensors may have no state class, or use state class `total` when the entity represents a total amount. These rate sensors represent a current price in `USD/kWh`, not an accumulating monetary total. + +## Decision + +- Keep `device_class: monetary`. +- Keep `native_unit_of_measurement: USD/kWh`. +- Remove `state_class` from the import/export price sensors. + +This preserves the current-price entity shape while avoiding invalid long-term statistics metadata. + +## Reference + +- Home Assistant sensor developer docs: https://developers.home-assistant.io/docs/core/entity/sensor/ diff --git a/tests/test_sensor.py b/tests/test_sensor.py index caade61..909d3fe 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -84,6 +84,23 @@ def test_import_sensor_returns_default_out_of_pocket_rate(monkeypatch): } +def test_rate_price_sensors_do_not_set_invalid_monetary_state_class(monkeypatch): + monkeypatch.setattr("custom_components.dte_rates.sensor.dt_util.now", lambda: datetime(2026, 3, 1, 12, 0)) + + coordinator = _coordinator_with_rate() + entry = SimpleNamespace(entry_id="entry_18", data={CONF_SELECTED_RATE: "D1.11", CONF_NET_METERING: False}) + + import_sensor = DteImportRateSensor(coordinator, entry) + export_sensor = DteExportRateSensor(coordinator, entry) + + assert getattr(import_sensor, "_attr_device_class", None) == "monetary" + assert getattr(export_sensor, "_attr_device_class", None) == "monetary" + assert import_sensor.native_unit_of_measurement == "USD/kWh" + assert export_sensor.native_unit_of_measurement == "USD/kWh" + assert getattr(import_sensor, "_attr_state_class", None) is None + assert getattr(export_sensor, "_attr_state_class", None) is None + + def test_import_sensor_can_omit_modifiers(monkeypatch): monkeypatch.setattr("custom_components.dte_rates.sensor.dt_util.now", lambda: datetime(2026, 3, 1, 12, 0))