From 6baaf5edd3b493c0e71dbc281d81ee4e7af0a6c6 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Thu, 8 Oct 2026 12:20:08 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Verbraucher:=20Bugfixes=20verkn=C3=BCpfte?= =?UTF-8?q?=20Z=C3=A4hler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/control/counter_all/hierarchy.py | 12 ++++++ .../control/counter_all/hierarchy_test.py | 40 +++++++++++++++++++ packages/helpermodules/command.py | 23 +++++++---- packages/helpermodules/command_test.py | 23 ++++++++++- 4 files changed, 90 insertions(+), 8 deletions(-) diff --git a/packages/control/counter_all/hierarchy.py b/packages/control/counter_all/hierarchy.py index 25c0770b76..ebf8dacffa 100644 --- a/packages/control/counter_all/hierarchy.py +++ b/packages/control/counter_all/hierarchy.py @@ -364,12 +364,24 @@ def check_and_remove(name, type_name: ComponentType, data_structure): check_and_remove("consumer", ComponentType.CONSUMER, data.data.consumer_data) def _add_missing_entries(self: HierarchyProtocol): + linked_extra_meter_counter_ids = { + consumer.data.extra_meter + for consumer in data.data.consumer_data.values() + if consumer.data.extra_meter is not None + } + def check_and_add(type_name: ComponentType, data_structure): for entry in data_structure: break_flag = False re_result = re.search("[0-9]+", entry) if re_result is not None: entry_num = int(re_result.group()) + else: + continue + + if type_name == ComponentType.COUNTER and entry_num in linked_extra_meter_counter_ids: + continue + for level in self.get_list_of_elements_per_level(): for element in level: if entry_num == element["id"] and element["type"] == type_name.value: diff --git a/packages/control/counter_all/hierarchy_test.py b/packages/control/counter_all/hierarchy_test.py index 6cf5a1456d..2f0d73d418 100644 --- a/packages/control/counter_all/hierarchy_test.py +++ b/packages/control/counter_all/hierarchy_test.py @@ -1,7 +1,10 @@ from typing import Dict, List, Optional, Union from unittest.mock import Mock import pytest +from control.consumer.consumer import Consumer +from control.consumer.consumer_data import ConsumerData from packages.conftest import hierarchy_hybrid, hierarchy_nested, hierarchy_standard +from control import data from control.counter import Counter @@ -401,6 +404,43 @@ def test_add_missing_entries(hierarchy, expected_hierarchy, data_, monkeypatch): assert counter_all.data.get.hierarchy == expected_hierarchy +def test_add_missing_entries_re_adds_removed_linked_counter(monkeypatch): + # setup + data.data_init(Mock()) + data.data.counter_data = { + "counter0": Mock(spec=Counter, num=0), + "counter6": Mock(spec=Counter, num=6), + } + data.data.bat_data = {} + data.data.cp_data = {} + data.data.pv_data = {} + data.data.consumer_data = {"consumer7": Mock(spec=Consumer, data=Mock(spec=ConsumerData, extra_meter=6))} + + counter_all = CounterAll() + counter_all.data.get.hierarchy = [{ + "id": 0, + "type": "counter", + "children": [ + {"id": 7, "type": "consumer", "children": []}, + ] + }] + + c = Mock(spec=Counter, num=0) + monkeypatch.setattr(CounterAll, "get_evu_counter", Mock(return_value=c)) + + # execution + counter_all._add_missing_entries() + + # evaluation + assert counter_all.data.get.hierarchy == [{ + "id": 0, + "type": "counter", + "children": [ + {"id": 7, "type": "consumer", "children": []}, + ] + }] + + @pytest.mark.parametrize("hierarchy, expected_ids", [ pytest.param(hierarchy_hybrid(), [2], id="hybrid"), diff --git a/packages/helpermodules/command.py b/packages/helpermodules/command.py index a2f44cabb8..93db6f1ad5 100644 --- a/packages/helpermodules/command.py +++ b/packages/helpermodules/command.py @@ -82,7 +82,7 @@ def __init__(self, event_command_completed: Event): try: self.event_command_completed = event_command_completed self._get_max_ids() - self._get_max_id_by_json_object("hierarchy", "counter/get/hierarchy/", -1) + self._get_max_id_hierarchy_by_topics(-1) except Exception: log.exception("Fehler im Command-Modul") @@ -125,13 +125,22 @@ def _get_max_ids(self) -> None: except Exception: log.exception("Fehler im Command-Modul") - def _get_max_id_by_json_object(self, id_topic: str, topic: str, default: int) -> None: - """ ermittelt die maximale ID vom Broker """ + def _get_max_id_hierarchy_by_topics(self, default: int) -> None: + """Ermittelt die maximale Hierarchie-ID ausschließlich aus Topics.""" try: - hierarchy = ProcessBrokerBranch(topic).get_payload() - max_id = counter_all.get_max_id_in_hierarchy(hierarchy, default) - setattr(self, f'max_id_{id_topic}', max_id) - Pub().pub(f'openWB/set/command/max_id/{id_topic}', max_id) + max_id = default + topics = ProcessBrokerBranch("").get_max_id() + hierarchy_topic_pattern = re.compile(r"openWB/(counter|chargepoint|consumer|pv|bat)/[0-9]+(/|$)") + for topic in topics: + if hierarchy_topic_pattern.search(topic) is None: + continue + try: + max_id = max(max_id, int(get_index(topic))) + except ValueError: + continue + + self.max_id_hierarchy = max_id + Pub().pub("openWB/set/command/max_id/hierarchy", max_id) except Exception: log.exception("Fehler im Command-Modul") diff --git a/packages/helpermodules/command_test.py b/packages/helpermodules/command_test.py index d01f479802..1ce9956ab9 100644 --- a/packages/helpermodules/command_test.py +++ b/packages/helpermodules/command_test.py @@ -46,7 +46,7 @@ def subdata_fixture() -> None: def test_check_max_num_of_internal_chargepoints(additional_cp_mode, config, expected_msg, subdata_fixture, monkeypatch): # setup monkeypatch.setattr(Command, "_get_max_ids", Mock()) - monkeypatch.setattr(Command, "_get_max_id_by_json_object", Mock()) + monkeypatch.setattr(Command, "_get_max_id_hierarchy_by_topics", Mock()) if additional_cp_mode: SubData.cp_data.update( {"cp1": Mock(spec=ChargepointStateUpdate, chargepoint=Mock( @@ -107,3 +107,24 @@ def test_add_consumer_uses_module_default_usage_type(usage_type, mock_pub, monke if call.args[0] == "openWB/set/consumer/1/usage"] assert len(usage_calls) == 1 assert usage_calls[0].args[1]["type"] == usage_type.value + + +def test_get_max_id_hierarchy_by_topics(mock_pub, monkeypatch): + class ProcessBrokerBranchMock: + def __init__(self, topic_str: str) -> None: + self.topic_str = topic_str + + def get_max_id(self): + return { + "openWB/counter/4/get/power": 500, + "openWB/chargepoint/9/config": {"id": 9}, + "openWB/consumer/5/module": {"type": "dummy"}, + } + + monkeypatch.setattr(command, "ProcessBrokerBranch", ProcessBrokerBranchMock) + + command_instance = Command.__new__(Command) + command_instance._get_max_id_hierarchy_by_topics(-1) + + assert command_instance.max_id_hierarchy == 9 + mock_pub.pub.assert_any_call("openWB/set/command/max_id/hierarchy", 9) From 1c866967ab9733ceeec300aaff94990e992ce4c3 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Thu, 8 Oct 2026 12:39:27 +0200 Subject: [PATCH 2/3] review --- packages/helpermodules/command.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/helpermodules/command.py b/packages/helpermodules/command.py index 93db6f1ad5..de117189df 100644 --- a/packages/helpermodules/command.py +++ b/packages/helpermodules/command.py @@ -7,7 +7,7 @@ import subprocess from threading import Event from time import sleep -from typing import Dict, Optional +from typing import Any, Dict, Optional import re import traceback from pathlib import Path @@ -81,12 +81,13 @@ class Command: def __init__(self, event_command_completed: Event): try: self.event_command_completed = event_command_completed - self._get_max_ids() - self._get_max_id_hierarchy_by_topics(-1) + max_id_received_topics = ProcessBrokerBranch("").get_max_id() + self._get_max_ids(max_id_received_topics) + self._get_max_id_hierarchy_by_topics(max_id_received_topics, -1) except Exception: log.exception("Fehler im Command-Modul") - def _get_max_ids(self) -> None: + def _get_max_ids(self, max_id_received_topics: Dict[str, Any]) -> None: """ ermittelt die maximale ID vom Broker """ plan_extractors = { "autolock_plan": lambda p: p.get("autolock", {}).get("plans", []), @@ -97,11 +98,10 @@ def _get_max_ids(self) -> None: "consumer_time_plan": lambda p: p.get("time_charging", {}).get("plans", []), } try: - received_topics = ProcessBrokerBranch("").get_max_id() for max_id_type in self.MAX_IDS.keys(): for id_topic, topic_str, default in self.MAX_IDS[max_id_type]: max_id = default - for topic, payload in received_topics.items(): + for topic, payload in max_id_received_topics.items(): try: if max_id_type == "nested payload": if re.search(topic_str, topic) is not None and payload is not None: @@ -125,13 +125,12 @@ def _get_max_ids(self) -> None: except Exception: log.exception("Fehler im Command-Modul") - def _get_max_id_hierarchy_by_topics(self, default: int) -> None: + def _get_max_id_hierarchy_by_topics(self, max_id_received_topics: Dict[str, Any], default: int) -> None: """Ermittelt die maximale Hierarchie-ID ausschließlich aus Topics.""" try: max_id = default - topics = ProcessBrokerBranch("").get_max_id() hierarchy_topic_pattern = re.compile(r"openWB/(counter|chargepoint|consumer|pv|bat)/[0-9]+(/|$)") - for topic in topics: + for topic in max_id_received_topics.keys(): if hierarchy_topic_pattern.search(topic) is None: continue try: From 6737fd6fd26e03c5eaedff4e24bead8862fa79fc Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Thu, 8 Oct 2026 12:43:58 +0200 Subject: [PATCH 3/3] review --- packages/helpermodules/command_test.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/helpermodules/command_test.py b/packages/helpermodules/command_test.py index 1ce9956ab9..ef2c35d72a 100644 --- a/packages/helpermodules/command_test.py +++ b/packages/helpermodules/command_test.py @@ -110,21 +110,12 @@ def test_add_consumer_uses_module_default_usage_type(usage_type, mock_pub, monke def test_get_max_id_hierarchy_by_topics(mock_pub, monkeypatch): - class ProcessBrokerBranchMock: - def __init__(self, topic_str: str) -> None: - self.topic_str = topic_str - - def get_max_id(self): - return { - "openWB/counter/4/get/power": 500, - "openWB/chargepoint/9/config": {"id": 9}, - "openWB/consumer/5/module": {"type": "dummy"}, - } - - monkeypatch.setattr(command, "ProcessBrokerBranch", ProcessBrokerBranchMock) - command_instance = Command.__new__(Command) - command_instance._get_max_id_hierarchy_by_topics(-1) + command_instance._get_max_id_hierarchy_by_topics({ + "openWB/counter/4/get/power": 500, + "openWB/chargepoint/9/config": {"id": 9}, + "openWB/consumer/5/module": {"type": "dummy"}, + }, -1) assert command_instance.max_id_hierarchy == 9 mock_pub.pub.assert_any_call("openWB/set/command/max_id/hierarchy", 9)