Marstek Venus mit via modbus an openHAB anbinden

Der Marstek Venus lässt sich ja sehr gut mit dem Shelly betreiben, wie ich in einem vorherigen Beitrag schon beschrieben habe. Was allerdings bislang nur über die App einsehbar ist, ist z.B. der Ladestand der Batterie. Gerade diesen Wert möchte ich in openHAB sehen, um auf die App verzichten zu können und die Werte auch in Automatisierungen verwenden zu können.

Was braucht es?

INSERTADS

Einrichten des Waveshare Modbus TCP – Adapters

Der Waveshare wird einfach ans Netz angeschlossen, mit Strom versorgt und ab da holt er sich eine IP-Adresse er DHCP.

Für die RS485-Schnittstelle braucht es beim Waveshare für den Venus grundsätzlich folgende Einstellungen:

  • Baud-Rate: 115.200
  • Data-Bits: 8
  • Parität: Keine
  • Stopp-Bit: 1
  • Flusskontrolle: Keine

Zur Konfiguration gibt es eine eigene Software, die aber nicht zwingend benötigt wird. Die hilft aber bei Bedarf durchaus beim Auffinden des Waveshares im Netzwerk. Der Waveshare selbst bringt einen Webserver mit einer kleinen GUI mit, auf der man auch alles nötige einstellen kann. Dieser läuft auf Port 80, dem regulären Webserver-Port, und erscheint nach Eingabe der IP im Browser.

Folgende Einstellungen sind für den Venus nötig – IP natürlich abhängig von den IPs deines Netzwerks (eine statische IP zu vergeben ist allein schon wegen der späteren openHAB-Einbindung sinnvoll):

Web-GUI zur Konfiguration des Waveshare-Adapters

Alternativ könnt ihr auch die Waveshare-Konfigurationssoftware VirCom nutzen

Ein Download-Link befindet sich im Waveshare-Wiki z.B. unter https://www.waveshare.com/wiki/RS485_TO_ETH_(B). Dateien einfach entpacken und VirCom starten. Nach Klick auf „Device“ zeigt er euch den Waveshare an und ihr könnt die Einstellungen auch in der GUI vornehmen:

VirCom-Konfiguration, Anzeige gefundener Waveshare-Adapter
VirCom-Konfiguration, Anpassung eines gefundenen Waveshare-Adapters

INSERTADS

Verkabelung und Anschließen Waveshare-Adapter an Marstek Venus

Für das (mitgelieferte) RS485-Adapterkabel des Speicher gibt es herstellerseitig keine große Doku. Von daher habe ich mich auf diesen Forenbeitrag bei tweakers.net gestützt, welcher aufzeigt, welcher der PINS welche Funktion hat.

Kurz zusammengefasst: Wenn man auf den Stecker des Marstek schaut, der an den Marstek angeschlossen wird, und die weiße Markierung oben rechts ist, dann ist die Belegung der PINs ab der weißen Markierung im Uhrzeigersinn: GND, +5V, Data GND, B, A.

Um nicht die das originale RS485-Kabel von Marstek aufschneiden bzw. generell modifizieren zu müssen, habe ich mir einen Adapter gekauft, der (2.54 XH 6 Pin, female). Man kann diese Kabel auch viel günstiger direkt aus China ordern, aber wegen 5-6 € Ersparnis wollte ich keine Wochen Lieferzeit abwarten.

Ich habe sicherheitshalber bei mir die Kabelenden im Adapter gegenüber der PINs des Kabels nochmal durchgemessen und komme auf nachfolgende Verteilung. Ich vermute, die Verteilung ist bei jedem Kabel gleich – würde es aber empfehlen, das lieber nochmal durchzumessen.

Stecker des Marstek, nach Durchmessen beschriftet, von links nach rechts: GND, +5V, DATA GND, B, A.

Am Waveshare selbst wird dann wie folgt angeschlossen:

Marstek-KabelWaveshare-Adapter / Screwterminal
ATA
BTB
Data GNDPW
+5V, GNDKein Anschluss (Waveshare benötigt >5V Betriebsspannung, daher externes Netzteil oder POE nötig)

