Hallo zusammen,
ich habe mir nachfolgendes script gebaut und dachte mir vielleicht hilft es dem einen oder anderen ja auch.
Es wird Python benötigt und es muss eine dependency installiert werden (pymodbus), hierfür empfehle ich eine virtualenv zu verwenden. In einem Terminal seiner Wahl (Windows sollte auch funktionieren, habe ich aber noch nicht getestet):
mkdir ein_name_deiner_wahl
um einen neuen Ordner zu erstellen
cd ein_name_deiner_wahl
um in den neuen Ordner hinein zu "gehen"
python -m venv .venv
python spezifisch um eine virtuelle Umgebung zu bekommen
source .venv/bin/activate
um diese Umgebung zu aktivieren (deaktivieren geht mit 'deactivate')
pip install pymodbus
um die library (dependency) in der aktivierten Umgebung zu installieren
touch main.py
um eine neue Datei mit dem name "main.py" zu erstellen.
Nun in die main.py (oder anderer Name, spielt keine Rolle) den nachfolgenden code kopieren.
import textwrap import pymodbus.client as ModbusClient from pymodbus import ( ExceptionResponse, Framer, ModbusException, ) from pymodbus.payload import BinaryPayloadDecoder from pymodbus.constants import Endian GRID_METER = 30 PV_INVERTER = 32 VICTRON_ENERGY_HUB = 100 VICTRON_ENERGY_SYSTEM = 100 VICTRON_MULTIPLUS = 242 # 261 see `Unit ID mapping in xlsx file` datapoints = { (PV_INVERTER, "com.victronenergy.pvinverter"): { "L1 Energy": [1030, "uint16", 100, "kWh"], "L2 Energy": [1034, "uint16", 100, "kWh"], "L3 Energy": [1038, "uint16", 100, "kWh"], "L1 Voltage": [1027, "uint16", 10, "V AC"], "L2 Voltage": [1031, "uint16", 10, "V AC"], "L3 Voltage": [1035, "uint16", 10, "V AC"], }, (GRID_METER, "com.victronenergy.grid"): { "L1 – Voltage": [2616, "uint16", 10, "V AC"], "L1 – Current": [2617, "int16", 10, "A AC"], "L2 – Voltage": [2618, "uint16", 10, "V AC"], "L2 – Current": [2619, "int16", 10, "A AC"], "L3 – Voltage": [2620, "uint16", 10, "V AC"], "L3 – Current": [2621, "int16", 10, "A AC"], }, (VICTRON_ENERGY_HUB, "com.victronenergy.hub4"): { "Grid limiting status": [2709, "int16", 1, "Active"], }, (VICTRON_ENERGY_SYSTEM, "com.victronenergy.system"): { "AC Consumption L1": [817, "uint16", 1, "W"], "AC Consumption L2": [818, "uint16", 1, "W"], "AC Consumption L3": [819, "uint16", 1, "W"], "Grid L1": [820, "int16", 1, "W"], "Grid L2": [821, "int16", 1, "W"], "Grid L3": [822, "int16", 1, "W"], }, (VICTRON_MULTIPLUS, "com.victronenergy.vebus"): { "Input voltage phase 1": [3, "uint16", 10, "V AC"], "Input voltage phase 2": [4, "uint16", 10, "V AC"], "Input voltage phase 3": [5, "uint16", 10, "V AC"], "Input current phase 1": [6, "int16", 10, "A AC"], "Input current phase 2": [7, "int16", 10, "A AC"], "Input current phase 3": [8, "int16", 10, "A AC"], }, } single_register_markers = ["int16", "uint16"] double_register_markers = ["int32", "uint32"] def query_victron_modbus_data(host, port, framer=Framer.SOCKET): """Run sync client.""" # uncomment to activate debugging # from pymodbus import pymodbus_apply_logging_config # pymodbus_apply_logging_config("DEBUG") client = ModbusClient.ModbusTcpClient( host, port=port, framer=framer, ) print("connect to server") client.connect() print("get and verify data") try: for device, points in datapoints.items(): for point, value in points.items(): # print(f"Reading \t {point} from {device[1]}") # check if we are reading a 16 or 32 bit value if points[point][1] in single_register_markers: rr = client.read_holding_registers(value[0], 1, device[0]) elif points[point][1] in double_register_markers: rr = client.read_holding_registers(value[0], 2, device[0]) else: print(f"Invalid data type {points[point][1]}") client.close() return decoder = BinaryPayloadDecoder.fromRegisters( rr.registers, byteorder=Endian.BIG ) if points[point][1] == "uint16": decoded = decoder.decode_16bit_uint() / points[point][2] elif points[point][1] == "int16": decoded = decoder.decode_16bit_int() / points[point][2] elif points[point][1] == "uint32": decoded = decoder.decode_32bit_uint() / points[point][2] elif points[point][1] == "int32": decoded = decoder.decode_32bit_int() / points[point][2] print( f"{device[1]+':' :<30} {point+':' :<50} {decoded} {textwrap.shorten(points[point][3], width=15)}" ) except ModbusException as exc: print(f"Received ModbusException({exc}) from library") client.close() return if rr.isError(): print(f"Received Modbus library error({rr})") client.close() return if isinstance(rr, ExceptionResponse): print(f"Received Modbus library exception ({rr})") # THIS IS NOT A PYTHON EXCEPTION, but a valid modbus message client.close() print("close connection") client.close() if __name__ == "__main__": query_victron_modbus_data("192.168.1.5", "502")
Man muss dann noch die IP (hier "192.168.1.5") in die richtige für seine Anlage ändern, entsprechend die device IDs (ganz oben im code) anpassen und anhand der XLSX Datei von Victron die benötigten Daten copy und pasten.
wenn alles klappt bekommt man die Daten ausgegeben wenn man einfach
python main.py
entsprechend ausführt.
Ist nichts besonderes aber ich hoffe es hilft jemanden.
Stand heute verwende ich "pymodbus" in der Version 3.6.6 und Python Version 3.12.1
Die Ausgabe sieht dann so aus (Unschöne Zeilenumbrüche kann man vermeiden wenn das Fenster groß genug ist, dann ist es eine Art Tabelle):
$ python main.py connect to server get and verify data com.victronenergy.pvinverter: L1 Energy: 298.78 kWh com.victronenergy.pvinverter: L2 Energy: 587.68 kWh com.victronenergy.pvinverter: L3 Energy: 116.56 kWh com.victronenergy.pvinverter: L1 Voltage: 226.1 V AC com.victronenergy.pvinverter: L2 Voltage: 223.8 V AC com.victronenergy.pvinverter: L3 Voltage: 224.7 V AC com.victronenergy.pvinverter: L1 Current: 1.4 A AC com.victronenergy.pvinverter: L2 Current: 1.4 A AC com.victronenergy.pvinverter: L3 Current: 1.6 A AC com.victronenergy.pvinverter: L1 Power: 325.0 W com.victronenergy.pvinverter: L2 Power: 319.0 W com.victronenergy.pvinverter: L3 Power: 360.0 W com.victronenergy.grid: L1 – Voltage: 223.5 V AC com.victronenergy.grid: L1 – Current: -2.4 A AC com.victronenergy.grid: L2 – Voltage: 225.6 V AC com.victronenergy.grid: L2 – Current: -1.2 A AC com.victronenergy.grid: L3 – Voltage: 224.6 V AC com.victronenergy.grid: L3 – Current: -1.4 A AC