Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle not installed python packages #1940

Merged
merged 3 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 115 additions & 106 deletions packages/control/ocpp.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from datetime import datetime
import json
import logging
from ocpp.v16 import call, ChargePoint as OcppChargepoint
import websockets

from helpermodules.utils.error_handling import ImportErrorContext
with ImportErrorContext():
from ocpp.v16 import call, ChargePoint as OcppChargepoint
with ImportErrorContext():
import websockets
import asyncio
from typing import Callable, Optional

Expand All @@ -13,114 +17,119 @@

log = logging.getLogger(__name__)

try:
class OcppMixin:
def _get_formatted_time(self: OptionalProtocol) -> str:
return datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")

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,
def _process_call(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)
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 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 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 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 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}"
f" und Zählerstand: {imported} beendet.")
except Exception as e:
fault_state.from_exception(e)
except NameError:
log.warning("OCPP-Modul nicht installiert. OCPP-Optionen sind deaktiviert.")

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)
class OcppMixin:
pass
9 changes: 6 additions & 3 deletions packages/helpermodules/modbusserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
from collections import defaultdict
import struct
from typing import Optional
from umodbus import conf
from umodbus.server.tcp import RequestHandler, get_server
from umodbus.utils import log_to_stream

from helpermodules.utils.error_handling import ImportErrorContext
with ImportErrorContext():
from umodbus import conf
from umodbus.server.tcp import RequestHandler, get_server
from umodbus.utils import log_to_stream

from helpermodules import timecheck
from helpermodules.hardware_configuration import get_serial_number
Expand Down
5 changes: 4 additions & 1 deletion packages/helpermodules/timecheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import copy
import logging
import datetime
from dateutil.relativedelta import relativedelta
from typing import Dict, List, Optional, Tuple, TypeVar, Union

from helpermodules.utils.error_handling import ImportErrorContext
with ImportErrorContext():
from dateutil.relativedelta import relativedelta

from helpermodules.abstract_plans import AutolockPlan, ScheduledChargingPlan, TimeChargingPlan

log = logging.getLogger(__name__)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import logging
import time

from helpermodules import timecheck
from helpermodules.messaging import MessageType
from helpermodules.pub import Pub


Expand Down Expand Up @@ -41,3 +43,31 @@ def error_counter_exceeded(self) -> bool:
def reset_error_counter(self):
self.error_timestamp = None
Pub().pub(self.topic, self.error_timestamp)


class ImportErrorContext:
def __init__(self):
pass

def __enter__(self):
return None

def __exit__(self, exception_type, exception, exception_traceback) -> bool:
if isinstance(exception, ModuleNotFoundError):
try:
msg = ("Importfehler: Das Python-Modul " + exception.args[0].split("'")[1] + " wurde nicht gefunden." +
" Bitte sicherstellen, dass diese openWB eine Verbindung zum Internet besitzt. Beim nächsten " +
"Neustart wird versucht, fehlende Software-Pakete zu installieren.")
except IndexError:
msg = "Importfehler: " + str(exception)
# pub_system_message() publlished an openWB/set/, dass wird beim Starten gelöscht
log.exception(msg)
now = time.time()
message_payload = {
"source": "command",
"type": MessageType.ERROR.value,
"message": msg,
"timestamp": int(now)
}
Pub().pub(f'openWB/system/messages/{(now * 1000):.0f}', message_payload)
return True
9 changes: 6 additions & 3 deletions packages/modules/backup_clouds/onedrive/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
import pickle
import json
import paho.mqtt.publish as publish
import msal
import base64

from helpermodules.utils.error_handling import ImportErrorContext
with ImportErrorContext():
import msal

from helpermodules.messaging import MessageType
from modules.backup_clouds.onedrive.config import OneDriveBackupCloud, OneDriveBackupCloudConfiguration

Expand Down Expand Up @@ -87,7 +90,7 @@ def generateMSALAuthCode(cloudbackup: OneDriveBackupCloud) -> dict:
app = msal.PublicClientApplication(
client_id=cloudbackup.configuration.clientID,
authority=cloudbackup.configuration.authority
)
)

# create device flow to obtain auth code
flow = app.initiate_device_flow(cloudbackup.configuration.scope)
Expand All @@ -105,7 +108,7 @@ def generateMSALAuthCode(cloudbackup: OneDriveBackupCloud) -> dict:

publish.single(
"openWB/set/system/backup_cloud/config", cloudbackupconfig_to_mqtt, retain=True, hostname="localhost"
)
)

result["message"] = """Autorisierung gestartet, bitte den Link öffnen, Code eingeben,
und Zugang autorisieren. Anschließend Zugangsberechtigung abrufen."""
Expand Down
5 changes: 4 additions & 1 deletion packages/modules/backup_clouds/samba/backup_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import io
import re
import socket
from smb.SMBConnection import SMBConnection

from helpermodules.utils.error_handling import ImportErrorContext
with ImportErrorContext():
from smb.SMBConnection import SMBConnection

from modules.backup_clouds.samba.config import SambaBackupCloud, SambaBackupCloudConfiguration
from modules.common.abstract_device import DeviceDescriptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from control import data
from helpermodules import pub, timecheck
from helpermodules.utils.error_counter import CP_ERROR, ErrorTimerContext
from helpermodules.utils.error_handling import CP_ERROR, ErrorTimerContext
from modules.chargepoints.external_openwb.config import OpenWBSeries
from modules.common.abstract_chargepoint import AbstractChargepoint
from modules.common.abstract_device import DeviceDescriptor
Expand Down
2 changes: 1 addition & 1 deletion packages/modules/chargepoints/mqtt/chargepoint_module.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging

from helpermodules.utils.error_counter import CP_ERROR, ErrorTimerContext
from helpermodules.utils.error_handling import CP_ERROR, ErrorTimerContext
from modules.chargepoints.mqtt.config import Mqtt
from modules.common.abstract_chargepoint import AbstractChargepoint
from modules.common.abstract_device import DeviceDescriptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging

from helpermodules import hardware_configuration
from helpermodules.utils.error_counter import CP_ERROR, ErrorTimerContext
from helpermodules.utils.error_handling import CP_ERROR, ErrorTimerContext
from modules.chargepoints.openwb_dc_adapter.config import OpenWBDcAdapter
from modules.common.abstract_chargepoint import AbstractChargepoint
from modules.common.abstract_device import DeviceDescriptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
import time

from helpermodules.utils.error_counter import CP_ERROR, ErrorTimerContext
from helpermodules.utils.error_handling import CP_ERROR, ErrorTimerContext
from modules.chargepoints.openwb_pro.config import OpenWBPro
from modules.common.abstract_chargepoint import AbstractChargepoint
from modules.common.abstract_device import DeviceDescriptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Optional

from control import data
from helpermodules.utils.error_counter import CP_ERROR, ErrorTimerContext
from helpermodules.utils.error_handling import CP_ERROR, ErrorTimerContext
from modules.chargepoints.openwb_series2_satellit.config import OpenWBseries2Satellit
from modules.common import modbus
from modules.common.abstract_chargepoint import AbstractChargepoint
Expand Down
Loading