Registerbelegung Marstek Venus Speicher

An dieser Stelle verweise ich auf die Register, die der Hersteller auch als PDF veröffentlicht hat. Ich werde mir hier später die nötigen Register, die ich tatsächlich nutzen will, heraussuchen:

INSERTADS

Einrichtung in openHAB

Um in openHAB Register auslesen bzw. schreiben zu können, ist zuerst die Installation des „Modbus Binding“ via Add-on-Store nötig.

Als erstes muss dann der Waveshare selbst als Gerät (Thing) eingebunden werden.
Dazu Thing hinzufügen, Modbus Binding und Modbus TCP Slave auswählen.

Nachfolgend die Einstellungen des Things (Modbus TCP Slave) als Code.

UID: modbus:tcp:venus-waveshare
label: Marstek Venus Waveshare Modbus Gateway
thingTypeUID: modbus:tcp
configuration:
  connectMaxTries: 2
  reconnectAfterMillis: 1000
  timeBetweenTransactionsMillis: 1000
  receiveTimoutMillis: 1000
  rtuEncoded: false
  port: 502
  timeBetweenReconnectMillis: 1000
  connectTimeoutMillis: 10000
  host: 192.168.1.14
  afterConnectionDelayMillis: 1000
  timeoutMillis: 8000
  id: 1
  enableDiscovery: false

Anschließend ist es nötig, auch die Abfragen auf die Register zu ermöglichen. Hierzu wird ein weiteres Thing (Regular Poll) eingebunden, um einen Poller zu registrieren.

Nachfolgender Code liest alle 5 Sekunden beispielhaft die Register 32100-32104 (battery voltage, battery current, battery power, battery SOC) aus.

UID: modbus:poller:venus-waveshare:venus-holding-registers
label: Marstek Venus Modbus Holding Register
thingTypeUID: modbus:poller
configuration:
  start: 32100
  length: 5
  refresh: 5000
  maxTries: 3
  cacheMillis: 50
  type: holding
bridgeUID: modbus:tcp:venus-waveshare

Um dann auch die konkreten Werte nutzen zu können braucht es je Wert ein weiteres Thing (Modbus Data), z.B. hier für den SOC-Wert (Ladezustand) des Akkus. Der Datentyp muss dem des PDF entsprechen. Die vielen Channels verwirren ggf. zwar zuerst (für mich war das die erste modbus-Nutzung überhaupt), sind aber nur Darstellung des jeweils gleichen, im Register vorhandenen Wertes in den bei openHAB insgesamt vorhandenen Datentypen. Braucht man den Wert (wie beim SOC) als Wert zwischen 0 und 100, ist z.B. der Dimmer-Type der richtige.

UID: modbus:data:venus-holding-registers:soc
label: Venus Batterie SOC
thingTypeUID: modbus:data
configuration:
  readValueType: uint16
  readTransform: default
  writeTransform: NONE
  offset: 0
  readStart: "32104"
  valueType: uint16
  dataType: 2bytes_int
  updateUnchangedValuesEveryMillis: 1000
  start: 1
  writeMultipleEvenWithSingleRegisterOrCoil: false
  writeMaxTries: 3
bridgeUID: modbus:poller:venus-waveshare:venus-holding-registers
channels:
  - id: number
    channelTypeUID: modbus:number-type
    label: Value as Number
    description: Number item channel
    configuration: {}
  - id: switch
    channelTypeUID: modbus:switch-type
    label: Value as Switch
    description: Switch item channel
    configuration: {}
  - id: contact
    channelTypeUID: modbus:contact-type
    label: Value as Contact
    description: Contact item channel
    configuration: {}
  - id: dimmer
    channelTypeUID: modbus:dimmer-type
    label: Value as Dimmer
    description: Dimmer item channel
    configuration: {}
  - id: datetime
    channelTypeUID: modbus:datetime-type
    label: Value as DateTime
    description: DateTime item channel
    configuration: {}
  - id: string
    channelTypeUID: modbus:string-type
    label: Value as String
    description: String item channel
    configuration: {}
  - id: rollershutter
    channelTypeUID: modbus:rollershutter-type
    label: Value as Rollershutter
    description: Rollershutter item channel
    configuration: {}
  - id: lastReadSuccess
    channelTypeUID: modbus:last-successful-read-type
    label: Last Successful Read
    description: Date of last read
    configuration: {}
  - id: lastReadError
    channelTypeUID: modbus:last-erroring-read-type
    label: Last Erroring Read
    description: Date of last read error
    configuration: {}
  - id: lastWriteSuccess
    channelTypeUID: modbus:last-successful-write-type
    label: Last Successful Write
    description: Date of last write
    configuration: {}
  - id: lastWriteError
    channelTypeUID: modbus:last-erroring-write-type
    label: Last Erroring Write
    description: Date of last write error
    configuration: {}

