Victron Geräte Verbindung via Bluetooth

das ist die Datei die auch bi mir auf dem VanPi ist

kannst du da die Änderungen direkt reinmachen? :slight_smile:

Wie gesagt, die Änderungen stammen nicht von mir! Ich möchte mich nicht mit fremden Federn schmücken :nerd_face:

Ja – hier ist deine Original-Datei, mit den Änderungen sauber eingetragen, so dass unbekannte OffReason-Werte (wie 129) nicht mehr crashen, sondern als Zahl durchgereicht werden.

> Wichtig: Damit try/except funktioniert, muss das außerhalb des Dicts passieren (so ist es unten).

from typing import Optional, Union

from victron_ble.devices.base import (

BitReader,

ChargerError,

Device,

DeviceData,

OffReason,

OperationMode,

)

class DcDcConverterData(DeviceData):

def get_charge_state(self) -> Optional\[OperationMode\]:

    """

    Return an enum indicating the current charging state

    """

    return self.\_data\["device_state"\]

def get_charger_error(self) -> Optional\[ChargerError\]:

    """

    Return an enum indicating the error code

    """

    return self.\_data\["charger_error"\]

def get_input_voltage(self) -> Optional\[float\]:

    """

    Return the input voltage in volts

    """

    return self.\_data\["input_voltage"\]

def get_output_voltage(self) -> Optional\[float\]:

    """

    Return the output voltage in volts

    """

    return self.\_data\["output_voltage"\]

def get_off_reason(self) -> Union\[OffReason, int\]:

    """

    Return an error code stating the reason for the output to be off

    If the OffReason value is unknown to this library version, the raw int

    value will be returned instead of raising an exception.

    """

    return self.\_data\["off_reason"\]

class DcDcConverter(Device):

data_type = DcDcConverterData

def parse_decrypted(self, decrypted: bytes) -> dict:

    reader = BitReader(decrypted)

    \# Charge State:   0 - Off

    \#                 3 - Bulk

    \#                 4 - Absorption

    \#                 5 - Float

    device_state = reader.read_unsigned_int(8)

    \# Charger Error Code

    charger_error = reader.read_unsigned_int(8)

    \# Input voltage reading in 0.01V increments

    input_voltage = reader.read_unsigned_int(16)

    \# Output voltage in 0.01V

    output_voltage = reader.read_signed_int(16)

    \# Reason for Charger Off

    off_reason = reader.read_unsigned_int(32)

    \# --- FIX: handle unknown OffReason values gracefully ---

    try:

        off_reason_parsed = OffReason(off_reason)

    except ValueError:

        \# Keep raw numeric code if library doesn't know this enum value yet

        off_reason_parsed = off_reason

    return {

        "device_state": (

            OperationMode(device_state) if device_state != 0xFF else None

        ),

        "charger_error": (

            ChargerError(charger_error) if charger_error != 0xFF else None

        ),

        "input_voltage": input_voltage / 100 if input_voltage != 0xFFFF else None,

        "output_voltage": (

            output_voltage / 100 if output_voltage != 0x7FFF else None

        ),

        "off_reason": off_reason_parsed,

    }

So spielst du das ein (Reihenfolge – bitte genau so)

  1. Datei editieren

sudo nano /usr/local/lib/python3.11/dist-packages/victron_ble/devices/dcdc_converter.py

→ Inhalt komplett ersetzen durch den Code oben, speichern.

  1. Syntax testen (RUN & POST OUTPUT, falls Fehler)

python3 -m py_compile /usr/local/lib/python3.11/dist-packages/victron_ble/devices/dcdc_converter.py

  1. Test

/usr/local/bin/victron-ble read D4:4B:0F:DA:CB:DA@DEINKEY

Wenn du danach weiterhin Probleme hast: poste bitte die Ausgabe von Schritt 2 (falls es eine gibt) und die erste Fehlermeldung aus Schritt 3.

