diff --git a/custom_components/ferroamp/sensor.py b/custom_components/ferroamp/sensor.py index 5cc9189..96146aa 100644 --- a/custom_components/ferroamp/sensor.py +++ b/custom_components/ferroamp/sensor.py @@ -207,7 +207,6 @@ def sso_event_received(msg): precision_energy, config_id, model=model, - state_class=SensorStateClass.TOTAL_INCREASING ), FaultcodeFerroampSensor( "Faultcode", @@ -300,7 +299,6 @@ def eso_event_received(msg): interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), EnergyFerroampSensor( "Total Energy Consumed", @@ -312,7 +310,6 @@ def eso_event_received(msg): interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), BatteryFerroampSensor( "State of Charge", @@ -627,6 +624,15 @@ def __init__(self, name, entity_prefix, key, unit: str | None, icon, device_id, def present(self, event) -> bool: return event.get(self._state_key, None) is not None + def get_value(self, event): + return event.get(self._state_key, None) + + def get_float_value(self, event) -> float: + val = event.get(self._state_key, None) + if val is None: + return 0 + return float(val["val"]) + def add_event(self, event): if not self.check_presence or self.present(event): self.events.append(event) @@ -706,10 +712,10 @@ def update_state_from_events(self, events) -> bool: temp = None count = 0 for event in events: - v = event.get(self._state_key, None) + v = self.get_value(event) if v is not None: count += 1 - temp = (temp or 0) + float(v["val"]) + temp = (temp or 0) + self.get_float_value(event) if temp is None: return False else: @@ -728,7 +734,7 @@ def __init__(self, name, entity_prefix, key, icon, device_id, device_name, inter self._attr_state_class = SensorStateClass.MEASUREMENT def get_voltage(self, event): - voltage = event.get(self._state_key, None) + voltage = self.get_value(event) if voltage is not None: voltage = dict(neg=float(voltage["neg"]), pos=float(voltage["pos"])) return voltage @@ -854,9 +860,14 @@ def __init__(self, name, entity_prefix, key, icon, device_id, device_name, inter interval, precision, config_id, + state_class=SensorStateClass.TOTAL_INCREASING, **kwargs ) + def add_event(self, event): + if self.get_float_value(event) > 0: + super().add_event(event) + def update_state_from_events(self, events): temp = None count = 0 @@ -1037,9 +1048,16 @@ def __init__(self, name, entity_prefix, key, icon, device_id, device_name, inter interval, precision, config_id, + state_class=SensorStateClass.TOTAL_INCREASING, **kwargs ) + def add_event(self, event): + phases = self.get_phases(event) + if phases is not None and (phases["L1"] is not None or phases["L2"] is not None or phases["L3"] is not None): + if (phases["L1"] + phases["L2"] + phases["L3"]) > 0: + super().add_event(event) + def get_phases(self, event): phases = super().get_phases(event) if phases is not None and (phases["L1"] is not None or phases["L2"] is not None or phases["L3"] is not None): @@ -1304,7 +1322,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), ThreePhaseEnergyFerroampSensor( "External Energy Consumed", @@ -1316,7 +1333,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), ThreePhaseEnergyFerroampSensor( "Inverter Energy Produced", @@ -1328,7 +1344,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), ThreePhaseEnergyFerroampSensor( "Inverter Energy Consumed", @@ -1340,7 +1355,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), ThreePhaseEnergyFerroampSensor( "Load Energy Produced", @@ -1352,7 +1366,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), ThreePhaseEnergyFerroampSensor( "Load Energy Consumed", @@ -1364,7 +1377,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), EnergyFerroampSensor( "Total Solar Energy", @@ -1376,7 +1388,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), EnergyFerroampSensor( "Battery Energy Produced", @@ -1388,7 +1399,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), EnergyFerroampSensor( "Battery Energy Consumed", @@ -1400,7 +1410,6 @@ def ehub_sensors(slug, interval, precision_battery, precision_current, precision interval, precision_energy, config_id, - state_class=SensorStateClass.TOTAL_INCREASING, ), IntValFerroampSensor( "System State", diff --git a/tests/test_sensor.py b/tests/test_sensor.py index fe1c9a6..1fce812 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -1,5 +1,6 @@ import uuid from unittest.mock import patch +import unittest import pytest from homeassistant.const import ( @@ -1692,6 +1693,47 @@ async def test_always_increasing(hass, mqtt_mock): sensor = hass.data[DOMAIN][DATA_DEVICES][config_entry.unique_id]["ferroamp_ehub"][entity.unique_id] assert sensor.state == "1348.5" +async def test_always_increasing_zerovalues(hass, mqtt_mock): + mock_restore_cache( + hass, + [ + State("sensor.ferroamp_total_solar_energy", "1348.5") + ], + ) + + hass.state = CoreState.starting + + config_entry = create_config() + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + topic = "extapi/data/ehub" + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "4422089590383"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "0"}}') + await hass.async_block_till_done() + + er = entity_registry.async_get(hass) + entity = er.async_get("sensor.ferroamp_total_solar_energy") + assert entity is not None + sensor = hass.data[DOMAIN][DATA_DEVICES][config_entry.unique_id]["ferroamp_ehub"][entity.unique_id] + assert float(sensor.state) == pytest.approx(1348.5) + + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "4856400000000"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "0"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "0"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "0"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "0"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "0"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "0"}}') + async_fire_mqtt_message(hass, topic, '{"id":{"val":"1"},"wpv":{"val": "4856400000000"}}') + await hass.async_block_till_done() + + er = entity_registry.async_get(hass) + entity = er.async_get("sensor.ferroamp_total_solar_energy") + assert entity is not None + sensor = hass.data[DOMAIN][DATA_DEVICES][config_entry.unique_id]["ferroamp_ehub"][entity.unique_id] + assert float(sensor.state) == pytest.approx(1349.0) + async def test_always_increasing_unknown_value(hass, mqtt_mock): mock_restore_cache( @@ -1771,6 +1813,52 @@ async def test_3phase_always_increasing(hass, mqtt_mock): sensor = hass.data[DOMAIN][DATA_DEVICES][config_entry.unique_id]["ferroamp_ehub"][entity.unique_id] assert sensor.state == "662.5" +async def test_3phase_always_increasing_zero_values(hass, mqtt_mock): + mock_restore_cache( + hass, + [ + State("sensor.ferroamp_external_energy_produced", "662.5") + ], + ) + + hass.state = CoreState.starting + + config_entry = create_config() + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + topic = "extapi/data/ehub" + msg = '{"id":{"val":"1"},"wextprodq": {"L2": "1118056851556", "L3": "604554554552", "L1": "662115344893"}}' + async_fire_mqtt_message(hass, topic, msg) + msg = '{"id":{"val":"1"},"wextprodq": {"L2": "0", "L3": "0", "L1": "0"}}' + async_fire_mqtt_message(hass, topic, msg) + async_fire_mqtt_message(hass, topic, msg) + async_fire_mqtt_message(hass, topic, msg) + await hass.async_block_till_done() + + er = entity_registry.async_get(hass) + entity = er.async_get("sensor.ferroamp_external_energy_produced") + assert entity is not None + sensor = hass.data[DOMAIN][DATA_DEVICES][config_entry.unique_id]["ferroamp_ehub"][entity.unique_id] + assert float(sensor.state) == pytest.approx(662.5) + + msg = '{"id":{"val":"1"},"wextprodq": {"L2": "1118056851556", "L3": "604554554552", "L1": "662115344893"}}' + async_fire_mqtt_message(hass, topic, msg) + msg = '{"id":{"val":"1"},"wextprodq": {"L2": "0", "L3": "0", "L1": "0"}}' + async_fire_mqtt_message(hass, topic, msg) + async_fire_mqtt_message(hass, topic, msg) + async_fire_mqtt_message(hass, topic, msg) + msg = '{"id":{"val":"1"},"wextprodq": {"L2": "1119056851556", "L3": "604564554552", "L1": "662116344893"}}' + async_fire_mqtt_message(hass, topic, msg) + msg = '{"id":{"val":"1"},"wextprodq": {"L2": "0", "L3": "0", "L1": "0"}}' + async_fire_mqtt_message(hass, topic, msg) + await hass.async_block_till_done() + + er = entity_registry.async_get(hass) + entity = er.async_get("sensor.ferroamp_external_energy_produced") + assert entity is not None + sensor = hass.data[DOMAIN][DATA_DEVICES][config_entry.unique_id]["ferroamp_ehub"][entity.unique_id] + assert float(sensor.state) == pytest.approx(662.7) async def test_3phase_always_increasing_unknown_value(hass, mqtt_mock): mock_restore_cache(