diff --git a/packages/control/chargepoint/chargepoint.py b/packages/control/chargepoint/chargepoint.py index f4998fb97b..a657886f3e 100644 --- a/packages/control/chargepoint/chargepoint.py +++ b/packages/control/chargepoint/chargepoint.py @@ -206,6 +206,15 @@ def is_charging_possible(self) -> Tuple[bool, Optional[str]]: def _process_charge_stop(self) -> None: # Charging Ev ist noch das EV des vorherigen Zyklus, wenn das nicht -1 war und jetzt nicht mehr geladen # werden soll (-1), Daten zurücksetzen. + # Ocpp Stop Funktion aufrufen + if not self.data.get.plug_state and self.data.set.ocpp_transaction_id is not None: + data.data.optional_data.stop_transaction( + self.data.config.ocpp_chargebox_id, + self.chargepoint_module.fault_state, + 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) if self.data.set.charging_ev_prev != -1: # Daten zurücksetzen, wenn nicht geladen werden soll. self.reset_control_parameter_at_charge_stop() @@ -712,6 +721,17 @@ def update(self, ev_list: Dict[str, Ev]) -> None: self._pub_connected_vehicle(ev_list[f"ev{vehicle}"]) else: self._pub_configured_ev(ev_list) + # OCPP Start Transaction nach Anstecken + if ((self.data.get.plug_state and self.data.set.plug_state_prev is False) or + (self.data.set.ocpp_transaction_id is None and self.data.get.charge_state)): + self.data.set.ocpp_transaction_id = data.data.optional_data.start_transaction( + self.data.config.ocpp_chargebox_id, + self.chargepoint_module.fault_state, + 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) # SoC nach Anstecken aktualisieren if ((self.data.get.plug_state and self.data.set.plug_state_prev is False) or (self.data.get.plug_state is False and self.data.set.plug_state_prev)): diff --git a/packages/control/chargepoint/chargepoint_data.py b/packages/control/chargepoint/chargepoint_data.py index d7807f0eda..a42511116a 100644 --- a/packages/control/chargepoint/chargepoint_data.py +++ b/packages/control/chargepoint/chargepoint_data.py @@ -140,6 +140,7 @@ class Set: rfid: Optional[str] = None target_current: float = 0 # Soll-Strom aus fest vorgegebener Stromstärke charging_ev_data: Ev = field(default_factory=ev_factory) + ocpp_transaction_id: Optional[int] = None @dataclass @@ -154,6 +155,7 @@ class Config: auto_phase_switch_hw: bool = False control_pilot_interruption_hw: bool = False id: int = 0 + ocpp_chargebox_id: Optional[str] = None def __post_init__(self): self.event_update_state: threading.Event diff --git a/packages/control/ocpp.py b/packages/control/ocpp.py new file mode 100644 index 0000000000..64a565de98 --- /dev/null +++ b/packages/control/ocpp.py @@ -0,0 +1,126 @@ +from datetime import datetime +import json +import logging +from ocpp.v16 import call, ChargePoint as OcppChargepoint +import websockets +import asyncio +from typing import Callable, Optional + +from control import data +from control.optional_data import OptionalProtocol +from modules.common.fault_state import FaultState + + +log = logging.getLogger(__name__) + + +class OcppMixin: + def _get_formatted_time(self: OptionalProtocol) -> str: + return datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ") + + def _process_call(self: OptionalProtocol, + chargebox_id: str, + fault_state: FaultState, + func: Callable) -> Optional[websockets.WebSocketClientProtocol]: + async def make_call() -> websockets.WebSocketClientProtocol: + async with websockets.connect(self.data.ocpp.url+chargebox_id, + subprotocols=[self.data.ocpp.version]) as ws: + try: + cp = OcppChargepoint(chargebox_id, ws, 2) + await cp.call(func) + except asyncio.exceptions.TimeoutError: + # log.exception("Erwarteter TimeOut StartTransaction") + pass + return ws + try: + if self.data.ocpp.active and chargebox_id: + return asyncio.run(make_call()) + except websockets.exceptions.InvalidStatusCode: + fault_state.warning(f"Chargebox ID {chargebox_id} konnte nicht im OCPP-Backend gefunden werden oder " + "URL des Backends ist falsch.") + return None + + def boot_notification(self: OptionalProtocol, + chargebox_id: str, + fault_state: FaultState, + model: str, + serial_number: str) -> Optional[int]: + try: + self._process_call(chargebox_id, fault_state, call.BootNotification( + charge_point_model=model, + charge_point_vendor="openWB", + firmware_version=data.data.system_data["system"].data["version"], + meter_serial_number=serial_number + )) + except Exception as e: + fault_state.from_exception(e) + + def start_transaction(self: OptionalProtocol, + chargebox_id: str, + fault_state: FaultState, + connector_id: int, + id_tag: str, + imported: int) -> Optional[int]: + try: + ws = self._process_call(chargebox_id, fault_state, call.StartTransaction( + connector_id=connector_id, + id_tag=id_tag if id_tag else "", + meter_start=int(imported), + timestamp=self._get_formatted_time() + )) + if ws: + tansaction_id = json.loads(ws.messages[0])[2]["transactionId"] + log.debug(f"Transaction ID: {tansaction_id} für Chargebox ID: {chargebox_id} mit Tag: {id_tag} und " + f"Zählerstand: {imported} erhalten.") + return tansaction_id + except Exception as e: + fault_state.from_exception(e) + return None + + def transfer_values(self: OptionalProtocol, + chargebox_id: str, + fault_state: FaultState, + connector_id: int, + imported: int) -> None: + try: + self._process_call(chargebox_id, fault_state, call.MeterValues( + connector_id=connector_id, + meter_value=[{"timestamp": self._get_formatted_time(), + "sampledValue": [ + { + "value": f'{int(imported)}', + "context": "Sample.Periodic", + "format": "Raw", + "measurand": "Energy.Active.Import.Register", + "unit": "Wh" + }, + ]}], + )) + log.debug(f"Zählerstand {imported} an Chargebox ID: {chargebox_id} übermittelt.") + except Exception as e: + fault_state.from_exception(e) + + def send_heart_beat(self: OptionalProtocol, chargebox_id: str, fault_state: FaultState) -> None: + try: + self._process_call(chargebox_id, fault_state, call.Heartbeat()) + log.debug(f"Heartbeat an Chargebox ID: {chargebox_id} gesendet.") + except Exception as e: + fault_state.from_exception(e) + + def stop_transaction(self: OptionalProtocol, + chargebox_id: str, + fault_state: FaultState, + imported: int, + transaction_id: int, + id_tag: str) -> None: + try: + self._process_call(chargebox_id, fault_state, call.StopTransaction(meter_stop=int(imported), + timestamp=self._get_formatted_time(), + transaction_id=transaction_id, + reason="EVDisconnected", + id_tag=id_tag if id_tag else "" + )) + log.debug(f"Transaction mit ID: {transaction_id} für Chargebox ID: {chargebox_id} mit Tag: {id_tag} und " + f"Zählerstand: {imported} beendet.") + except Exception as e: + fault_state.from_exception(e) diff --git a/packages/control/ocpp_test.py b/packages/control/ocpp_test.py new file mode 100644 index 0000000000..d9e3efa51f --- /dev/null +++ b/packages/control/ocpp_test.py @@ -0,0 +1,77 @@ +from unittest.mock import Mock +import pytest + +from control import data +from control.chargepoint.chargepoint import Chargepoint +from control.chargepoint.chargepoint_template import CpTemplate +from control.counter import Counter +from control.ev import Ev +from modules.chargepoints.mqtt.chargepoint_module import ChargepointModule +from modules.chargepoints.mqtt.config import Mqtt + + +@pytest.fixture() +def mock_data() -> None: + data.data_init(Mock()) + data.data.optional_data.data.ocpp.active = True + data.data.optional_data.data.ocpp.url = "ws://localhost:9000/" + + +def test_start_transaction(mock_data, monkeypatch): + cp = Chargepoint(1, None) + cp.data.config.ocpp_chargebox_id = "cp1" + cp.data.get.plug_state = True + cp.template = CpTemplate() + cp.chargepoint_module = ChargepointModule(Mqtt()) + + start_transaction_mock = Mock() + monkeypatch.setattr(data.data.optional_data, "start_transaction", start_transaction_mock) + _pub_configured_ev_mock = Mock() + monkeypatch.setattr(cp, "_pub_configured_ev", _pub_configured_ev_mock) + + cp.update([]) + + assert start_transaction_mock.call_args == (("cp1", cp.chargepoint_module.fault_state, 1, None, 0),) + + +def test_stop_transaction(mock_data, monkeypatch): + cp = Chargepoint(1, None) + cp.data.config.ocpp_chargebox_id = "cp1" + cp.data.get.plug_state = False + cp.data.set.ocpp_transaction_id = 124 + cp.data.set.charging_ev_prev = 1 + cp.chargepoint_module = ChargepointModule(Mqtt()) + cp.template = CpTemplate() + + stop_transaction_mock = Mock() + monkeypatch.setattr(data.data.optional_data, "stop_transaction", stop_transaction_mock) + get_evu_counter_mock = Mock(return_value=Mock(spec=Counter)) + monkeypatch.setattr(data.data.counter_all_data, "get_evu_counter", get_evu_counter_mock) + data.data.ev_data["ev1"] = Ev(1) + + cp._process_charge_stop() + + assert stop_transaction_mock.call_args == (("cp1", cp.chargepoint_module.fault_state, 0, 124, None),) + + +def test_send_ocpp_data(mock_data, monkeypatch): + data.data.cp_data["cp1"] = Chargepoint(1, None) + data.data.cp_data["cp1"].data.config.ocpp_chargebox_id = "cp1" + data.data.cp_data["cp1"].data.get.plug_state = True + data.data.cp_data["cp1"].chargepoint_module = ChargepointModule(Mqtt()) + data.data.cp_data["cp1"].data.get.serial_number = "123456" + transfer_values_mock = Mock() + monkeypatch.setattr(data.data.optional_data, "transfer_values", transfer_values_mock) + boot_notification_mock = Mock() + monkeypatch.setattr(data.data.optional_data, "boot_notification", boot_notification_mock) + send_heart_beat_mock = Mock() + monkeypatch.setattr(data.data.optional_data, "send_heart_beat", send_heart_beat_mock) + + data.data.optional_data.ocpp_boot_notification_sent = False + + data.data.optional_data._transfer_meter_values() + + boot_notification_mock.call_args == (("cp1", "mqtt", "123456"),) + send_heart_beat_mock.call_args == (("cp1",),) + transfer_values_mock.call_args == (("cp1", 1, 0),) + assert data.data.optional_data.ocpp_boot_notification_sent is True diff --git a/packages/control/optional.py b/packages/control/optional.py index a4007408d1..8a33678668 100644 --- a/packages/control/optional.py +++ b/packages/control/optional.py @@ -1,91 +1,31 @@ """Optionale Module """ -from dataclasses import dataclass, field import logging from math import ceil # Aufrunden import threading -from typing import Dict, List +from typing import List -from dataclass_utils.factories import empty_dict_factory +from control import data +from control.ocpp import OcppMixin +from control.optional_data import OptionalData from helpermodules import hardware_configuration from helpermodules.constants import NO_ERROR from helpermodules.pub import Pub from helpermodules.timecheck import create_unix_timestamp_current_full_hour from helpermodules.utils import thread_handler from modules.common.configurable_tariff import ConfigurableElectricityTariff -from modules.display_themes.cards.config import CardsDisplayTheme log = logging.getLogger(__name__) -@dataclass -class EtGet: - fault_state: int = 0 - fault_str: str = NO_ERROR - prices: Dict = field(default_factory=empty_dict_factory) - - -def get_factory() -> EtGet: - return EtGet() - - -@dataclass -class Et: - get: EtGet = field(default_factory=get_factory) - - -def et_factory() -> Et: - return Et() - - -@dataclass -class InternalDisplay: - active: bool = False - on_if_plugged_in: bool = True - pin_active: bool = False - pin_code: str = "0000" - standby: int = 60 - theme: CardsDisplayTheme = CardsDisplayTheme() - - -def int_display_factory() -> InternalDisplay: - return InternalDisplay() - - -@dataclass -class Led: - active: bool = False - - -def led_factory() -> Led: - return Led() - - -@dataclass -class Rfid: - active: bool = False - - -def rfid_factory() -> Rfid: - return Rfid() - - -@dataclass -class OptionalData: - et: Et = field(default_factory=et_factory) - int_display: InternalDisplay = field(default_factory=int_display_factory) - led: Led = field(default_factory=led_factory) - rfid: Rfid = field(default_factory=rfid_factory) - dc_charging: bool = False - - -class Optional: +class Optional(OcppMixin): def __init__(self): try: self.data = OptionalData() self.et_module: ConfigurableElectricityTariff = None self.data.dc_charging = hardware_configuration.get_hardware_configuration_setting("dc_charging") Pub().pub("openWB/optional/dc_charging", self.data.dc_charging) + self.ocpp_boot_notification_sent = False except Exception: log.exception("Fehler im Optional-Modul") @@ -153,3 +93,27 @@ def et_get_prices(self): Pub().pub("openWB/set/optional/et/get/fault_str", NO_ERROR) except Exception: log.exception("Fehler im Optional-Modul") + + def ocpp_transfer_meter_values(self): + try: + if self.data.ocpp.active: + thread_handler(threading.Thread(target=self._transfer_meter_values, args=(), name="OCPP Client")) + except Exception: + log.exception("Fehler im OCPP-Optional-Modul") + + def _transfer_meter_values(self): + for cp in data.data.cp_data.values(): + try: + if self.ocpp_boot_notification_sent is False: + # Boot-Notfification nicht in der init-Funktion aufrufen, da noch nicht alles initialisiert ist + self.boot_notification(cp.data.config.ocpp_chargebox_id, + cp.chargepoint_module.fault_state, + cp.chargepoint_module.config.type, + cp.data.get.serial_number) + self.ocpp_boot_notification_sent = True + if cp.data.set.ocpp_transaction_id is not None: + self.send_heart_beat(cp.data.config.ocpp_chargebox_id, cp.chargepoint_module.fault_state) + self.transfer_values(cp.data.config.ocpp_chargebox_id, + cp.chargepoint_module.fault_state, cp.num, int(cp.data.get.imported)) + except Exception: + log.exception("Fehler im OCPP-Optional-Modul") diff --git a/packages/control/optional_data.py b/packages/control/optional_data.py new file mode 100644 index 0000000000..80f7ac4dd3 --- /dev/null +++ b/packages/control/optional_data.py @@ -0,0 +1,84 @@ +from dataclasses import dataclass, field +from typing import Dict, Optional, Protocol + +from dataclass_utils.factories import empty_dict_factory +from helpermodules.constants import NO_ERROR +from modules.display_themes.cards.config import CardsDisplayTheme + + +@dataclass +class EtGet: + fault_state: int = 0 + fault_str: str = NO_ERROR + prices: Dict = field(default_factory=empty_dict_factory) + + +def get_factory() -> EtGet: + return EtGet() + + +@dataclass +class Et: + get: EtGet = field(default_factory=get_factory) + + +def et_factory() -> Et: + return Et() + + +@dataclass +class InternalDisplay: + active: bool = False + on_if_plugged_in: bool = True + pin_active: bool = False + pin_code: str = "0000" + standby: int = 60 + theme: CardsDisplayTheme = CardsDisplayTheme() + + +def int_display_factory() -> InternalDisplay: + return InternalDisplay() + + +@dataclass +class Led: + active: bool = False + + +def led_factory() -> Led: + return Led() + + +@dataclass +class Rfid: + active: bool = False + + +def rfid_factory() -> Rfid: + return Rfid() + + +@dataclass +class Ocpp: + active: bool = False + url: Optional[str] = None + version: str = "ocpp1.6" + + +def ocpp_factory() -> Ocpp: + return Ocpp() + + +@dataclass +class OptionalData: + et: Et = field(default_factory=et_factory) + int_display: InternalDisplay = field(default_factory=int_display_factory) + led: Led = field(default_factory=led_factory) + rfid: Rfid = field(default_factory=rfid_factory) + dc_charging: bool = False + ocpp: Ocpp = field(default_factory=ocpp_factory) + + +class OptionalProtocol(Protocol): + @property + def data(self) -> OptionalData: ... diff --git a/packages/control/process.py b/packages/control/process.py index 5831b01c08..0a742fe277 100644 --- a/packages/control/process.py +++ b/packages/control/process.py @@ -10,6 +10,7 @@ from control.chargepoint.chargepoint_state import ChargepointState from helpermodules.pub import Pub from helpermodules.utils._thread_handler import joined_thread_handler +from modules.common.fault_state_level import FaultStateLevel log = logging.getLogger(__name__) @@ -53,6 +54,8 @@ def process_algorithm_results(self) -> None: f"openWB/set/chargepoint/{cp.num}/get/state_str", "Ladevorgang wurde gestartet... (bei Problemen: Prüfe bitte zuerst in den Einstellungen" " 'Ladeeinstellungen' und 'Konfiguration'.)") + if cp.chargepoint_module.fault_state.fault_state != FaultStateLevel.NO_ERROR: + cp.chargepoint_module.fault_state.store_error() modules_threads.append(self._start_charging(cp)) except Exception: log.exception("Fehler im Process-Modul für Ladepunkt "+str(cp)) diff --git a/packages/helpermodules/logger.py b/packages/helpermodules/logger.py index 435088fa73..06bd3c6c6e 100644 --- a/packages/helpermodules/logger.py +++ b/packages/helpermodules/logger.py @@ -81,6 +81,7 @@ def mb_to_bytes(megabytes: int) -> int: logging.getLogger("pymodbus").setLevel(logging.WARNING) logging.getLogger("uModbus").setLevel(logging.WARNING) + logging.getLogger("websockets").setLevel(logging.WARNING) def threading_excepthook(args): logging.getLogger(__name__).error("Uncaught exception in threading.excepthook:", exc_info=( diff --git a/packages/helpermodules/setdata.py b/packages/helpermodules/setdata.py index 1658400283..3a09686ea1 100644 --- a/packages/helpermodules/setdata.py +++ b/packages/helpermodules/setdata.py @@ -541,6 +541,7 @@ def process_chargepoint_topic(self, msg: mqtt.MQTTMessage): elif ("/set/manual_lock" in msg.topic or "/set/perform_control_pilot_interruption" in msg.topic or "/set/perform_phase_switch" in msg.topic or + "/set/ocpp_transaction_active" in msg.topic or "/set/plug_state_prev" in msg.topic): self._validate_value(msg, bool) elif "/set/autolock_state" in msg.topic: @@ -548,6 +549,8 @@ def process_chargepoint_topic(self, msg: mqtt.MQTTMessage): elif ("/set/rfid" in msg.topic or "/set/plug_time" in msg.topic): self._validate_value(msg, float) + elif "/set/ocpp_transaction_id" in msg.topic: + self._validate_value(msg, int) elif "/set/log" in msg.topic: self._validate_value(msg, "json") elif "/config/ev" in msg.topic: @@ -851,7 +854,8 @@ def process_optional_topic(self, msg: mqtt.MQTTMessage): self._validate_value(msg, int, [(0, 2)]) elif "openWB/set/optional/et/get/fault_str" in msg.topic: self._validate_value(msg, str) - elif "openWB/set/optional/et/provider" in msg.topic: + elif ("openWB/set/optional/et/provider" in msg.topic or + "openWB/set/optional/ocpp/config" in msg.topic): self._validate_value(msg, "json") elif "openWB/set/optional/rfid/active" in msg.topic: self._validate_value(msg, bool) diff --git a/packages/helpermodules/subdata.py b/packages/helpermodules/subdata.py index a866fff1b5..82a99dfb7b 100644 --- a/packages/helpermodules/subdata.py +++ b/packages/helpermodules/subdata.py @@ -9,26 +9,20 @@ import subprocess import paho.mqtt.client as mqtt -from control import bat_all, bat, pv_all +from control import bat_all, bat, counter, counter_all, ev, general, optional, pv, pv_all from control.chargepoint import chargepoint -from control import counter -from control import counter_all -from control import ev -from control import general from control.chargepoint.chargepoint_all import AllChargepoints from control.chargepoint.chargepoint_data import Log from control.chargepoint.chargepoint_state_update import ChargepointStateUpdate from control.chargepoint.chargepoint_template import CpTemplate, CpTemplateData -from helpermodules import graph +from control.optional_data import Ocpp +from helpermodules import graph, system from helpermodules.abstract_plans import AutolockPlan from helpermodules.broker import InternalBrokerClient from helpermodules.messaging import MessageType, pub_system_message from helpermodules.utils.run_command import run_command from helpermodules.utils.topic_parser import decode_payload, get_index, get_second_index -from control import optional from helpermodules.pub import Pub -from helpermodules import system -from control import pv from dataclass_utils import dataclass_from_dict from modules.common.abstract_vehicle import CalculatedSocState, GeneralVehicleConfig from modules.common.configurable_backup_cloud import ConfigurableBackupCloud @@ -659,6 +653,8 @@ def process_optional_topic(self, var: optional.Optional, msg: mqtt.MQTTMessage): self.set_json_payload_class(var.data.led, msg) elif re.search("/optional/rfid/", msg.topic) is not None: self.set_json_payload_class(var.data.rfid, msg) + elif re.search("/optional/ocpp/", msg.topic) is not None: + self.set_json_payload_class(var.data.ocpp, msg) elif re.search("/optional/int_display/", msg.topic) is not None: self.set_json_payload_class(var.data.int_display, msg) if re.search("/(standby|active|rotation)$", msg.topic) is not None: @@ -683,6 +679,9 @@ def process_optional_topic(self, var: optional.Optional, msg: mqtt.MQTTMessage): var.et_get_prices() else: self.set_json_payload_class(var.data.et, msg) + elif re.search("/optional/ocpp/", msg.topic) is not None: + config_dict = decode_payload(msg.payload) + var.data.ocpp = dataclass_from_dict(Ocpp, config_dict) else: self.set_json_payload_class(var.data, msg) except Exception: diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 6251afc440..2295fd0132 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -11,6 +11,7 @@ from control.bat_all import BatConsiderationMode from control.chargepoint.charging_type import ChargingType from control.general import ChargemodeConfig +from control.optional_data import Ocpp import dataclass_utils from control.chargepoint.chargepoint_template import get_chargepoint_template_default @@ -128,6 +129,8 @@ class UpdateConfig: "^openWB/chargepoint/[0-9]+/set/log$", "^openWB/chargepoint/[0-9]+/set/phases_to_use$", "^openWB/chargepoint/[0-9]+/set/charging_ev_prev$", + "^openWB/chargepoint/[0-9]+/set/ocpp_transaction_id$", + "^openWB/chargepoint/[0-9]+/set/ocpp_transaction_active$", "^openWB/command/max_id/autolock_plan$", "^openWB/command/max_id/charge_template$", @@ -252,6 +255,7 @@ class UpdateConfig: "^openWB/optional/int_display/only_local_charge_points", "^openWB/optional/led/active$", "^openWB/optional/rfid/active$", + "^openWB/optional/ocpp/config$", "^openWB/pv/config/configured$", "^openWB/pv/get/exported$", @@ -499,6 +503,7 @@ class UpdateConfig: ("openWB/optional/int_display/theme", dataclass_utils.asdict(CardsDisplayTheme())), ("openWB/optional/int_display/only_local_charge_points", False), ("openWB/optional/led/active", False), + ("openWB/optional/ocpp/config", dataclass_utils.asdict(Ocpp())), ("openWB/optional/rfid/active", False), ("openWB/system/backup_cloud/config", NO_MODULE), ("openWB/system/backup_cloud/backup_before_update", True), diff --git a/packages/main.py b/packages/main.py index 8a0bc15694..e191d5674f 100755 --- a/packages/main.py +++ b/packages/main.py @@ -18,23 +18,16 @@ from threading import Thread from control.chargelog.chargelog import calculate_charge_cost +from control import data, prepare, process +from control.algorithm import algorithm +from helpermodules import command, setdata, subdata, timecheck, update_config from helpermodules.changed_values_handler import ChangedValuesContext from helpermodules.measurement_logging.update_yields import update_daily_yields, update_pv_monthly_yearly_yields from helpermodules.measurement_logging.write_log import LogType, save_log -from modules import loadvars -from modules import configuration -from helpermodules import timecheck, update_config -from helpermodules import subdata -from helpermodules import setdata -from helpermodules import command from helpermodules.modbusserver import start_modbus_server from helpermodules.pub import Pub -from control import prepare -from control import data -from control import process -from control.algorithm import algorithm from helpermodules.utils import exit_after -from modules import update_soc +from modules import configuration, loadvars, update_soc from modules.internal_chargepoint_handler.internal_chargepoint_handler import GeneralInternalChargepointHandler from modules.internal_chargepoint_handler.rfid import RfidReader from modules.utils import wait_for_module_update_completed @@ -94,6 +87,7 @@ def handler5MinAlgorithm(self): update_pv_monthly_yearly_yields() data.data.general_data.grid_protection() data.data.optional_data.et_get_prices() + data.data.optional_data.ocpp_transfer_meter_values() data.data.counter_all_data.validate_hierarchy() except KeyboardInterrupt: log.critical("Ausführung durch exit_after gestoppt: "+traceback.format_exc()) diff --git a/packages/modules/chargepoints/mqtt/chargepoint_module.py b/packages/modules/chargepoints/mqtt/chargepoint_module.py index 65c7af517b..769376a064 100644 --- a/packages/modules/chargepoints/mqtt/chargepoint_module.py +++ b/packages/modules/chargepoints/mqtt/chargepoint_module.py @@ -20,8 +20,7 @@ def __init__(self, config: Mqtt) -> None: f"openWB/set/chargepoint/{self.config.id}/get/error_timestamp", CP_ERROR, hide_exception=True) def set_current(self, current: float) -> None: - with SingleComponentUpdateContext(self.fault_state): - log.debug("MQTT-Ladepunkte abonnieren die Soll-Stromstärke direkt vom Broker.") + log.debug("MQTT-Ladepunkte abonnieren die Soll-Stromstärke direkt vom Broker.") def get_values(self) -> None: with SingleComponentUpdateContext(self.fault_state): diff --git a/requirements.txt b/requirements.txt index 78cb018b81..1fe5751786 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,3 +23,10 @@ pytz==2023.3.post1 grpcio==1.60.1 protobuf==4.25.3 bimmer_connected==0.16.1 +# ocpp +jsonschema==4.22.0 +jsonschema-specifications==2023.12.1 +ocpp==1.0.0 +referencing==0.35.1 +rpds-py==0.18.1 +websockets==12.0