diff --git a/packages/helpermodules/command.py b/packages/helpermodules/command.py index f03fd86884..9ec985caf1 100644 --- a/packages/helpermodules/command.py +++ b/packages/helpermodules/command.py @@ -28,7 +28,8 @@ from helpermodules.broker import BrokerClient from helpermodules.data_migration.data_migration import MigrateData -from helpermodules.measurement_logging.process_log import get_daily_log, get_monthly_log, get_yearly_log +from helpermodules.measurement_logging.process_log import (convert_legacy_units, get_daily_log, get_monthly_log, + get_yearly_log) from helpermodules.messaging import MessageType, pub_user_message from helpermodules.mosquitto_dynsec.mosquitto_dynsec import (generate_password_reset_token, get_user_email, send_password_reset_to_server, verify_password_reset_token) @@ -822,15 +823,15 @@ def getChargeLog(self, connection_id: str, payload: dict) -> None: def getDailyLog(self, connection_id: str, payload: dict) -> None: Pub().pub(f'openWB/set/log/daily/{payload["data"]["date"]}', - get_daily_log(payload["data"]["date"])) + convert_legacy_units(get_daily_log(payload["data"]["date"]))) def getMonthlyLog(self, connection_id: str, payload: dict) -> None: Pub().pub(f'openWB/set/log/monthly/{payload["data"]["date"]}', - get_monthly_log(payload["data"]["date"])) + convert_legacy_units(get_monthly_log(payload["data"]["date"]))) def getYearlyLog(self, connection_id: str, payload: dict) -> None: Pub().pub(f'openWB/set/log/yearly/{payload["data"]["date"]}', - get_yearly_log(payload["data"]["date"])) + convert_legacy_units(get_yearly_log(payload["data"]["date"]))) def initCloud(self, connection_id: str, payload: dict) -> None: parent_file = Path(__file__).resolve().parents[2] diff --git a/packages/helpermodules/command_test.py b/packages/helpermodules/command_test.py index dade5c3324..d9115dfbd4 100644 --- a/packages/helpermodules/command_test.py +++ b/packages/helpermodules/command_test.py @@ -6,6 +6,7 @@ from control.chargepoint.chargepoint_state_update import ChargepointStateUpdate import dataclass_utils from helpermodules.command import Command +from helpermodules.measurement_logging import process_log from helpermodules.subdata import SubData from modules.chargepoints.external_openwb.config import OpenWBSeries from modules.chargepoints.internal_openwb.config import (InternalOpenWB, InternalOpenWBConfiguration, @@ -14,6 +15,9 @@ from modules.chargepoints.internal_openwb.chargepoint_module import ChargepointModule as ChargepointModuleInternal +pytest_plugins = ["helpermodules.measurement_logging.process_log_testdata", "helpermodules.command_test_data"] + + @pytest.fixture def subdata_fixture() -> None: SubData(*([Mock()]*16)) @@ -51,3 +55,22 @@ def test_check_max_num_of_internal_chargepoints(additional_cp_mode, config, expe # evaluation assert msg == expected_msg + + +def test_getDailyLog(regular_daily_log_entry, + regular_daily_log_entry_processed_legacy_converted, + mock_pub, + monkeypatch): + # setup + c = Command(Mock()) + mock_pub.reset_mock() + collect_daily_log_data_mock = Mock(return_value=regular_daily_log_entry) + monkeypatch.setattr(process_log, "_collect_daily_log_data", collect_daily_log_data_mock) + + # execution + c.getDailyLog("test", {"data": {"date": "20250616"}}) + + # evaluation + assert len(mock_pub.method_calls) == 1 + assert mock_pub.method_calls[0][1][0] == 'openWB/set/log/daily/20250616' + assert mock_pub.method_calls[0][1][1] == regular_daily_log_entry_processed_legacy_converted diff --git a/packages/helpermodules/command_test_data.py b/packages/helpermodules/command_test_data.py new file mode 100644 index 0000000000..048def3eb1 --- /dev/null +++ b/packages/helpermodules/command_test_data.py @@ -0,0 +1,157 @@ +import pytest + + +@pytest.fixture() +def regular_daily_log_entry_processed_legacy_converted(): + return {'entries': [{'bat': {'all': {'energy_exported': 0, + 'energy_imported': 0, + 'exported': 3195.13, + 'fault_state': 0, + 'imported': 629.37, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0, + 'soc': 48}, + 'bat2': {'energy_exported': 0, + 'energy_imported': 0, + 'exported': 3195.13, + 'fault_state': 0, + 'imported': 629.37, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0, + 'soc': 48}}, + 'counter': {'counter0': {'energy_exported': 0.772, + 'energy_imported': 0, + 'exported': 26029.945, + 'fault_state': 0, + 'grid': True, + 'imported': 2728.572, + 'power_average': -9.3, + 'power_exported': 9.3, + 'power_imported': 0}}, + 'cp': {'all': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 12639.11, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}, + 'cp3': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 12639.11, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}, + 'cp4': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 0, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}, + 'cp5': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 0, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}}, + 'date': '14:25', + 'energy_source': {'bat': 0.0, 'cp': 0.0, 'grid': 0.0, 'pv': 1.0}, + 'ev': {'ev0': {'soc': None}}, + 'hc': {'all': {'energy_exported': 0, + 'energy_imported': 0.037, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0.037, + 'fault_state': 0, + 'imported': 2324.001611140539, + 'power_average': 0.448, + 'power_exported': 0, + 'power_imported': 0.448}}, + 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, + 'pv': {'all': {'energy_exported': 0.809, + 'energy_imported': 0, + 'exported': 35827, + 'fault_state': 0, + 'power_average': -9.74, + 'power_exported': 9.74, + 'power_imported': 0}, + 'pv1': {'energy_exported': 0.809, + 'energy_imported': 0, + 'exported': 35827, + 'fault_state': 0, + 'power_average': -9.74, + 'power_exported': 9.74, + 'power_imported': 0}}, + 'sh': {}, + 'timestamp': 1750767902}], + 'message': '', + 'names': {'bat2': 'MQTT-Speicher', + 'counter0': 'MQTT-Zähler', + 'counter2': 'Test-Zähler', + 'cp3': 'MQTT-Ladepunkt', + 'cp4': 'MQTT-Ladepunkt', + 'cp5': 'MQTT-Ladepunkt', + 'ev0': 'Standard-Fahrzeug', + 'pv1': 'MQTT-Wechselrichter'}, + 'totals': {'bat': {'all': {'energy_exported': 0, 'energy_imported': 0}, + 'bat2': {'energy_exported': 0, 'energy_imported': 0}}, + 'counter': {'counter0': {'energy_exported': 772.41, + 'energy_imported': 0, + 'grid': True}}, + 'cp': {'all': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}, + 'cp3': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}, + 'cp4': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}, + 'cp5': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}}, + 'hc': {'all': {'energy_imported': 37.177, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 37.177}}, + 'pv': {'all': {'energy_exported': 809}, + 'pv1': {'energy_exported': 809}}, + 'sh': {}}} diff --git a/packages/helpermodules/measurement_logging/process_log.py b/packages/helpermodules/measurement_logging/process_log.py index 901869037f..bdab771624 100644 --- a/packages/helpermodules/measurement_logging/process_log.py +++ b/packages/helpermodules/measurement_logging/process_log.py @@ -8,7 +8,7 @@ from helpermodules.measurement_logging.write_log import (LegacySmartHomeLogData, LogType, create_entry, get_previous_entry) from helpermodules.messaging import MessageType, pub_system_message -from helpermodules.utils.precision_math import decimal_add, decimal_multiply, decimal_subtract +from helpermodules.utils.precision_math import decimal_add, decimal_divide, decimal_multiply, decimal_subtract log = logging.getLogger(__name__) @@ -47,6 +47,143 @@ def get_default_charge_log_columns() -> Dict: } +# {'entries': [{'bat': {'all': {'energy_exported': 0.0, # kWh +# 'energy_imported': 0.0, # kWh +# 'exported': 50.75, # Wh +# 'imported': 2551.98, # Wh +# 'power_average': 0.0, # kW +# 'power_exported': 0, # kW +# 'power_imported': 0.0, # kW +# 'soc': 100}, # % +# 'bat2': {'energy_exported': 0.0, # kWh +# 'energy_imported': 0.0, # kWh +# 'exported': 50.75, # Wh +# 'imported': 2551.98, # Wh +# 'power_average': 0.0, # kW +# 'power_exported': 0, # kW +# 'power_imported': 0.0, # kW +# 'soc': 100}}, # % +# 'counter': {'counter0': {'energy_exported': 4.421, # kWh +# 'energy_imported': 0.0, # kWh +# 'exported': 24425.677, # Wh +# 'grid': True, +# 'imported': 90.379, # Wh +# 'power_average': -7.139, # kW +# 'power_exported': 7.139, # kW +# 'power_imported': 0}}, # kW +# 'cp': {'all': {'energy_exported': 0.0, # kWh +# 'energy_imported': 0.081, # kWh +# 'energy_imported_bat': 0.0, # kWh +# 'energy_imported_cp': 0.0, # kWh +# 'energy_imported_grid': 0.0, # kWh +# 'energy_imported_pv': 0.081, # kWh +# 'exported': 0, # Wh +# 'imported': 29123.5, # Wh +# 'power_average': 0.131, # kW +# 'power_exported': 0, # kW +# 'power_imported': 0.131}, # kW +# 'cp3': {'energy_exported': 0.0, # kWh +# 'energy_imported': 0.0, # kWh +# 'energy_imported_bat': 0.0, # kWh +# 'energy_imported_cp': 0.0, # kWh +# 'energy_imported_grid': 0.0, # kWh +# 'energy_imported_pv': 0.0, # kWh +# 'exported': 0, # Wh +# 'imported': 10638.5, # Wh +# 'power_average': 0.0, # kW +# 'power_exported': 0, # kW +# 'power_imported': 0.0}}, # kW +# 'date': '10:11', +# 'energy_source': {'bat': 0.0, 'cp': 0.0, 'grid': 0.0, 'pv': 1.0}, # % +# 'ev': {'ev0': {'soc': None}}, +# 'hc': {'all': {'energy_exported': 0.0, # kWh +# 'energy_imported': 0.004, # kWh +# 'energy_imported_bat': 0.0, # kWh +# 'energy_imported_cp': 0.0, # kWh +# 'energy_imported_grid': 0.0, # kWh +# 'energy_imported_pv': 0.004, # kWh +# 'imported': 32922.337425797836, # Wh +# 'power_average': 0.006, # kW +# 'power_exported': 0, # kW +# 'power_imported': 0.006}}, # kW +# 'prices': {'bat': 0.0002, # €/Wh +# 'cp': 0, # €/Wh +# 'grid': 0.00014862, # €/Wh +# 'pv': 0.00015}, # €/Wh +# 'pv': {'all': {'energy_exported': 4.697, # kWh +# 'energy_imported': 0.0, # kWh +# 'exported': 45013, # Wh +# 'power_average': -7.586, # kW +# 'power_exported': 7.586, # kW +# 'power_imported': 0}, # kW +# 'pv1': {'energy_exported': 4.697, # kWh +# 'energy_imported': 0.0, # kWh +# 'exported': 45013, # Wh +# 'power_average': -7.586, # kW +# 'power_exported': 7.586, # kW +# 'power_imported': 0}}, # kW +# 'sh': {}, +# 'timestamp': 1779351076}], +# 'names': {'bat2': 'MQTT-Speicher', +# 'counter0': 'MQTT-Zähler', +# 'cp3': 'MQTT-Ladepunkt 3', +# 'ev0': 'Standard-Fahrzeug', +# 'pv1': 'MQTT-Wechselrichter'}, +# 'totals': {'bat': {'all': {'energy_exported': 0.0, # Wh +# 'energy_imported': 52.0}, # Wh +# 'bat2': {'energy_exported': 0.0, # Wh +# 'energy_imported': 0.0}}, # Wh +# 'counter': {'counter0': {'energy_exported': 6280.0, # Wh +# 'energy_imported': 0.0, # Wh +# 'grid': True}}, +# 'cp': {'all': {'energy_exported': 0.0, # Wh +# 'energy_imported': 341.0, # Wh +# 'energy_imported_bat': 0.0, # Wh +# 'energy_imported_cp': 0.0, # Wh +# 'energy_imported_grid': 260.0, # Wh +# 'energy_imported_pv': 81.0}, # Wh +# 'cp3': {'energy_exported': 0.0, # Wh +# 'energy_imported': 0.0, # Wh +# 'energy_imported_bat': 0.0, # Wh +# 'energy_imported_cp': 0.0, # Wh +# 'energy_imported_grid': 0.0, # Wh +# 'energy_imported_pv': 0.0}}, # Wh +# 'hc': {'all': {'energy_imported': 39.0, # Wh +# 'energy_imported_bat': 0.0, # Wh +# 'energy_imported_cp': 0.0, # Wh +# 'energy_imported_grid': 35.0, # Wh +# 'energy_imported_pv': 4.0}}, # Wh +# 'pv': {'all': {'energy_exported': 6673.0}, # Wh +# 'pv1': {'energy_exported': 6673.0}}, # Wh +# 'sh': {}}} + +UNIT_KEYS_KILO = ("energy_imported", + "energy_imported_grid", + "energy_imported_pv", + "energy_imported_bat", + "energy_imported_cp", + "energy_exported", + "power_average", + "power_imported", + "power_exported") + + +def convert_legacy_units(data: dict) -> dict: + for entry in data["entries"]: + for group in ("bat", "counter", "cp", "pv", "sh", "hc"): + if group in entry: + for module in entry[group].keys(): + try: + for value in UNIT_KEYS_KILO: + if value in entry[group][module].keys(): + entry[group][module][value] = decimal_divide(entry[group][module][value], 1000) + except KeyError: + log.exception( + f"Fehler beim Konvertieren der Einheiten von {group} {module} in Eintrag " + f"{entry['timestamp']}") + return data + + def safe_get_nested(data: Dict, *keys, default: Union[int, float] = 0) -> Union[int, float]: current = data for key in keys: @@ -92,70 +229,6 @@ def get_totals(entries: List, process_entries: bool = True) -> Dict: f"group:{totals_group}, module:{entry_module}, key:{entry_module_key}") return totals -# {"entries": [ -# { -# "timestamp": int, -# "date": str, -# "cp": { -# "cp1": {"imported": Zählerstand in kW, "exported": Zählerstand in kW} -# ... (dynamisch, je nach konfigurierter Anzahl) -# "all": { -# "imported": Zählerstand in kW, -# "exported": Zählerstand in kW -# } -# } -# "ev": { -# "ev1": {"soc": int in %} -# ... (dynamisch, je nach konfigurierter Anzahl) -# } -# "counter": { -# "counter0": {"imported": kW, "exported": kW} -# ... (dynamisch, je nach konfigurierter Anzahl) -# } -# "pv": { -# "all": {"exported": kW} -# "pv0": {"exported": kW} -# ... (dynamisch, je nach konfigurierter Anzahl) -# } -# "bat": { -# "all": {"imported": kW, "exported": kW, "soc": int in %} -# "bat0": {"imported": kW, "exported": kW, "soc": int in %} -# ... (dynamisch, je nach konfigurierter Anzahl) -# } -# "sh": { -# "sh1": { -# "exported": kW, -# "imported": kW, -# wenn konfiguriert: -# "temp1": int in °C, -# "temp2": int in °C, -# "temp3": int in °C -# }, -# ... (dynamisch, je nach Anzahl konfigurierter Geräte) -# }, -# "energy_source": {"grid": %, "pv": %, "bat": %, "cp": %} -# }], -# "totals": { -# {'bat': {'all': {'exported': 0, 'imported': 175.534}, -# 'bat2': {'exported': 0, 'imported': 172.556}}, -# 'counter': {'counter0': {'exported': 1.105, 'imported': 1.1}}, -# 'cp': {'all': {'exported': 0, 'imported': 105}, -# 'cp3': {'exported': 0, 'imported': 10}, -# 'cp4': {'exported': 0, 'imported': 85}, -# 'cp5': {'exported': 0, 'imported': 0}, -# 'cp6': {'exported': 0, 'imported': 64}}, -# 'ev': {'ev1': {}}, -# 'pv': {'all': {'imported': 251}, 'pv1': {'imported': 247}}}, -# 'sh': { 'sh1': {'exported': 123, 'imported': 123}}, -# "energy_source": {"grid": %, "pv": %, "bat": %, "cp": %} -# }, -# "names": { -# "counter0": "Mein EVU-Zähler", -# "bat2": "Mein toller Speicher", -# ... -# } -# } - def get_daily_log(date: str): data = _collect_daily_log_data(date) diff --git a/packages/helpermodules/measurement_logging/process_log_integration_test.py b/packages/helpermodules/measurement_logging/process_log_integration_test.py index 3bb1156e0a..d6090f0cb8 100644 --- a/packages/helpermodules/measurement_logging/process_log_integration_test.py +++ b/packages/helpermodules/measurement_logging/process_log_integration_test.py @@ -1,25 +1,30 @@ from unittest.mock import Mock -import pytest from helpermodules.measurement_logging import process_log -from helpermodules.measurement_logging.process_log_testdata import (counter_jumps_forward, - counter_jumps_forward_processed, - regular_daily_log_entry, - regular_daily_log_entry_processed) +pytest_plugins = ["helpermodules.measurement_logging.process_log_testdata"] -@pytest.mark.parametrize("data, expected", [ - pytest.param(counter_jumps_forward, counter_jumps_forward_processed, id="counter jumps forward"), - pytest.param(regular_daily_log_entry, regular_daily_log_entry_processed, id="regular daily log entry") -]) -def test_get_daily_log(data, expected, monkeypatch): + +def test_get_daily_log_counter_jump(counter_jumps_forward, counter_jumps_forward_processed, monkeypatch): + # setup + collect_daily_log_data_mock = Mock(return_value=counter_jumps_forward) + monkeypatch.setattr(process_log, "_collect_daily_log_data", collect_daily_log_data_mock) + + # execution + daily_log_processed = process_log.get_daily_log("20250616") + + # evaluation + assert daily_log_processed == counter_jumps_forward_processed + + +def test_get_daily_log_regular(regular_daily_log_entry, regular_daily_log_entry_processed, monkeypatch): # setup - collect_daily_log_data_mock = Mock(return_value=data) + collect_daily_log_data_mock = Mock(return_value=regular_daily_log_entry) monkeypatch.setattr(process_log, "_collect_daily_log_data", collect_daily_log_data_mock) # execution daily_log_processed = process_log.get_daily_log("20250616") # evaluation - assert daily_log_processed == expected + assert daily_log_processed == regular_daily_log_entry_processed diff --git a/packages/helpermodules/measurement_logging/process_log_testdata.py b/packages/helpermodules/measurement_logging/process_log_testdata.py index 032b5f4712..b31cf19fa2 100644 --- a/packages/helpermodules/measurement_logging/process_log_testdata.py +++ b/packages/helpermodules/measurement_logging/process_log_testdata.py @@ -1,447 +1,461 @@ -counter_jumps_forward = {'entries': [{'bat': {'all': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}, - 'bat2': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}}, - 'counter': {'counter0': {'exported': 26029.945, - 'grid': True, - 'imported': 0, - 'fault_state': 0}, - 'counter2': {'exported': 26029.945, - 'grid': False, - 'imported': 0, - 'fault_state': 0}}, - 'cp': {'all': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, - 'cp3': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, - 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, - 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, - 'date': '14:25', - 'ev': {'ev0': {'soc': None, 'fault_state': 0}}, - 'hc': {'all': {'imported': 2324.001611140539, 'fault_state': 0}}, - 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, - 'pv': {'all': {'exported': 35827, 'fault_state': 0}, - 'pv1': {'exported': 35827, 'fault_state': 0}}, - 'sh': {}, - 'timestamp': 1750767902}, - {'bat': {'all': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}, - 'bat2': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}}, - 'counter': {'counter0': {'exported': 26802.355, - 'grid': True, - 'imported': 0, - 'fault_state': 0}, - 'counter2': {'exported': 26029.945, - 'grid': False, - 'imported': 0, - 'fault_state': 0}}, - 'cp': {'all': {'exported': 0, 'imported': 20639.11, 'fault_state': 0}, - 'cp3': {'exported': 0, 'imported': 20639.11, 'fault_state': 0}, - 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, - 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, - 'date': '14:30', - 'ev': {'ev0': {'soc': None, 'fault_state': 0}}, - 'hc': {'all': {'imported': 2361.178611303703, 'fault_state': 0}}, - 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, - 'pv': {'all': {'exported': 36636, 'fault_state': 0}, - 'pv1': {'exported': 36636, 'fault_state': 0}}, - 'sh': {}, - 'timestamp': 1750768201}], - 'names': {'bat2': 'MQTT-Speicher', - 'counter0': 'MQTT-Zähler', - 'counter2': 'Test-Zähler', - 'cp3': 'MQTT-Ladepunkt', - 'cp4': 'MQTT-Ladepunkt', - 'cp5': 'MQTT-Ladepunkt', - 'ev0': 'Standard-Fahrzeug', - 'pv1': 'MQTT-Wechselrichter'}} +import pytest -counter_jumps_forward_processed = {'entries': [{'bat': {'all': {'energy_exported': 0, - 'energy_imported': 0, - 'exported': 3195.13, - 'fault_state': 0, - 'imported': 629.37, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0, - 'soc': 48}, - 'bat2': {'energy_exported': 0, - 'energy_imported': 0, - 'exported': 3195.13, - 'fault_state': 0, - 'imported': 629.37, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0, - 'soc': 48}}, - 'counter': {'counter0': {'energy_exported': 772.41, - 'energy_imported': 0, - 'exported': 26029.945, - 'fault_state': 0, - 'grid': True, - 'imported': 0, - 'power_average': -9299.92, - 'power_exported': 9299.92, - 'power_imported': 0}, - 'counter2': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'exported': 26029.945, - 'fault_state': 0, - 'grid': False, - 'imported': 0, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0}}, - 'cp': {'all': {'energy_exported': 0, - 'energy_imported': 8000, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 8000, - 'exported': 0, - 'fault_state': 0, - 'imported': 12639.11, - 'power_average': 96321.07, - 'power_exported': 0, - 'power_imported': 96321.07}, - 'cp3': {'energy_exported': 0, - 'energy_imported': 8000, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 8000, - 'exported': 0, - 'fault_state': 0, - 'imported': 12639.11, - 'power_average': 96321.07, - 'power_exported': 0, - 'power_imported': 96321.07}, - 'cp4': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'exported': 0, - 'fault_state': 0, - 'imported': 0, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0}, - 'cp5': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'exported': 0, - 'fault_state': 0, - 'imported': 0, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0}}, - 'date': '14:25', - 'energy_source': {'bat': 0.0, 'cp': 0.0, 'grid': 0.0, 'pv': 1.0}, - 'ev': {'ev0': {'fault_state': 0, 'soc': None}}, - 'hc': {'all': {'energy_exported': 0, - 'energy_imported': 37.177, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 37.177, - 'fault_state': 0, - 'imported': 2324.001611140539, - 'power_average': 447.616, - 'power_exported': 0, - 'power_imported': 447.616}}, - 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, - 'pv': {'all': {'energy_exported': 809, - 'energy_imported': 0, - 'exported': 35827, - 'fault_state': 0, - 'power_average': -9740.468, - 'power_exported': 9740.468, - 'power_imported': 0}, - 'pv1': {'energy_exported': 809, - 'energy_imported': 0, - 'exported': 35827, - 'fault_state': 0, - 'power_average': -9740.468, - 'power_exported': 9740.468, - 'power_imported': 0}}, - 'sh': {}, - 'timestamp': 1750767902}], - 'message': '', - 'names': {'bat2': 'MQTT-Speicher', - 'counter0': 'MQTT-Zähler', - 'counter2': 'Test-Zähler', - 'cp3': 'MQTT-Ladepunkt', - 'cp4': 'MQTT-Ladepunkt', - 'cp5': 'MQTT-Ladepunkt', - 'ev0': 'Standard-Fahrzeug', - 'pv1': 'MQTT-Wechselrichter'}, - 'totals': {'bat': {'all': {'energy_exported': 0, 'energy_imported': 0}, - 'bat2': {'energy_exported': 0, 'energy_imported': 0}}, - 'counter': {'counter0': {'energy_exported': 772.41, - 'energy_imported': 0, - 'grid': True}, - 'counter2': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'grid': False}}, - 'cp': {'all': {'energy_exported': 0, - 'energy_imported': 8000, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 8000}, - 'cp3': {'energy_exported': 0, - 'energy_imported': 8000, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 8000}, - 'cp4': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0}, - 'cp5': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0}}, - 'hc': {'all': {'energy_imported': 37.177, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 37.177}}, - 'pv': {'all': {'energy_exported': 809}, - 'pv1': {'energy_exported': 809}}, - 'sh': {}}} -regular_daily_log_entry = {'entries': [{'bat': {'all': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}, - 'bat2': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}}, - 'counter': {'counter0': {'exported': 26029.945, - 'grid': True, - 'imported': 2728.572, - 'fault_state': 0}, }, - 'cp': {'all': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, - 'cp3': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, - 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, - 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, - 'date': '14:25', - 'ev': {'ev0': {'soc': None}}, - 'hc': {'all': {'imported': 2324.001611140539, 'fault_state': 0}}, - 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, - 'pv': {'all': {'exported': 35827, 'fault_state': 0}, - 'pv1': {'exported': 35827, 'fault_state': 0}}, - 'sh': {}, - 'timestamp': 1750767902}, - {'bat': {'all': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}, - 'bat2': {'exported': 3195.13, - 'imported': 629.37, - 'soc': 48, - 'fault_state': 0}}, - 'counter': {'counter0': {'exported': 26802.355, - 'grid': True, - 'imported': 2728.572, - 'fault_state': 0}}, - 'cp': {'all': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, - 'cp3': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, - 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, - 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, - 'date': '14:30', - 'ev': {'ev0': {'soc': None, 'fault_state': 0}}, - 'hc': {'all': {'imported': 2361.178611303703, 'fault_state': 0}}, - 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, - 'pv': {'all': {'exported': 36636, 'fault_state': 0}, - 'pv1': {'exported': 36636, 'fault_state': 0}}, - 'sh': {}, - 'timestamp': 1750768201}], - 'names': {'bat2': 'MQTT-Speicher', - 'counter0': 'MQTT-Zähler', - 'counter2': 'Test-Zähler', - 'cp3': 'MQTT-Ladepunkt', - 'cp4': 'MQTT-Ladepunkt', - 'cp5': 'MQTT-Ladepunkt', - 'ev0': 'Standard-Fahrzeug', - 'pv1': 'MQTT-Wechselrichter'}} +@pytest.fixture() +def counter_jumps_forward(): + return {'entries': [{'bat': {'all': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}, + 'bat2': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}}, + 'counter': {'counter0': {'exported': 26029.945, + 'grid': True, + 'imported': 0, + 'fault_state': 0}, + 'counter2': {'exported': 26029.945, + 'grid': False, + 'imported': 0, + 'fault_state': 0}}, + 'cp': {'all': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, + 'cp3': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, + 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, + 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, + 'date': '14:25', + 'ev': {'ev0': {'soc': None, 'fault_state': 0}}, + 'hc': {'all': {'imported': 2324.001611140539, 'fault_state': 0}}, + 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, + 'pv': {'all': {'exported': 35827, 'fault_state': 0}, + 'pv1': {'exported': 35827, 'fault_state': 0}}, + 'sh': {}, + 'timestamp': 1750767902}, + {'bat': {'all': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}, + 'bat2': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}}, + 'counter': {'counter0': {'exported': 26802.355, + 'grid': True, + 'imported': 0, + 'fault_state': 0}, + 'counter2': {'exported': 26029.945, + 'grid': False, + 'imported': 0, + 'fault_state': 0}}, + 'cp': {'all': {'exported': 0, 'imported': 20639.11, 'fault_state': 0}, + 'cp3': {'exported': 0, 'imported': 20639.11, 'fault_state': 0}, + 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, + 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, + 'date': '14:30', + 'ev': {'ev0': {'soc': None, 'fault_state': 0}}, + 'hc': {'all': {'imported': 2361.178611303703, 'fault_state': 0}}, + 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, + 'pv': {'all': {'exported': 36636, 'fault_state': 0}, + 'pv1': {'exported': 36636, 'fault_state': 0}}, + 'sh': {}, + 'timestamp': 1750768201}], + 'names': {'bat2': 'MQTT-Speicher', + 'counter0': 'MQTT-Zähler', + 'counter2': 'Test-Zähler', + 'cp3': 'MQTT-Ladepunkt', + 'cp4': 'MQTT-Ladepunkt', + 'cp5': 'MQTT-Ladepunkt', + 'ev0': 'Standard-Fahrzeug', + 'pv1': 'MQTT-Wechselrichter'}} -regular_daily_log_entry_processed = {'entries': [{'bat': {'all': {'energy_exported': 0, - 'energy_imported': 0, - 'exported': 3195.13, - 'fault_state': 0, - 'imported': 629.37, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0, - 'soc': 48}, - 'bat2': {'energy_exported': 0, - 'energy_imported': 0, - 'exported': 3195.13, - 'fault_state': 0, - 'imported': 629.37, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0, - 'soc': 48}}, - 'counter': {'counter0': {'energy_exported': 772.41, - 'energy_imported': 0, - 'exported': 26029.945, - 'fault_state': 0, - 'grid': True, - 'imported': 2728.572, - 'power_average': -9299.92, - 'power_exported': 9299.92, - 'power_imported': 0}}, - 'cp': {'all': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'exported': 0, - 'fault_state': 0, - 'imported': 12639.11, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0}, - 'cp3': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'exported': 0, - 'fault_state': 0, - 'imported': 12639.11, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0}, - 'cp4': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'exported': 0, - 'fault_state': 0, - 'imported': 0, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0}, - 'cp5': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0, - 'exported': 0, - 'fault_state': 0, - 'imported': 0, - 'power_average': 0, - 'power_exported': 0, - 'power_imported': 0}}, - 'date': '14:25', - 'energy_source': {'bat': 0.0, 'cp': 0.0, 'grid': 0.0, 'pv': 1.0}, - 'ev': {'ev0': {'soc': None}}, - 'hc': {'all': {'energy_exported': 0, - 'energy_imported': 37.177, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 37.177, - 'fault_state': 0, - 'imported': 2324.001611140539, - 'power_average': 447.616, - 'power_exported': 0, - 'power_imported': 447.616}}, - 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, - 'pv': {'all': {'energy_exported': 809, - 'energy_imported': 0, - 'exported': 35827, - 'fault_state': 0, - 'power_average': -9740.468, - 'power_exported': 9740.468, - 'power_imported': 0}, - 'pv1': {'energy_exported': 809, - 'energy_imported': 0, - 'exported': 35827, - 'fault_state': 0, - 'power_average': -9740.468, - 'power_exported': 9740.468, - 'power_imported': 0}}, - 'sh': {}, - 'timestamp': 1750767902}], - 'message': '', - 'names': {'bat2': 'MQTT-Speicher', - 'counter0': 'MQTT-Zähler', - 'counter2': 'Test-Zähler', - 'cp3': 'MQTT-Ladepunkt', - 'cp4': 'MQTT-Ladepunkt', - 'cp5': 'MQTT-Ladepunkt', - 'ev0': 'Standard-Fahrzeug', - 'pv1': 'MQTT-Wechselrichter'}, - 'totals': {'bat': {'all': {'energy_exported': 0, 'energy_imported': 0}, - 'bat2': {'energy_exported': 0, 'energy_imported': 0}}, - 'counter': {'counter0': {'energy_exported': 772.41, - 'energy_imported': 0, - 'grid': True}}, - 'cp': {'all': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0}, - 'cp3': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0}, - 'cp4': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0}, - 'cp5': {'energy_exported': 0, - 'energy_imported': 0, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 0}}, - 'hc': {'all': {'energy_imported': 37.177, - 'energy_imported_bat': 0, - 'energy_imported_cp': 0, - 'energy_imported_grid': 0, - 'energy_imported_pv': 37.177}}, - 'pv': {'all': {'energy_exported': 809}, - 'pv1': {'energy_exported': 809}}, - 'sh': {}}} + +@pytest.fixture() +def counter_jumps_forward_processed(): + return {'entries': [{'bat': {'all': {'energy_exported': 0, + 'energy_imported': 0, + 'exported': 3195.13, + 'fault_state': 0, + 'imported': 629.37, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0, + 'soc': 48}, + 'bat2': {'energy_exported': 0, + 'energy_imported': 0, + 'exported': 3195.13, + 'fault_state': 0, + 'imported': 629.37, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0, + 'soc': 48}}, + 'counter': {'counter0': {'energy_exported': 772.41, + 'energy_imported': 0, + 'exported': 26029.945, + 'fault_state': 0, + 'grid': True, + 'imported': 0, + 'power_average': -9299.92, + 'power_exported': 9299.92, + 'power_imported': 0}, + 'counter2': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 26029.945, + 'fault_state': 0, + 'grid': False, + 'imported': 0, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}}, + 'cp': {'all': {'energy_exported': 0, + 'energy_imported': 8000, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 8000, + 'exported': 0, + 'fault_state': 0, + 'imported': 12639.11, + 'power_average': 96321.07, + 'power_exported': 0, + 'power_imported': 96321.07}, + 'cp3': {'energy_exported': 0, + 'energy_imported': 8000, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 8000, + 'exported': 0, + 'fault_state': 0, + 'imported': 12639.11, + 'power_average': 96321.07, + 'power_exported': 0, + 'power_imported': 96321.07}, + 'cp4': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 0, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}, + 'cp5': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 0, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}}, + 'date': '14:25', + 'energy_source': {'bat': 0.0, 'cp': 0.0, 'grid': 0.0, 'pv': 1.0}, + 'ev': {'ev0': {'fault_state': 0, 'soc': None}}, + 'hc': {'all': {'energy_exported': 0, + 'energy_imported': 37.177, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 37.177, + 'fault_state': 0, + 'imported': 2324.001611140539, + 'power_average': 447.616, + 'power_exported': 0, + 'power_imported': 447.616}}, + 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, + 'pv': {'all': {'energy_exported': 809, + 'energy_imported': 0, + 'exported': 35827, + 'fault_state': 0, + 'power_average': -9740.468, + 'power_exported': 9740.468, + 'power_imported': 0}, + 'pv1': {'energy_exported': 809, + 'energy_imported': 0, + 'exported': 35827, + 'fault_state': 0, + 'power_average': -9740.468, + 'power_exported': 9740.468, + 'power_imported': 0}}, + 'sh': {}, + 'timestamp': 1750767902}], + 'message': '', + 'names': {'bat2': 'MQTT-Speicher', + 'counter0': 'MQTT-Zähler', + 'counter2': 'Test-Zähler', + 'cp3': 'MQTT-Ladepunkt', + 'cp4': 'MQTT-Ladepunkt', + 'cp5': 'MQTT-Ladepunkt', + 'ev0': 'Standard-Fahrzeug', + 'pv1': 'MQTT-Wechselrichter'}, + 'totals': {'bat': {'all': {'energy_exported': 0, 'energy_imported': 0}, + 'bat2': {'energy_exported': 0, 'energy_imported': 0}}, + 'counter': {'counter0': {'energy_exported': 772.41, + 'energy_imported': 0, + 'grid': True}, + 'counter2': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'grid': False}}, + 'cp': {'all': {'energy_exported': 0, + 'energy_imported': 8000, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 8000}, + 'cp3': {'energy_exported': 0, + 'energy_imported': 8000, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 8000}, + 'cp4': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}, + 'cp5': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}}, + 'hc': {'all': {'energy_imported': 37.177, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 37.177}}, + 'pv': {'all': {'energy_exported': 809}, + 'pv1': {'energy_exported': 809}}, + 'sh': {}}} + + +@pytest.fixture() +def regular_daily_log_entry(): + return {'entries': [{'bat': {'all': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}, + 'bat2': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}}, + 'counter': {'counter0': {'exported': 26029.945, + 'grid': True, + 'imported': 2728.572, + 'fault_state': 0}, }, + 'cp': {'all': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, + 'cp3': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, + 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, + 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, + 'date': '14:25', + 'ev': {'ev0': {'soc': None}}, + 'hc': {'all': {'imported': 2324.001611140539, 'fault_state': 0}}, + 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, + 'pv': {'all': {'exported': 35827, 'fault_state': 0}, + 'pv1': {'exported': 35827, 'fault_state': 0}}, + 'sh': {}, + 'timestamp': 1750767902}, + {'bat': {'all': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}, + 'bat2': {'exported': 3195.13, + 'imported': 629.37, + 'soc': 48, + 'fault_state': 0}}, + 'counter': {'counter0': {'exported': 26802.355, + 'grid': True, + 'imported': 2728.572, + 'fault_state': 0}}, + 'cp': {'all': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, + 'cp3': {'exported': 0, 'imported': 12639.11, 'fault_state': 0}, + 'cp4': {'exported': 0, 'imported': 0, 'fault_state': 0}, + 'cp5': {'exported': 0, 'imported': 0, 'fault_state': 0}}, + 'date': '14:30', + 'ev': {'ev0': {'soc': None, 'fault_state': 0}}, + 'hc': {'all': {'imported': 2361.178611303703, 'fault_state': 0}}, + 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, + 'pv': {'all': {'exported': 36636, 'fault_state': 0}, + 'pv1': {'exported': 36636, 'fault_state': 0}}, + 'sh': {}, + 'timestamp': 1750768201}], + 'names': {'bat2': 'MQTT-Speicher', + 'counter0': 'MQTT-Zähler', + 'counter2': 'Test-Zähler', + 'cp3': 'MQTT-Ladepunkt', + 'cp4': 'MQTT-Ladepunkt', + 'cp5': 'MQTT-Ladepunkt', + 'ev0': 'Standard-Fahrzeug', + 'pv1': 'MQTT-Wechselrichter'}} + + +@pytest.fixture() +def regular_daily_log_entry_processed(): + return {'entries': [{'bat': {'all': {'energy_exported': 0, + 'energy_imported': 0, + 'exported': 3195.13, + 'fault_state': 0, + 'imported': 629.37, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0, + 'soc': 48}, + 'bat2': {'energy_exported': 0, + 'energy_imported': 0, + 'exported': 3195.13, + 'fault_state': 0, + 'imported': 629.37, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0, + 'soc': 48}}, + 'counter': {'counter0': {'energy_exported': 772.41, + 'energy_imported': 0, + 'exported': 26029.945, + 'fault_state': 0, + 'grid': True, + 'imported': 2728.572, + 'power_average': -9299.92, + 'power_exported': 9299.92, + 'power_imported': 0}}, + 'cp': {'all': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 12639.11, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}, + 'cp3': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 12639.11, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}, + 'cp4': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 0, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}, + 'cp5': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0, + 'exported': 0, + 'fault_state': 0, + 'imported': 0, + 'power_average': 0, + 'power_exported': 0, + 'power_imported': 0}}, + 'date': '14:25', + 'energy_source': {'bat': 0.0, 'cp': 0.0, 'grid': 0.0, 'pv': 1.0}, + 'ev': {'ev0': {'soc': None}}, + 'hc': {'all': {'energy_exported': 0, + 'energy_imported': 37.177, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 37.177, + 'fault_state': 0, + 'imported': 2324.001611140539, + 'power_average': 447.616, + 'power_exported': 0, + 'power_imported': 447.616}}, + 'prices': {'bat': 0.0002, 'grid': 0.0003, 'pv': 0.00015}, + 'pv': {'all': {'energy_exported': 809, + 'energy_imported': 0, + 'exported': 35827, + 'fault_state': 0, + 'power_average': -9740.468, + 'power_exported': 9740.468, + 'power_imported': 0}, + 'pv1': {'energy_exported': 809, + 'energy_imported': 0, + 'exported': 35827, + 'fault_state': 0, + 'power_average': -9740.468, + 'power_exported': 9740.468, + 'power_imported': 0}}, + 'sh': {}, + 'timestamp': 1750767902}], + 'message': '', + 'names': {'bat2': 'MQTT-Speicher', + 'counter0': 'MQTT-Zähler', + 'counter2': 'Test-Zähler', + 'cp3': 'MQTT-Ladepunkt', + 'cp4': 'MQTT-Ladepunkt', + 'cp5': 'MQTT-Ladepunkt', + 'ev0': 'Standard-Fahrzeug', + 'pv1': 'MQTT-Wechselrichter'}, + 'totals': {'bat': {'all': {'energy_exported': 0, 'energy_imported': 0}, + 'bat2': {'energy_exported': 0, 'energy_imported': 0}}, + 'counter': {'counter0': {'energy_exported': 772.41, + 'energy_imported': 0, + 'grid': True}}, + 'cp': {'all': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}, + 'cp3': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}, + 'cp4': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}, + 'cp5': {'energy_exported': 0, + 'energy_imported': 0, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 0}}, + 'hc': {'all': {'energy_imported': 37.177, + 'energy_imported_bat': 0, + 'energy_imported_cp': 0, + 'energy_imported_grid': 0, + 'energy_imported_pv': 37.177}}, + 'pv': {'all': {'energy_exported': 809}, + 'pv1': {'energy_exported': 809}}, + 'sh': {}}} diff --git a/packages/helpermodules/utils/precision_math.py b/packages/helpermodules/utils/precision_math.py index 9d79c774e8..e11029cf02 100644 --- a/packages/helpermodules/utils/precision_math.py +++ b/packages/helpermodules/utils/precision_math.py @@ -38,6 +38,14 @@ def decimal_multiply(value1: Union[int, float], value2: Union[int, float]) -> Un return _decimal_to_number(result) +def decimal_divide(numerator: Union[int, float], denominator: Union[int, float]) -> Union[int, float]: + """Divide two values using Decimal to avoid floating point issues.""" + if denominator == 0: + raise ValueError("Denominator cannot be zero.") + result = (Decimal(str(numerator)) / Decimal(str(denominator))).quantize(Decimal('0.001')) + return _decimal_to_number(result) + + def decimal_subtract(value1: Union[int, float], value2: Union[int, float]) -> Union[int, float]: """Subtract two values using Decimal to avoid floating point issues.""" result = (Decimal(str(value1)) - Decimal(str(value2))).quantize(Decimal('0.001'))