root@pekaway:/etc# python3 -m py_compile /usr/local/lib/python3.11/dist-packages/victron_ble/devices/dcdc_converter.py
  File "/usr/local/lib/python3.11/dist-packages/victron_ble/devices/dcdc_converter.py", line 64
    \# --- FIX: handle unknown OffReason values gracefully ---
     ^
SyntaxError: unexpected character after line continuation character

from typing import Optional

from victron_ble.devices.base import (
    BitReader,
    ChargerError,
    Device,
    DeviceData,
    OffReason,
    OperationMode,
)


class DcDcConverterData(DeviceData):
    def get_charge_state(self) -> Optional[OperationMode]:
        """
        Return an enum indicating the current charging state
        """
        return self._data["device_state"]

    def get_charger_error(self) -> Optional[ChargerError]:
        """
        Return an enum indicating the error code
        """
        return self._data["charger_error"]

    def get_input_voltage(self) -> Optional[float]:
        """
        Return the input voltage in volts
        """
        return self._data["input_voltage"]

    def get_output_voltage(self) -> Optional[float]:
        """
        Return the output voltage in volts
        """
        return self._data["output_voltage"]

    def get_off_reason(self) -> OffReason:
        """
        Return an error code stating the reason for the output to be off
        """
        return self._data["off_reason"]


class DcDcConverter(Device):
    data_type = DcDcConverterData

    def parse_decrypted(self, decrypted: bytes) -> dict:
        reader = BitReader(decrypted)

        # Charge State:   0 - Off
        #                 3 - Bulk
        #                 4 - Absorption
        #                 5 - Float
        device_state = reader.read_unsigned_int(8)
        # Charger Error Code
        charger_error = reader.read_unsigned_int(8)
        # Input voltage reading in 0.01V increments
        input_voltage = reader.read_unsigned_int(16)
        # Output voltage in 0.01V
        output_voltage = reader.read_signed_int(16)
        # Reason for Charger Off
        off_reason = reader.read_unsigned_int(32)
        \# --- FIX: handle unknown OffReason values gracefully ---

    try:

        off_reason_parsed = OffReason(off_reason)

    except ValueError:

        \# Keep raw numeric code if library doesn't know this enum value yet

        off_reason_parsed = off_reason

        return {
            "device_state": (
                OperationMode(device_state) if device_state != 0xFF else None
            ),
            "charger_error": (
                ChargerError(charger_error) if charger_error != 0xFF else None
            ),
            "input_voltage": input_voltage / 100 if input_voltage != 0xFFFF else None,
            "output_voltage": (
                output_voltage / 100 if output_voltage != 0x7FFF else None
            ),
            "off_reason": OffReason(off_reason),
        }

Ich verstehe den Sinn der Backslash vor der Raute, die setzt man normal am Zeitenende um einenneinzeiler besser lesbar zu machen.

Ich würde die einfach mal löschen oder um sie weiter stehen zu lassen mit einer Raute davor auskommentiert…

Also #\#

Ich verstehe aber nicht was du da machen musst, ich hatte mit victron_ble auch meine Geräte ausgelesen, bis ich es zum laufen hatte brauchte ein wenig arbeit, bis ich eine virtuelle python Environment laufen hatte.

Wie gesagt ich mache es per esp32 c6 und ble und sende die Werte direkt an mqtt, weil mein pi4 oft auf 70-80% lief und alles so langsam war.

Gruß

Roland

hab den Fehler wie hier victron_ble\devices\base.py beschrieben gefixed :slight_smile:

ENGINE_SHUTDOWN = 0x00000080

diese Zeile eingefügt in base.py
    ENGINE_SHUTDOWN_AND_INPUT_VOLTAGE_LOCKOUT = 0x00000081

ANALYSING_INPUT_VOLTAGE = 0x00000100

und dann mit

python3 -m py_compile /usr/local/lib/python3.11/dist-packages/victron_ble/devices/base.py

compiliert → läuft jetzt :+1:

Das hört man gerne, super!

Gruß

Roland

Edit: Setze deinen Lösungsbeitrag auf “Solution”, dann können andere direkt sehen was geholfen hat.