Wenn du Hilfe benötigst, 🔍 suche bitte, bevor du einen neues Thema oder Beitrag erstellst.
Deye Updaten lassen Umfrage Deye-Wiki
Deye Hybrid Angebote Deye Zubehör Produkte
Hallo zusammen!
Ich bastle aktuell an meiner Heim-Automation und wollte meinen Deye per USB-to-RS485 über die RS485 Schnittstelle am BMS-Port einbinden.
Bevor ich das in irgendeiner Software mache und irgendwas nicht funktioniert, habe ich einen ersten Anlauf gemacht, das mit Python unter Linux einmal zu testen. Mit ChatGPT-Unterstützung ging das ganz flott...
Es braucht in meinem Setup 3 Dateien:
deye_registers.py
DEYE_REGISTERS = {
# --- GRID ---
"grid_power": {"addr": 625, "length": 1, "type": "holding", "decode": "int16", "scale": 1, "desc": "Grid side total power"},
"grid_energy": {"addr": 522, "length": 2, "type": "holding", "decode": "uint32s", "scale": 0.1, "desc": "Total Grid Buy Power (Wh)"},
"grid_current_A": {"addr": 613, "length": 1, "type": "holding", "decode": "int16", "scale": 0.01, "desc": "Out-of-grid current A"},
"grid_current_B": {"addr": 614, "length": 1, "type": "holding", "decode": "int16", "scale": 0.01, "desc": "Out-of-grid current B"},
"grid_current_C": {"addr": 615, "length": 1, "type": "holding", "decode": "int16", "scale": 0.01, "desc": "Out-of-grid current C"},
# --- PV ---
"pv1_power": {"addr": 672, "length": 1, "type": "holding", "decode": "uint16", "scale": 1, "desc": "PV1 input power"},
"pv2_power": {"addr": 673, "length": 1, "type": "holding", "decode": "uint16", "scale": 1, "desc": "PV2 input power"},
"pv_total_energy": {"addr": 534, "length": 2, "type": "holding", "decode": "uint32s", "scale": 0.1, "desc": "Total PV Power (Wh)"},
# --- BATTERY ---
"battery_power": {"addr": 590, "length": 1, "type": "holding", "decode": "int16", "scale": 1, "desc": "Battery output power"},
"battery_discharge": {"addr": 518, "length": 2, "type": "holding", "decode": "uint32s", "scale": 0.1, "desc": "Total discharge of the battery (Wh)"},
"battery_soc": {"addr": 588, "length": 1, "type": "holding", "decode": "uint16", "scale": 1, "desc": "Battery capacity (SOC)"},
}
modbus_client.py
from pymodbus.client import ModbusSerialClient
from enum import Enum
class DATATYPE(Enum):
INT16 = ("h", 1)
UINT16 = ("H", 1)
INT32 = ("i", 2)
UINT32 = ("I", 2)
INT64 = ("q", 4)
UINT64 = ("Q", 4)
FLOAT32 = ("f", 2)
FLOAT64 = ("d", 4)
STRING = ("s", 0)
BITS = ("bits", 0)
DECODE_MAP = {
"int16": DATATYPE.INT16,
"uint16": DATATYPE.UINT16,
"int32": DATATYPE.INT32,
"uint32": DATATYPE.UINT32,
"int64": DATATYPE.INT64,
"uint64": DATATYPE.UINT64,
"float32": DATATYPE.FLOAT32,
"float64": DATATYPE.FLOAT64,
"string": DATATYPE.STRING,
"bits": DATATYPE.BITS,
"uint32s": DATATYPE.UINT32,
"int32s": DATATYPE.INT32,
}
class DeyeModbusClient:
def __init__(self, port="/dev/ttyACM0", baudrate=9600, unit=1):
self.client = ModbusSerialClient(
port=port,
baudrate=baudrate,
timeout=1,
stopbits=1,
bytesize=8,
parity="N"
)
self.unit = unit
def connect(self):
return self.client.connect()
def close(self):
self.client.close()
def read_register(self, address, length, data_type):
result = self.client.read_holding_registers(address=address, count=length, slave=self.unit)
if not result or result.isError():
return None
data_type = DECODE_MAP.get(data_type.lower())
return self.client.convert_from_registers(
registers=result.registers,
data_type=data_type,
word_order='big'
)
deye_cli.py
#!/usr/bin/env python3
import argparse
from deye_registers import DEYE_REGISTERS
from modbus_client import DeyeModbusClient
def main():
parser = argparse.ArgumentParser(description="Deye Wechselrichter CLI")
parser.add_argument("register", help="Name des Registers oder 'all'")
parser.add_argument("--port", default="/dev/ttyACM0", help="Modbus-RTU Port")
parser.add_argument("--baudrate", type=int, default=9600, help="Baudrate")
parser.add_argument("--unit", type=int, default=1, help="Modbus Unit ID")
args = parser.parse_args()
client = DeyeModbusClient(port=args.port, baudrate=args.baudrate, unit=args.unit)
if not client.connect():
print("❌ Verbindung fehlgeschlagen")
return
try:
if args.register == "all":
for name, reg in DEYE_REGISTERS.items():
value = client.read_register(reg["addr"], reg["length"], reg["decode"])
print(f"{name:20} = {value} ({reg['desc']})")
else:
reg = DEYE_REGISTERS.get(args.register)
if not reg:
print(f"❌ Unbekanntes Register: {args.register}")
return
value = client.read_register(reg["addr"], reg["length"], reg["decode"])
print(f"{args.register} = {value} ({reg['desc']})")
finally:
client.close()
if __name__ == "__main__":
main()
Meine RS485 Schnittstelle ist /dev/ttyACM0.
Ausgabe:
sudo python3 deye_cli.py all grid_power = -2984 (Grid side total power) grid_energy = 145031168 (Total Grid Buy Power (Wh)) grid_current_A = 433 (Out-of-grid current A) grid_current_B = 447 (Out-of-grid current B) grid_current_C = 482 (Out-of-grid current C) pv1_power = 432 (PV1 input power) pv2_power = 6041 (PV2 input power) pv3_power = 0 (PV3 input power) pv4_power = 0 (PV4 input power) pv_total_energy = 1622671361 (Total PV Power (Wh)) battery_power = -3 (Battery output power) battery_discharge = 882900992 (Total discharge of the battery (Wh)) battery_soc = 100 (Battery capacity (SOC)) soc_target = 720907 (SOC target (Min/Max abhängig vom Modus)) soc_time_start = 500 (SOC time of use 1 (Start)) soc_time_end = 32768900 (SOC time of use 1 (End)) charge_mode = 0 (Lade-/Entlademodus-Schalter)
-> Kommunikation läuft.
Sind die Register vollständig? -> Sicherlich nicht...
Sind alle Werte korrekt skaliert? -> Habe ich nicht geprüft?
Kann man den Code schöner machen? -> Ganz bestimmt!
Provided as is 😉
Moin, hier die Werte, die du alleine über den WLAN-Stick ohne Modbus auslesen kannst.
Nachteil ist, du kannst ohne Modbus natürlich nicht schreiben (Einstellungen ändern).
die du alleine über den WLAN-Stick ohne Modbus auslesen kannst.
Sicher, dass es ohne Modbus geht?
Nachteil ist, du kannst ohne Modbus natürlich nicht schreiben (Einstellungen ändern).
Dann schau dir bei GitHub die Solarman-Stick-Logger-Integration von David Rapan an. Über WLAN kannst du dort die Register ganz „ohne Modbus” 😀 schreiben.
Deye SUN-12K-SG04LP3-EU, 36 х Trina Vertex S 425W, 2 x Deye RW-M 6.1
Deye SUN-8K-SG04LP3-EU, 10 х Trina Vertex S+ 430W, 2 x Deye RW-M 6.1
2 x Deye SUN 2000, je 4 х Trina Vertex S+ 430W, Netzparallel zu 8kW WR
1 x Deye SUN 600, 2 х Sharp NU-JC 410W, Netzparallel zu 8kW WR
@amiko Oh, das muss neu sein. Gab es vor einem Jahr noch nicht, als ich HA eingerichtet habe. Hast du das mal ausprobiert? In der Beschreibung steht noch in der Entwicklung aber stable?
Oh, das muss neu sein. Gab es vor einem Jahr noch nicht, als ich HA eingerichtet habe.
Das läuft bei mir schon lange, eventuell seit über einem Jahr. Das kann ich jetzt nicht sagen. Ich hatte zuerst die Integration von Stephan installiert und dann gewechselt. Die von David gefällt mir besser.
PS. Ich habe nachgeschaut. Im Mai 2024 hatte ich die Integration von David schon am Laufen.
Deye SUN-12K-SG04LP3-EU, 36 х Trina Vertex S 425W, 2 x Deye RW-M 6.1
Deye SUN-8K-SG04LP3-EU, 10 х Trina Vertex S+ 430W, 2 x Deye RW-M 6.1
2 x Deye SUN 2000, je 4 х Trina Vertex S+ 430W, Netzparallel zu 8kW WR
1 x Deye SUN 600, 2 х Sharp NU-JC 410W, Netzparallel zu 8kW WR
@amiko Schaue ich mir mal an, danke. Finde es erstaunlich, dass man darüber auch schreiben kann. Dachte die Solarman Integrationen rufen nur die Json Daten vom Wlan-Stick im lokalen Netzwerk ab und verarbeiten sie dann.
Du kannst die Modbus-Befehle sogar über die Deye-Cloud oder Solarman an dein WR über den WLAN-Stick übertragen. Der WLAN-Stick ist über die RS232-Schnittstelle mit dem WR verbunden. Über die RS232-Schnittstelle kannst du sogar mehr Register auslesen als über die RS485-Schnittstelle. Zum Beispiel können die Register ab Adresse 10000, in denen die Werte der einzelnen Batteriepacks stehen, nur über die RS232-Schnittstelle ausgelesen werden.
Deye SUN-12K-SG04LP3-EU, 36 х Trina Vertex S 425W, 2 x Deye RW-M 6.1
Deye SUN-8K-SG04LP3-EU, 10 х Trina Vertex S+ 430W, 2 x Deye RW-M 6.1
2 x Deye SUN 2000, je 4 х Trina Vertex S+ 430W, Netzparallel zu 8kW WR
1 x Deye SUN 600, 2 х Sharp NU-JC 410W, Netzparallel zu 8kW WR

