I recently bought a battery marstek Eva 3.
Integrating in energydashboard was not that difficult.
From the battery's registers I get the varous values.
The kWh in and out are presented as values which are regular updated. Values are accepted in dz using custom kWh device. These are not accepted in the energy dahboard. I got stuck for now. How to proceed?
Bart
How populate kWh device
Moderator: leecollings
-
BartSr
- Posts: 548
- Joined: Sunday 03 July 2016 16:16
- Target OS: Raspberry Pi / ODroid
- Domoticz version: V2024.7
- Location: Netherlands
- Contact:
How populate kWh device
Raspberry pi 3b
Arduino
KAKU
RfxCom
Zwave2MQTT
OTGW
Chinese sensors temp (Dallas),movement
Tasmota
Esp8266 / 32 espeasy
Zigbee2MQTT
Arduino
KAKU
RfxCom
Zwave2MQTT
OTGW
Chinese sensors temp (Dallas),movement
Tasmota
Esp8266 / 32 espeasy
Zigbee2MQTT
-
RNEE
- Posts: 83
- Joined: Sunday 05 August 2018 10:13
- Target OS: Raspberry Pi / ODroid
- Domoticz version: 2026.4
- Location: NL/Eindhoven area
- Contact:
Re: How populate kWh device
I don’t read how you get your values from Eva in Domoticz.
i made a tool for reading the registers from Marstek Venus V2.
I used a P1 domoticz device 250 for reporting in-out values, and that works very well.
viewtopic.php?t=43830
i made a tool for reading the registers from Marstek Venus V2.
I used a P1 domoticz device 250 for reporting in-out values, and that works very well.
viewtopic.php?t=43830
Domoticz (since 2016) on Docker on Raspberry PI 5 with 500 Gb NVMe|Milight|KaKu + RFXCOM|Goodwe|Smartstuff P1 meter|Buienradar|Afval kalender|Tuya-wifi|Zigbee + deCONZ Conbee II|Marstek Homebattery 5,12Kwh via Modbus on Pusr-dr134|MQTTMapper|Quatt v2|
-
BartSr
- Posts: 548
- Joined: Sunday 03 July 2016 16:16
- Target OS: Raspberry Pi / ODroid
- Domoticz version: V2024.7
- Location: Netherlands
- Contact:
Re: How populate kWh device
Here is my code to get data via Modbus tcp without need of PUSER-DR134
Code: Select all
#!/usr/bin/env python3
"""Marstek Venus E 3.0 - Modbus TCP naar MQTT/Domoticz.
Domoticz IDX-koppelingen:
2463 batterijvermogen (W)
2459 batterij SOC (%)
2460 batterijspanning (V)
2461 totaal geladen energie (kWh)
2462 totaal ontladen energie (kWh)
Registerinterpretaties:
30000[1] : vermogen, signed 16-bit, W
30100[0] : spanning, /100 = V
30100[1] : stroom, signed 16-bit, /10 = A (alleen log/diagnose)
34001[1] : SOC, /10 = %
33000[0:4]: twee 32-bit tellers (high word, low word), /100 = kWh
Let op: de schaalfactoren en interpretaties van spanning en energietellers
zijn gebaseerd op de eerder onderzochte registerwaarden. Controleer ze aan
de hand van plausibiliteit en veranderingen in de Marstek voordat je ze als
definitief beschouwt. Stroom wordt nog niet naar Domoticz gepubliceerd.
"""
import json
import logging
import time
from datetime import datetime
import paho.mqtt.client as mqtt
from pymodbus.client import ModbusTcpClient
# Marstek Ethernet
MARSTEK_IP = "192.168.2.97"
MARSTEK_PORT = 502
MODBUS_DEVICE_ID = 1
MODBUS_TIMEOUT = 5
# MQTT
MQTT_HOST = "127.0.0.1"
MQTT_PORT = 1883
MQTT_CLIENT_ID = "marstek_reader"
MQTT_RAW_TOPIC = "marstek/raw"
DOMOTICZ_TOPIC = "domoticz/in"
# Domoticz IDX
IDX = {
"battery_power": 2463,
"battery_soc": 2459,
"battery_voltage": 2460,
"battery_energy_in": 2461,
"battery_energy_out": 2462,
}
INTERVAL_SECONDS = 5
# Adressen en aantallen zijn gelijk gehouden aan de eerder werkende reader.
REGISTERS = {
"30000": (30000, 2),
"30100": (30100, 2),
"34001": (34001, 3),
"33000": (33000, 4),
}
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
def signed16(value):
"""Converteer een unsigned Modbus-register naar signed 16-bit."""
return value if value < 32768 else value - 65536
def uint32(high_word, low_word):
"""Combineer twee 16-bit registers: eerst high word, dan low word."""
return (int(high_word) << 16) | int(low_word)
def publish_domoticz(client, idx, value):
if not idx:
return
payload = {"idx": int(idx), "nvalue": 0, "svalue": str(value)}
info = client.publish(
DOMOTICZ_TOPIC, json.dumps(payload), qos=1, retain=False
)
info.wait_for_publish()
if info.rc != mqtt.MQTT_ERR_SUCCESS:
raise RuntimeError(f"MQTT-publicatie mislukt voor Domoticz IDX {idx}")
def read_register_blocks():
client = ModbusTcpClient(
MARSTEK_IP,
port=MARSTEK_PORT,
timeout=MODBUS_TIMEOUT,
retries=0,
)
try:
if not client.connect():
raise ConnectionError(
f"Marstek niet bereikbaar op {MARSTEK_IP}:{MARSTEK_PORT}"
)
data = {}
for name, (address, count) in REGISTERS.items():
response = client.read_holding_registers(
address=address,
count=count,
device_id=MODBUS_DEVICE_ID,
)
if response.isError():
raise RuntimeError(
f"Modbus-fout bij registerblok {address}: {response}"
)
data[name] = response.registers
time.sleep(0.3)
return data
finally:
client.close()
def decode_measurements(data):
"""Decodeer alleen de eerder onderzochte meetwaarden."""
power_w = signed16(data["30000"][1])
# Blok 30100: eerste woord spanning, tweede woord stroom.
voltage_v = data["30100"][0] / 100.0
current_a = signed16(data["30100"][1]) / 10.0
# Blok 34001: tweede woord is SOC in tienden van procenten.
soc_percent = data["34001"][1] / 10.0
# Blok 33000: twee 32-bit cumulatieve tellers.
energy_in_kwh = uint32(data["33000"][0], data["33000"][1]) / 100.0
energy_out_kwh = uint32(data["33000"][2], data["33000"][3]) / 100.0
return {
"battery_power": power_w,
"battery_soc": soc_percent,
"battery_voltage": voltage_v,
"battery_current": current_a,
"battery_energy_in": energy_in_kwh,
"battery_energy_out": energy_out_kwh,
}
def main():
mqtt_client = mqtt.Client(client_id=MQTT_CLIENT_ID)
mqtt_client.connect(MQTT_HOST, MQTT_PORT, 60)
mqtt_client.loop_start()
logging.info("Marstek Venus E 3.0-driver gestart")
logging.info("Modbus: %s:%s", MARSTEK_IP, MARSTEK_PORT)
logging.info("Domoticz IDX'en: %s", IDX)
try:
while True:
try:
data = read_register_blocks()
values = decode_measurements(data)
# Ruwe registers bewaren voor controle en verdere analyse.
raw_payload = {
"timestamp": datetime.now().isoformat(),
"registers": data,
"decoded": values,
}
info = mqtt_client.publish(
MQTT_RAW_TOPIC,
json.dumps(raw_payload),
qos=1,
retain=True,
)
info.wait_for_publish()
publish_domoticz(
mqtt_client, IDX["battery_power"], values["battery_power"]
)
publish_domoticz(
mqtt_client, IDX["battery_soc"], values["battery_soc"]
)
publish_domoticz(
mqtt_client, IDX["battery_voltage"], values["battery_voltage"]
)
publish_domoticz(
mqtt_client, IDX["battery_energy_in"], values["battery_energy_in"]
)
publish_domoticz(
mqtt_client, IDX["battery_energy_out"], values["battery_energy_out"]
)
logging.info(
"Marstek | vermogen: %s W | SOC: %.1f%% | "
"spanning: %.2f V | stroom: %.1f A | "
"geladen: %.2f kWh | ontladen: %.2f kWh",
values["battery_power"],
values["battery_soc"],
values["battery_voltage"],
values["battery_current"],
values["battery_energy_in"],
values["battery_energy_out"],
)
except Exception as error:
logging.exception("Marstek uitleesfout: %s", error)
time.sleep(INTERVAL_SECONDS)
except KeyboardInterrupt:
logging.info("Marstek-driver handmatig gestopt")
finally:
mqtt_client.loop_stop()
mqtt_client.disconnect()
if __name__ == "__main__":
main()
Raspberry pi 3b
Arduino
KAKU
RfxCom
Zwave2MQTT
OTGW
Chinese sensors temp (Dallas),movement
Tasmota
Esp8266 / 32 espeasy
Zigbee2MQTT
Arduino
KAKU
RfxCom
Zwave2MQTT
OTGW
Chinese sensors temp (Dallas),movement
Tasmota
Esp8266 / 32 espeasy
Zigbee2MQTT
-
RNEE
- Posts: 83
- Joined: Sunday 05 August 2018 10:13
- Target OS: Raspberry Pi / ODroid
- Domoticz version: 2026.4
- Location: NL/Eindhoven area
- Contact:
Re: How populate kWh device
Ah okay, the V2 doesn't have its own network interface like the V3 ev.
So that requires the P-usr134. It also takes care of the query of the registers.
But can't you do anything with the P1 device 250 for reporting?
So that requires the P-usr134. It also takes care of the query of the registers.
But can't you do anything with the P1 device 250 for reporting?
Domoticz (since 2016) on Docker on Raspberry PI 5 with 500 Gb NVMe|Milight|KaKu + RFXCOM|Goodwe|Smartstuff P1 meter|Buienradar|Afval kalender|Tuya-wifi|Zigbee + deCONZ Conbee II|Marstek Homebattery 5,12Kwh via Modbus on Pusr-dr134|MQTTMapper|Quatt v2|