62 lines
1.8 KiB
Python
62 lines
1.8 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from pymodbus.client import ModbusTcpClient
|
|
import struct, sys
|
|
|
|
MODBUS_IP = "192.168.1.112"
|
|
MODBUS_PORT = 502
|
|
UNIT_ID = 1
|
|
|
|
METER_START = 40240 # Startadresse Model 203-Felder
|
|
|
|
def to_i16(u16): # unsigned 16 → signed 16
|
|
return struct.unpack(">h", struct.pack(">H", u16))[0]
|
|
|
|
def read_regs(client, addr, count):
|
|
rr = client.read_holding_registers(address=addr, count=count, slave=UNIT_ID)
|
|
if rr.isError():
|
|
return None
|
|
return rr.registers
|
|
|
|
def read_meter_power(client):
|
|
base = METER_START
|
|
p = read_regs(client, base + 16, 1) # M_AC_Power
|
|
pa = read_regs(client, base + 17, 1) # Phase A
|
|
pb = read_regs(client, base + 18, 1) # Phase B
|
|
pc = read_regs(client, base + 19, 1) # Phase C
|
|
sf = read_regs(client, base + 20, 1) # Scale Factor
|
|
if not p or not sf:
|
|
return None
|
|
sff = to_i16(sf[0])
|
|
return {
|
|
"total": to_i16(p[0]) * (10 ** sff),
|
|
"A": to_i16(pa[0]) * (10 ** sff) if pa else None,
|
|
"B": to_i16(pb[0]) * (10 ** sff) if pb else None,
|
|
"C": to_i16(pc[0]) * (10 ** sff) if pc else None,
|
|
"sf": sff
|
|
}
|
|
|
|
def fmt_w(v):
|
|
if v is None: return "-"
|
|
neg = v < 0
|
|
v = abs(v)
|
|
return f"{'-' if neg else ''}{v/1000:.2f} kW" if v >= 1000 else f"{'-' if neg else ''}{v:.0f} W"
|
|
|
|
def main():
|
|
client = ModbusTcpClient(MODBUS_IP, port=MODBUS_PORT)
|
|
if not client.connect():
|
|
print("❌ Verbindung fehlgeschlagen."); sys.exit(1)
|
|
try:
|
|
m = read_meter_power(client)
|
|
if m:
|
|
print(f"Meter-Leistung: {fmt_w(m['total'])} "
|
|
f"(A {fmt_w(m['A'])}, B {fmt_w(m['B'])}, C {fmt_w(m['C'])}) [SF={m['sf']}]")
|
|
else:
|
|
print("Meter-Leistung konnte nicht gelesen werden.")
|
|
finally:
|
|
client.close()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|