Zu guter Letzt muss nun der jeweils benötigte Channel mit einem Item (mit passendem Datentyp) verknüpft werden. Schon steht dann als Item z.B. der State of Charge zur Verfügung:

Beispielhaft SOC (State of Charge) des Akkus im 12h-Verlauf)

Nächstes Ziel ist nun die Anbindung aller nötigen Register in openHAB sowie auch ein Umsetzen einer Steuerung des Speichers in openHAB.

Dazu aber später ggf. separat mehr.

20 Antworten auf „Marstek Venus mit via modbus an openHAB anbinden“

  1. Super Anleitung, bekomme die Werte in openhab, jedoch immer mal wieder mit ReadTimeOuts im Log. Eine Idee, woran das liegen könnte?

    1. Tatsächlich geht es mir ähnlich. Festgestellt habe ich, dass wenn zu viele Register auf einmal angefragt werden sollen, das Zusammenspiel nicht mehr passt. Daher habe ich immer nur Gruppen für die Werte gebildet, die ich wirklich brauche. Trotz manchmal aufkommender Timeouts im Log – da geht es mir ähnlich wie Dir – werden aber die Werte dennoch verlässlich schnell aktualisiert.

      1. Danke dir für die Info! Bin ich wenigstens nicht allein.. 😊 Ich werde mal probieren, ob ich an den abfragen der Things noch etwas optimieren kann..

  2. Hi nochmal.. Habe das Modbus Binding nun wie folgt angepasst:

    UID: modbus:tcp:venus-waveshare
    label: Marstek Venus Waveshare Modbus Gateway
    thingTypeUID: modbus:tcp
    configuration:
    connectMaxTries: 2
    reconnectAfterMillis: 1000
    timeBetweenTransactionsMillis: 1000
    receiveTimoutMillis: 1000
    rtuEncoded: false
    port: 502
    timeBetweenReconnectMillis: 1000
    connectTimeoutMillis: 10000
    host: 192.168.178.30
    afterConnectionDelayMillis: 1000
    timeoutMillis: 8000
    id: 1
    enableDiscovery: false

    Habe nun seit mehreren Stunden keine Einträge mehr im Log und scheint bislang ohne Auffälligkeiten zu funktionieren. Vielleicht kannst du das ja verifizieren.. 🙂

    Gruß Rene

  3. Hi, hast du es schon geschafft die anderen Werte über Modbus auszulesen und könntest deine openHAB Config dafür teilen? Besonders würden mich die 35000er Temperaturwerte (zur Ansteuerung eines externen Lüfters) und 33000er Energiewerte interessieren, da scheitere ich aber mit meinen trivialen Modbus Kenntnissen.

    Besten Dank 🙂

    1. Hallo,
      ja, auf die gleiche Art und Weise.
      schau immer auch ins Logfile, habe festgestellt wenn zu viele Register auf einmal ausgelesen werden macht er irgendwann nicht mehr das, was er machen sollte, daher lieber „kleine häppchen“ jeweils als Thing für den poller.

      35-er Werte, thing:

      UID: modbus:poller:venus-waveshare:venus-holding-registers-35000-35011
      label: Marstek Venus Modbus Holding Register 35000-35003
      thingTypeUID: modbus:poller
      configuration:
      start: 35000
      length: 3
      refresh: 500
      maxTries: 3
      cacheMillis: 50
      type: holding
      bridgeUID: modbus:tcp:venus-waveshare

      Thing der Temperatur:

      UID: modbus:data:venus-holding-registers-35000-35011:venus_temperature_internal
      label: Venus Temperatur intern
      thingTypeUID: modbus:data
      configuration:
      readValueType: int16
      readTransform: default
      writeTransform: default
      readStart: „35000“
      updateUnchangedValuesEveryMillis: 1000
      writeMultipleEvenWithSingleRegisterOrCoil: false
      writeMaxTries: 3
      bridgeUID: modbus:poller:venus-waveshare:venus-holding-registers-35000-35011
      channels:
      – id: number
      channelTypeUID: modbus:number-type
      label: Value as Number
      description: Number item channel
      configuration: {}
      – id: switch
      channelTypeUID: modbus:switch-type
      label: Value as Switch
      description: Switch item channel
      configuration: {}
      – id: contact
      channelTypeUID: modbus:contact-type
      label: Value as Contact
      description: Contact item channel
      configuration: {}
      – id: dimmer
      channelTypeUID: modbus:dimmer-type
      label: Value as Dimmer
      description: Dimmer item channel
      configuration: {}
      – id: datetime
      channelTypeUID: modbus:datetime-type
      label: Value as DateTime
      description: DateTime item channel
      configuration: {}
      – id: string
      channelTypeUID: modbus:string-type
      label: Value as String
      description: String item channel
      configuration: {}
      – id: rollershutter
      channelTypeUID: modbus:rollershutter-type
      label: Value as Rollershutter
      description: Rollershutter item channel
      configuration: {}
      – id: lastReadSuccess
      channelTypeUID: modbus:last-successful-read-type
      label: Last Successful Read
      description: Date of last read
      configuration: {}
      – id: lastReadError
      channelTypeUID: modbus:last-erroring-read-type
      label: Last Erroring Read
      description: Date of last read error
      configuration: {}
      – id: lastWriteSuccess
      channelTypeUID: modbus:last-successful-write-type
      label: Last Successful Write
      description: Date of last write
      configuration: {}
      – id: lastWriteError
      channelTypeUID: modbus:last-erroring-write-type
      label: Last Erroring Write
      description: Date of last write error
      configuration: {}

      Item der Temperatur dann auf Channel „Value as Number“ verlinkt:

      label: Venus Temperatur intern
      type: Number
      category: temperature_hot
      groupNames:
      – gruppePVSpeicherShellyVenus
      – pvspeicher
      tags:
      – Point
      – Temperature

  4. Hallo Florian,

    zunächst mal vielen Dank für deine ausführliche Beschreibung. Ich habe mir deine Arbeit zur Vorlage genommen um meinen Venus E ebenfalls mit Modbus auszulesen. Allerdings habe ich ein paar Abweichungen von deiner Vorlage festgestellt, auf die ich kurz eingehen möchte:

    Seit Mitte August sind wir stolze Besitzer eines Marstek Venus E, Version 2 (der Nachfolger ist eine Woche später angekündigt worden). Nachdem die Verbindung zum Shelly Pro 3EM eingerichtet war, läuft der Speicher, wie erwartet. Mich hat aber auch bald gestört, dass ich zwar den Verlauf des Energieverbrauchs über das Shelly gut analysieren und aufzeichnen kann (mqtt), über den Speicher selbst aber nur Statusinformationen über die App bekomme.

    Dann habe ich deinen Artikel gefunden und mir beim Chinesen einen Waveshare RS485- LAN/Wifi Converter bestellt (https://spotpear.com/index/product/detail/id/1024.html), allerdings einen etwas anderen, als den, den du beschreibst. Der hat einen DC- Input von 5-36 V, dh. Ich kann ihn direkt am Modbus- Connector des Marstek betreiben und er hat WLan, ich brauche kein Kabel zum Open Hab Rechner (außerdem kann er mqtt, was mir wichtig war). Beim Einrichten habe ich mich dann zunächst weitestgehend an deine Beschreibung gehalten, musste aber ein paar Abweichungen feststellen.

    1. Die Belegung des RS485 Ports ist bei mir ein wenig anders, als du es beschreibst: Signal-GND und Power-GND sind genau vertauscht. Da sie, entgegen meiner Erwartung, untereinander nicht verbunden sind, ist das wichtig.

    2. Entgegen der Beschreibung in der PDF- Datei zur Registerbelegung ist im Register 32104 der Ladezustand der Batterie in % und nicht in 0,1% abgelegt.

    3. Entsprechend nehme ich in OH einfach den Channel „Value as Number“ zum Auslesen des Ladezustands.

    Ich lese gleichzeitig noch den Register 32102 aus, in welchem die Leistung eingetragen ist, mit der der Speicher gerade ge- bzw. entladen wird. Beide stelle ich in einer Page graphisch dar.
    Mich würde bei dieser Gelegenheit interessieren, ob die im Register 32105 eingetragene Kapazität der Batterie wirklich angepasst wird (entsprechend abnimmt mit zunehmendem Alter), oder ist es einfach eine Konstante. Bei mir erscheint da natürlich 5120 Wh. Die Kiste ist aber auch noch neu.

    Soviel erstmal dazu. Ich werde mal versuchen, eine eigene Regelung zu bauen und schauen, ob die besser funktioniert, als die eingebaute.

    Gruß, Uwe

  5. Hi,
    Inzwischen kann man beim Support das Freischalten der lokalen API für die Marstek bitten.
    Nach 3 Tagen konnte ich die API in der Marstek App einschalten.
    Inzwischen habe ich die Integration rudimentär ins OpenHAB geschafft und teste das die nächsten Tage. Das geht mit dem 3rd Party Binding für TCP/UDP, weil die Ansteuerung per UDP gemacht wird.
    Es sieht aber schon vielversprechend aus. Integration ins EVCC werde ich auch in Kürze ausprobieren.
    Damit sollten die Klimmzüge per Modbus oder anderer Dienste erledigt sein …
    Ich kann hier auch eine kleine Anleitung einstellen, wenn es stabil läuft …

    1. Hallo, Danke für deinen Beitrag! Ich habe das auch schon gelesen und auch bereits bei Marstek angefragt. Die Freischaltung steht allerdings noch aus. Wenn ich mir modbus sparen kann, nehme ich das auch gern wieder raus, dann muss ein Gerät weniger mitlaufen… Halte mich / und hier gern auf dem laufenden!

  6. Hi,
    jetzt läuft meine Integration seit 2 Tagen ganz ordentlich.
    Folgendes muss man tun:
    1.) API aktivieren lassen
    2.) In Openhab das 3rd Party Binding „TCP/UDP Binding“ installieren
    3.) 2 neue Things anlegen (habe das über das UI gemacht:
    a) Ein Thing für den UDP Client: Dort tragt ihr die IP-Adresse und den Port Eurer Venus ein.
    In dem neuen Thing auch einen Channel vom Typ „String“ anlegen, z.B. sendData
    b) Ein weiteres Thing für den UDP Receiver: Dort habe ich als host 0.0.0.0 eingetragen, zuerst hatte ich die Venus drin, aber das hat irgendwie nicht geklappt (ist vermutlich auch falsch). Als port den richtigen UDP Port eintragen.
    In diesem Receiver-Thing dann einen channel, z.B. result. Als Address Filter habe ich folgendes eingegeben, damit er nur auf meine Venus hört: 192.168.178.63:*

    4.) Folgende Items habe ich angelegt (alle verknüpft mit einem MQTT CHannel, weil ich eine Integration ins EVCC gebastelt habe). Wer das nicht braucht, kann das MQTT auch weglassen.
    String Marstek_Send_Data „Marstek Senden“ { channel=“tcpudp:client:8d7c831141:sendData“ }
    String Marstek_Receive_Data „Marstek Empfangen“ { channel=“tcpudp:receiver:afff5d1e5d:result“ }
    Number Marstek_Battery_SOC „Marstek SOC [%.0f %%]“ [ „Internal“ ] {channel=“mqtt:topic:brokerhome:marstek:soc“}
    Number Marstek_Battery_Power „Marstek Power [%.0f W]“ [ „Internal“ ] {channel=“mqtt:topic:brokerhome:marstek:power“}

    5.) Rules. Hier schicke ich alle 10 Sekunden einen String über den Client und bekomme über den Receiver die Resultate per JSON zurück, die ich dann nach Item aufschlüssele und in meinem Fall direkt über MQTT publiziere.:
    rule „Trigger Marstek Battery Data“
    // Trigger every 10 seconds the battery data from Marstek
    when
    Time cron „0/10 0/1 * 1/1 * ? *“
    then
    var String json = ‚{„id“: 1, „method“: „ES.GetStatus“, „params“: {„id“: 0}}‘
    Marstek_Send_Data.sendCommand(json);
    end

    rule „Get Marstek Battery Data“

    when
    Item Marstek_Receive_Data changed
    then
    val String json = (Marstek_Receive_Data.state as StringType).toString
    val String soc = transform(„JSONPATH“, „$.result.bat_soc“, json)
    val String discharge = transform(„JSONPATH“, „$.result.ongrid_power“, json)
    val String charge = transform(„JSONPATH“, „$.result.offgrid_power“, json)
    Marstek_Battery_SOC.sendCommand(soc)
    if (Float::parseFloat(charge) > 0 ) {
    Marstek_Battery_Power.sendCommand(charge)
    } else {
    Marstek_Battery_Power.sendCommand(discharge)
    }
    end

    Viel Glück beim testen!

    1. Danke für deinen Vertrag! Aktuell schaltet der Support die API leider nicht mehr frei, meine Anfrage wurde abgelehnt, mit der Begründung, man würde das aktuell nicht mehr anbieten und sich melden, wenn man das wieder anbiete…
      Von daher bleibe ich erst mal bei modbus. Sobald das aber geht, schaue ich es mir gerne an!

  7. Ok, ich habe geschrieben, dass ich Software-Entwickler bin und eine Integration ins Smarthome bauen will. Das hat vermutlich gezogen.

    Sonst kannst Du mal checken, ob die Freischaltung auch mit diesem Tool funktioniert (über Bluetooth verbinden, dafür darf aber zum gleichen Zeitpunkt eine Verbindung mit dem Smartphone laufen).
    https://github.com/rweijnen/marstek-venus-monitor
    Am besten die Beta Version nehmen …

  8. Hi zusammen, ich habe auch den Venus und zwar in der 3.0 Version. Ich habe mich beim Support wegen der alten FW gemeldet und die V144 freigeschaltet bekommen.

    Nun habe ich zufällig festgestellt, dass am LAN bzw. WIFI Anschluss des Speichers der Port 502 nach dem Reset offen war – was mich stutzig gemacht hat. Denn das ist der Modbus TCP Port. Aber Ich habe keinen RS-485 Adapter – sondern der ist da – nativ via TCP! 🔥 🔥 🔥

    Ich habe mich nach etwas probieren auch darauf verbinden können. Es scheint so, dass es funktioniert! Mit der kompletten Liste der Register ist es in Openhab noch etwas unstabil – da bin ich noch am testen.

    Es wäre eine große Hilfe, wenn sich andere Besitzer mit Firmware V144 auf dem Venus E 3.0 die Mühe machen könnten und mal Portscan auf die IP(s) des Speichers machen würden um zu sehen, ob sie auch einen offenen Port 502 finden. Vermutlich muss der Speicher dafür einmal Werksresetted werden (10s den Power Button drücken).

    Danach direkt einen Portscan auf die IP des Speichers machen (z.B. mit nmap oder fing):
    – Alle offenen TCP-Ports scannen:
    nmap -sT
    – Intensiver Scan mit Service-Erkennung:
    nmap -sV -p-

    Ist der Port offen, gerne in OH/ HA den modbus adapter auf die Adresse konfigurieren und mal testen, was passiert 🙂

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden.

Durch die weitere Nutzung der Seite wird der Verwendung von Cookies und den Inhalten der Datenschutzerklärung zugestimmt. Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklärst du sich damit einverstanden.

Schließen