Forum

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

DEYE SUN 12K-SG04LP...
 
Benachrichtigungen
Alles löschen

DEYE SUN 12K-SG04LP03-EU / Modbus RTU per Python script

7 Beiträge
3 Benutzer
3 Reactions
302 Ansichten
(@the_kuki)
Neues Mitglied Neues Mitglied
Mitglied seit: Vor 6 Monaten
Beiträge: 2
Themenstarter  

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 😉



   
amiko reacted
Zitat
 Bubu
(@bubu)
Deye Kenner Neues Mitglied
Mitglied seit: Vor 2 Jahren
Beiträge: 80
 

Moin, hier die Werte, die du alleine über den WLAN-Stick ohne Modbus auslesen kannst.

 Siehe https://github.com/StephanJoubert/home_assistant_solarman/blob/c0b60a35278641189dcb2a4f92925e0103723ff7/README.md

Nachteil ist, du kannst ohne Modbus natürlich nicht schreiben (Einstellungen ändern).


Diese r Beitrag wurde geändert Vor 3 Monaten von Bubu

   
AntwortZitat
(@amiko)
PV Master Neues Mitglied
Mitglied seit: Vor 2 Jahren
Beiträge: 650
 

Veröffentlicht von: @bubu

die du alleine über den WLAN-Stick ohne Modbus auslesen kannst.

Sicher, dass es ohne Modbus geht? 

Veröffentlicht von: @bubu

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


   
AntwortZitat
 Bubu
(@bubu)
Deye Kenner Neues Mitglied
Mitglied seit: Vor 2 Jahren
Beiträge: 80
 

@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?



   
AntwortZitat
(@amiko)
PV Master Neues Mitglied
Mitglied seit: Vor 2 Jahren
Beiträge: 650
 

Veröffentlicht von: @bubu

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.


Diese r Beitrag wurde geändert Vor 3 Monaten von amiko

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


   
Bubu reacted
AntwortZitat
 Bubu
(@bubu)
Deye Kenner Neues Mitglied
Mitglied seit: Vor 2 Jahren
Beiträge: 80
 

@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.



   
AntwortZitat
(@amiko)
PV Master Neues Mitglied
Mitglied seit: Vor 2 Jahren
Beiträge: 650
 

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.


Diese r Beitrag wurde geändert Vor 2 Monaten von amiko

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


   
Bubu reacted
AntwortZitat