From 05156f6b8dbded6e871dee12b6e63bc0125ea12d Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Wed, 26 Nov 2025 12:18:12 +0100 Subject: [PATCH 1/2] metadata for cp --- packages/control/chargelog/chargelog.py | 4 - packages/control/chargepoint/chargepoint.py | 86 ++++--------------- .../control/chargepoint/chargepoint_data.py | 41 ++++----- packages/control/chargepoint/rfid.py | 3 - packages/control/process.py | 1 - packages/helpermodules/command.py | 1 - packages/helpermodules/setdata.py | 3 +- packages/helpermodules/update_config.py | 1 - 8 files changed, 41 insertions(+), 99 deletions(-) diff --git a/packages/control/chargelog/chargelog.py b/packages/control/chargelog/chargelog.py index e60f61942c..0b2099cba7 100644 --- a/packages/control/chargelog/chargelog.py +++ b/packages/control/chargelog/chargelog.py @@ -8,11 +8,9 @@ from typing import Any, Dict, List, Optional, Tuple from control import data -from dataclass_utils import asdict from helpermodules.measurement_logging.process_log import ( FILE_ERRORS, CalculationType, _analyse_energy_source, _process_entries, analyse_percentage, get_log_from_date_until_now, get_totals) -from helpermodules.pub import Pub from helpermodules import timecheck from helpermodules.utils.json_file_handler import write_and_check @@ -116,7 +114,6 @@ def collect_data(chargepoint): log_data.time_charged += now - log_data.timestamp_start_charging log_data.timestamp_start_charging = None log_data.end = now - Pub().pub(f"openWB/set/chargepoint/{chargepoint.num}/set/log", asdict(log_data)) except Exception: log.exception("Fehler im Ladelog-Modul") @@ -299,7 +296,6 @@ def calc_energy_costs(cp, create_log_entry: bool = False): f"total charged_energy_by_source {cp.data.set.log.charged_energy_by_source}") costs = _calc_costs(charged_energy_by_source, reference_entries[-1]["prices"]) cp.data.set.log.costs += costs - Pub().pub(f"openWB/set/chargepoint/{cp.num}/set/log", asdict(cp.data.set.log)) def calculate_charged_energy_by_source(cp, processed_entries, reference_entries, create_log_entry: bool = False): diff --git a/packages/control/chargepoint/chargepoint.py b/packages/control/chargepoint/chargepoint.py index 29357161f3..2233541d31 100644 --- a/packages/control/chargepoint/chargepoint.py +++ b/packages/control/chargepoint/chargepoint.py @@ -97,21 +97,6 @@ def _is_grid_protection_inactive(self) -> Tuple[bool, Optional[str]]: message = "Ladepunkt gesperrt, da der Netzschutz aktiv ist." return state, message - def _is_loadmanagement_available(self) -> Tuple[bool, Optional[str]]: - """ prüft, ob Lastmanagement verfügbar ist. Wenn keine Werte vom EVU-Zähler empfangen werden, darf nicht geladen - werden. - """ - if self.data.set.loadmanagement_available: - state = True - message = None - else: - state = False - message = ("Ladepunkt gesperrt, da keine Werte vom EVU- oder Zwischenzähler-Zähler empfangen wurden und " - "deshalb kein Lastmanagement durchgeführt werden kann. Bitte schaue auf der Status-Seite nach " - "Fehlermeldungen bei den Zählern. Falls Du dennoch laden möchtest, kannst Du als " - "Gerät 'Virtuelles Gerät' mit einer Komponente 'Virtueller Zähler' verwenden.") - return state, message - def _is_autolock_inactive(self) -> Tuple[bool, Optional[str]]: """ prüft, ob Autolock nicht aktiv ist oder ob die Sperrung durch einen dem LP zugeordneten ID-Tag aufgehoben werden kann. @@ -149,10 +134,6 @@ def _is_manual_lock_inactive(self) -> Tuple[bool, Optional[str]]: (self.data.get.vehicle_id is not None and fnmatch(self.data.get.vehicle_id, tag_id)) or (self.data.set.rfid is not None and fnmatch(self.data.set.rfid, tag_id))): match = True - if match: - Pub().pub(f"openWB/set/chargepoint/{self.num}/set/manual_lock", False) - elif self.template.data.disable_after_unplug and self.data.get.plug_state is False: - Pub().pub(f"openWB/set/chargepoint/{self.num}/set/manual_lock", True) if self.data.set.manual_lock: charging_possible = False @@ -160,6 +141,11 @@ def _is_manual_lock_inactive(self) -> Tuple[bool, Optional[str]]: else: charging_possible = True message = None + + if match: + self.data.set.manual_lock = False + elif self.template.data.disable_after_unplug and self.data.get.plug_state is False: + self.data.set.manual_lock = True return charging_possible, message def _is_ev_plugged(self) -> Tuple[bool, Optional[str]]: @@ -175,13 +161,11 @@ def is_charging_possible(self) -> Tuple[bool, Optional[str]]: try: charging_possible, message = self._is_grid_protection_inactive() if charging_possible: - charging_possible, message = self._is_loadmanagement_available() + charging_possible, message = self._is_manual_lock_inactive() if charging_possible: - charging_possible, message = self._is_manual_lock_inactive() + charging_possible, message = self._is_ev_plugged() if charging_possible: - charging_possible, message = self._is_ev_plugged() - if charging_possible: - charging_possible, message = self._is_autolock_inactive() + charging_possible, message = self._is_autolock_inactive() except Exception: log.exception("Fehler in der Ladepunkt-Klasse von "+str(self.num)) return False, "Keine Ladung, da ein interner Fehler aufgetreten ist: "+traceback.format_exc() @@ -198,7 +182,7 @@ def _process_charge_stop(self) -> None: self.data.get.imported, self.data.set.ocpp_transaction_id, self.data.set.rfid) - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/ocpp_transaction_id", None) + self.data.set.ocpp_transaction_id = None self.reset_control_parameter_at_charge_stop() data.data.counter_all_data.get_evu_counter().reset_switch_on_off(self) if self.data.get.plug_state is False and self.data.set.plug_state_prev is True: @@ -206,28 +190,18 @@ def _process_charge_stop(self) -> None: self.data.control_parameter = control_parameter_factory() if self.data.set.charge_template.data.load_default: self.data.config.ev = 0 - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/config/ev", 0) if self.template.data.disable_after_unplug: self.data.set.manual_lock = True - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/manual_lock", True) log.debug("/set/manual_lock True") if data.data.general_data.data.temporary_charge_templates_active: self.update_charge_template( data.data.ev_data["ev"+str(self.data.config.ev)].charge_template) self.data.set.rfid = None - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/rfid", None) self.data.set.plug_time = None - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/plug_time", None) self.data.set.phases_to_use = self.data.get.phases_in_use - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/phases_to_use", - self.data.set.phases_to_use) self.data.set.current = 0 - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/current", 0) - self.data.set.energy_to_charge = 0 - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/energy_to_charge", 0) def setup_values_at_start(self): - self._reset_values_at_start() self._set_values_at_start() def set_control_parameter(self, submode: str): @@ -253,24 +227,15 @@ def set_control_parameter(self, submode: str): except Exception: log.exception("Fehler im LP-Modul "+str(self.num)) - def _reset_values_at_start(self): - self.data.set.loadmanagement_available = True - def _set_values_at_start(self): if self.data.get.plug_state and self.data.set.plug_time is None: self.data.set.plug_time = timecheck.create_timestamp() - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/plug_time", - self.data.set.plug_time) def remember_previous_values(self): self.data.set.charge_state_prev = self.data.get.charge_state self.data.set.plug_state_prev = self.data.get.plug_state self.data.set.current_prev = self.data.set.current self.data.set.ev_prev = self.data.config.ev - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/charge_state_prev", self.data.set.charge_state_prev) - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/plug_state_prev", self.data.set.plug_state_prev) - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/current_prev", self.data.set.current_prev) - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/ev_prev", self.data.set.ev_prev) def reset_log_data_chargemode_switch(self) -> None: reset_log = Log() @@ -423,8 +388,6 @@ def initiate_phase_switch(self): self.data.set.log.imported_since_plugged == 0): # Einmal muss die Anzahl der Phasen gesetzt werden. if self.data.set.phases_to_use == 0: - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/phases_to_use", - self.data.control_parameter.phases) self.data.set.phases_to_use = self.data.control_parameter.phases if self.hw_supports_phase_switch(): if self._is_phase_switch_required(): @@ -456,8 +419,6 @@ def initiate_phase_switch(self): self.data.control_parameter.timestamp_last_phase_switch = create_timestamp() self.set_state_and_log(message) if self.data.set.phases_to_use != self.data.control_parameter.phases: - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/phases_to_use", - self.data.control_parameter.phases) self.data.set.phases_to_use = self.data.control_parameter.phases self.data.control_parameter.state = ChargepointState.PERFORMING_PHASE_SWITCH else: @@ -742,8 +703,6 @@ def update(self, ev_list: Dict[str, Ev]) -> None: self.num, self.data.set.rfid or self.data.get.rfid or self.data.get.vehicle_id, self.data.get.imported) - Pub().pub("openWB/set/chargepoint/"+str(self.num) + - "/set/ocpp_transaction_id", self.data.set.ocpp_transaction_id) if self.data.get.plug_state and self.data.set.plug_state_prev is False: self.data.control_parameter.timestamp_chargemode_changed = create_timestamp() # SoC nach Anstecken aktualisieren @@ -784,12 +743,12 @@ def _get_charging_ev(self, vehicle: int, ev_list: Dict[str, Ev]) -> Ev: Pub().pub(f"openWB/set/vehicle/{charging_ev.num}/get/force_soc_update", True) log.debug("SoC nach EV-Wechsel") self.data.config.ev = vehicle - Pub().pub(f"openWB/set/chargepoint/{self.num}/config", dataclasses.asdict(self.data.config)) self.data.set.charging_ev_data = charging_ev return charging_ev def update_charge_template(self, charge_template: ChargeTemplate) -> None: # Prüfen, ob ein temporäres Ladeprofil aktiv ist und dieses übernehmen + self.data.set.charge_template = charge_template Pub().pub(f"openWB/set/chargepoint/{self.num}/set/charge_template", dataclasses.asdict(charge_template.data)) @@ -804,24 +763,24 @@ def _pub_connected_vehicle(self, vehicle: Ev): LP-Nummer """ try: - soc_obj = ConnectedSoc( + self.data.get.connected_vehicle.soc = ConnectedSoc( range_charged=self.data.set.log.range_charged, range_unit=data.data.general_data.data.range_unit, ) if vehicle.soc_module is not None: - soc_obj.timestamp = vehicle.data.get.soc_timestamp - soc_obj.soc = vehicle.data.get.soc - soc_obj.fault_state = vehicle.data.get.fault_state - soc_obj.fault_str = vehicle.data.get.fault_str - soc_obj.range = vehicle.data.get.range - info_obj = ConnectedInfo(id=vehicle.num, - name=vehicle.data.name) + self.data.get.connected_vehicle.soc.timestamp = vehicle.data.get.soc_timestamp + self.data.get.connected_vehicle.soc.soc = vehicle.data.get.soc + self.data.get.connected_vehicle.soc.fault_state = vehicle.data.get.fault_state + self.data.get.connected_vehicle.soc.fault_str = vehicle.data.get.fault_str + self.data.get.connected_vehicle.soc.range = vehicle.data.get.range + self.data.get.connected_vehicle.info = ConnectedInfo(id=vehicle.num, + name=vehicle.data.name) if (self.data.set.charge_template.data.chargemode.selected == "time_charging" or self.data.set.charge_template.data.chargemode.selected == "scheduled_charging"): current_plan = self.data.control_parameter.current_plan else: current_plan = None - config_obj = ConnectedConfig( + self.data.get.connected_vehicle.config = ConnectedConfig( charge_template=self.data.set.charge_template.data.id, ev_template=vehicle.ev_template.data.id, chargemode=self.data.set.charge_template.data.chargemode.selected, @@ -830,13 +789,6 @@ def _pub_connected_vehicle(self, vehicle: Ev): average_consumption=vehicle.ev_template.data.average_consump, time_charging_in_use=True if (self.data.control_parameter.submode == "time_charging") else False) - if soc_obj != self.data.get.connected_vehicle.soc: - Pub().pub(f"openWB/chargepoint/{self.num}/get/connected_vehicle/soc", dataclasses.asdict(soc_obj)) - if info_obj != self.data.get.connected_vehicle.info: - Pub().pub(f"openWB/chargepoint/{self.num}/get/connected_vehicle/info", dataclasses.asdict(info_obj)) - if config_obj != self.data.get.connected_vehicle.config: - Pub().pub(f"openWB/chargepoint/{self.num}/get/connected_vehicle/config", - dataclasses.asdict(config_obj)) except Exception: log.exception("Fehler im Prepare-Modul") diff --git a/packages/control/chargepoint/chargepoint_data.py b/packages/control/chargepoint/chargepoint_data.py index 6a4f435c3e..35afda4f13 100644 --- a/packages/control/chargepoint/chargepoint_data.py +++ b/packages/control/chargepoint/chargepoint_data.py @@ -59,9 +59,11 @@ def connected_soc_factory() -> ConnectedSoc: @dataclass class ConnectedVehicle: - config: ConnectedConfig = field(default_factory=connected_config_factory) - info: ConnectedInfo = field(default_factory=connected_info_factory) - soc: ConnectedSoc = field(default_factory=connected_soc_factory) + config: ConnectedConfig = field(default_factory=connected_config_factory, + metadata={"topic": "get/connected_vehicle/config"}) + info: ConnectedInfo = field(default_factory=connected_info_factory, + metadata={"topic": "get/connected_vehicle/info"}) + soc: ConnectedSoc = field(default_factory=connected_soc_factory, metadata={"topic": "get/connected_vehicle/soc"}) def empty_enery_source_dict_factory(): @@ -148,25 +150,24 @@ def log_factory() -> Log: @dataclass class Set: - charge_template: ChargeTemplate = field(default_factory=charge_template_factory) - current: float = 0 - energy_to_charge: float = 0 - ev_prev: int = 0 - loadmanagement_available: bool = True - log: Log = field(default_factory=log_factory) - manual_lock: bool = False - phases_to_use: int = 0 - plug_state_prev: bool = False - plug_time: Optional[float] = None - required_power: float = 0 - rfid: Optional[str] = None + charge_template: ChargeTemplate = field(default_factory=charge_template_factory, + metadata={"topic": "set/charge_template"}) + current: float = field(default=0, metadata={"topic": "set/current"}) + ev_prev: int = field(default=0, metadata={"topic": "set/ev_prev"}) + log: Log = field(default_factory=log_factory, metadata={"topic": "set/log"}) + manual_lock: bool = field(default=False, metadata={"topic": "set/manual_lock"}) + phases_to_use: int = field(default=0, metadata={"topic": "set/phases_to_use"}) + plug_state_prev: bool = field(default=False, metadata={"topic": "set/plug_state_prev"}) + plug_time: Optional[float] = field(default=None, metadata={"topic": "set/plug_time"}) + required_power: float = field(default=0, metadata={"topic": "set/required_power"}) + rfid: Optional[str] = field(default=None, metadata={"topic": "set/rfid"}) # set current aus dem vorherigen Zyklus, um zu wissen, ob am Ende des Zyklus die Ladung freigegeben wird # (für Control-Pilot-Unterbrechung) - current_prev: float = 0.0 - target_current: float = 0 # Soll-Strom aus fest vorgegebener Stromstärke + current_prev: float = field(default=0.0, metadata={"topic": "set/current_prev"}) + target_current: float = field(default=0, metadata={"topic": "set/target_current"}) charging_ev_data: Ev = field(default_factory=ev_factory) - ocpp_transaction_id: Optional[int] = None - charge_state_prev: bool = False + ocpp_transaction_id: Optional[int] = field(default=None, metadata={"topic": "set/ocpp_transaction_id"}) + charge_state_prev: bool = field(default=False, metadata={"topic": "set/charge_state_prev"}) @dataclass @@ -225,7 +226,7 @@ class ChargepointData: control_parameter: ControlParameter = field(default_factory=control_parameter_factory) get: Get = field(default_factory=get_factory) set: Set = field(default_factory=set_factory) - config: Config = field(default_factory=config_factory) + config: Config = field(default_factory=config_factory, metadata={"topic": "config"}) def set_event(self, event: Optional[Event] = None) -> None: self.event_update_state = event diff --git a/packages/control/chargepoint/rfid.py b/packages/control/chargepoint/rfid.py index 70c565b244..eec1dfd575 100644 --- a/packages/control/chargepoint/rfid.py +++ b/packages/control/chargepoint/rfid.py @@ -29,7 +29,6 @@ def _link_rfid_to_cp(self: ChargepointProtocol) -> None: # keine Duo cp2_data is None): self.data.set.rfid = rfid - Pub().pub("openWB/chargepoint/"+str(self.num)+"/set/rfid", rfid) self.chargepoint_module.clear_rfid() self.data.get.rfid = None @@ -65,10 +64,8 @@ def _validate_rfid(self) -> None: self.data.get.rfid_timestamp = None if self.template.data.disable_after_unplug: self.data.set.manual_lock = True - Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/manual_lock", True) if self.data.set.charging_ev_data.charge_template.data.load_default: self.data.config.ev = 0 - Pub().pub(f"openWB/set/chargepoint/{self.num}/config", asdict(self.data.config)) Pub().pub(f"openWB/set/chargepoint/{self.num}/get/rfid_timestamp", None) msg = ("Es ist in den letzten 5 Minuten kein EV angesteckt worden, dem " f"der ID-Tag {rfid} zugeordnet werden kann. Daher wird dieser verworfen.") diff --git a/packages/control/process.py b/packages/control/process.py index ebea5b5366..524bad7021 100644 --- a/packages/control/process.py +++ b/packages/control/process.py @@ -139,7 +139,6 @@ def _update_state(self, chargepoint: chargepoint.Chargepoint) -> None: current = 0 chargepoint.data.set.current = current - Pub().pub("openWB/set/chargepoint/"+str(chargepoint.num)+"/set/current", current) log.info(f"LP{chargepoint.num}: set current {current} A, " f"state {ChargepointState(chargepoint.data.control_parameter.state).name}") diff --git a/packages/helpermodules/command.py b/packages/helpermodules/command.py index 345d8bc8d0..49a82fb272 100644 --- a/packages/helpermodules/command.py +++ b/packages/helpermodules/command.py @@ -254,7 +254,6 @@ def addChargepoint(self, connection_id: str, payload: dict) -> None: """ def setup_added_chargepoint(): Pub().pub(f'openWB/chargepoint/{new_id}/config', chargepoint_config) - Pub().pub(f'openWB/chargepoint/{new_id}/set/manual_lock', False) {Pub().pub(f"openWB/chargepoint/{new_id}/get/"+k, v) for (k, v) in asdict(chargepoint.Get()).items()} charge_template = SubData.ev_charge_template_data[f"ct{SubData.ev_data['ev0'].data.charge_template}"] charge_template = dataclass_utils.asdict(charge_template.data) diff --git a/packages/helpermodules/setdata.py b/packages/helpermodules/setdata.py index 067ede9af8..c988cd005a 100644 --- a/packages/helpermodules/setdata.py +++ b/packages/helpermodules/setdata.py @@ -476,8 +476,7 @@ def process_chargepoint_topic(self, msg: mqtt.MQTTMessage): self._validate_value(msg, float, [(float("-inf"), 0), (0, 0), (6, 32), (0, 450)]) else: self._validate_value(msg, float, [(float("-inf"), 0), (6, 32), (0, 0)]) - elif ("/set/energy_to_charge" in msg.topic or - "/set/required_power" in msg.topic): + elif "/set/required_power" in msg.topic: self._validate_value(msg, float, [(0, float("inf"))]) elif "/set/phases_to_use" in msg.topic: self._validate_value(msg, int, [(0, 3)]) diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 8650124c05..18ecd07724 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -145,7 +145,6 @@ class UpdateConfig: "^openWB/chargepoint/[0-9]+/get/rfid_timestamp$", "^openWB/chargepoint/[0-9]+/set/charge_template$", "^openWB/chargepoint/[0-9]+/set/current$", - "^openWB/chargepoint/[0-9]+/set/energy_to_charge$", "^openWB/chargepoint/[0-9]+/set/manual_lock$", "^openWB/chargepoint/[0-9]+/set/charge_state_prev$", "^openWB/chargepoint/[0-9]+/set/plug_state_prev$", From 0f445a10f4479af22a2b0f09d6e235c3a9237e02 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Wed, 26 Nov 2025 13:02:45 +0100 Subject: [PATCH 2/2] flake8 --- packages/control/chargepoint/rfid.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/control/chargepoint/rfid.py b/packages/control/chargepoint/rfid.py index eec1dfd575..93a50e13e5 100644 --- a/packages/control/chargepoint/rfid.py +++ b/packages/control/chargepoint/rfid.py @@ -1,5 +1,4 @@ import logging -from dataclasses import asdict from typing import Optional from control import data