Der Code Sammelt Daten von einem Shelly (1pm) und stellt die Leistung via Modbus zur Verfügung. Und zwar in einer Form wie es ein EM24 Ethernet von Carlo Gavazzi / Victron tun würde.
Damit kann man Shellys in ein Victron GX einbinden. Dort kann man Konfigurieren als was sich das Energiemeter einbindet. Standard ist Netz Messung ("Grid"). Ich habe es als PV Inverter am Multiplus Ausgang konfiguriert. Ein Shelly3em wird vermutlich in kürze noch als Gridmeter kommen.
Etwas mehr Erklärung in der Röhre: https://www.youtube.com/watch?v=5n8DMf9HP0c
Port ist auf 1502 gesetzt, damit alles im ohne zicken im Userlevel laufen kann. Die GX erlaubt frei Port wahl.
Abhängigkeiten: benötigt wird nur
Code: Alles auswählen
pip3 install pyModbusTCP
Das Skript auf eine Maschine mit python3 kopieren. zB einem raspberry py.
Bei mir lauft es aber zZ als cron @reboot autostart. (ggf als service einrichten, das würde dem Pfusch aber nicht gerecht werden)
Code: Alles auswählen
from pyModbusTCP.server import ModbusServer, DataBank
import json
import sys
from urllib import request
import time
import threading
s_pow = None
def getpow():
global s_pow
return s_pow
def shellyget():
global s_pow
err = 0
while 1:
try:
l = request.urlopen("http://192.168.2.249/status").read().decode("utf-8")
j = json.loads(l)
p = j["meters"][0]["power"]
err = 0
except:
err += 1
if err > 5:
s_pow = None
time.sleep(1)
continue
s_pow = int(10*float(p))
time.sleep(20)
class Regs(DataBank):
def __init__(self):
# turn off allocation of memory for standard modbus object types
# only "holding registers" space will be replaced by dynamic build values.
super().__init__(virtual_mode=True)
def get_holding_registers(self, address, number=1, srv_info=None):
#print("reg: ", address, "#: ", number)
if number > 1000:
return
else:
if address == 11:
return [1648] # 12 type 1648->EM24DINAV23XE1X
if address == 770:
return [8*256+1*256+1] # 771 - rev meas
if address == 772:
return [8*256+6*256+1] # 773 - rev com
if address == 4098:
return [0] # meas sys 3P.n
if address == 20480:
return [ord('B')*256+ord('V'), ord('0')*256+ord('4'), ord('2')*256+ord('0'), ord('0')*256+ord('3'),ord('1')*256+ord('0'), ord('0')*256+ord('1'), ord('1')*256] # SN-> BK0390085001X
if address == 40960:
return [7] # Appl H (all)
if address == 0 and number == 80:
#return [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]
p = getpow() # p in W*10
if s_pow == None:
return
V = 2300
V_L1_N = V
V_L1_N_h = 0 # (V >> 16) & 0xFFFF
A_L1 = int(p * 1000 / V) & 0xFFFF
A_L1_h = (int(p * 1000 / V) >> 16) & 0xFFFF
P_S = p & 0xFFFF
P_S_h = (p >> 16) & 0xFFFF
VA_S = P_S
VA_S_h = P_S_h
### FIXME !!! only 16 bit used
# p5 EM24 E1 COMMUNICATION PROTOCOL pdf
return [V_L1_N, V_L1_N_h, 0, 0, 0, 0, #V L-N
0, 0, 0, 0, 0, 0, #V L-L
A_L1, A_L1_h, 0, 0, 0, 0, #A
p, 0, 0, 0, 0, 0, #W
0, 0, 0, 0, 0, 0, #VA
0, 0, 0, 0, 0, 0, #var
0, 0, 0, 0, #V
P_S, P_S_h, #W (sum)
VA_S, VA_S_h, #VA (sum)
0, 0, #var (sum)
0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
if address == 41216:
return [3] # switch locked
return
if __name__ == '__main__':
#print("run yeah!")
threading.Thread(target = shellyget).start()
# init modbus server and start it
server = ModbusServer(host='0.0.0.0', port=1502, data_bank=Regs())
#print (server)
server.start()
#reg: 11 #: 1 # type
#reg: 40960 #: 1 #application
#reg: 40960 #: 1 #application
#reg: 770 #: 1 # 771 - rev meas
#reg: 772 #: 1 # 773 - rev com
#reg: 4098 #: 1 # 4099 - meas sys
#reg: 20480 #: 7 # snum ascii
> crontab -e
dann in einer Zeile ergänzen:
Code: Alles auswählen
@reboot python3 /pfad/zum/skript.py
* Jetzt gibt es nur die Leistung. Spannung, Strom wird nur stumpf gesetzt.
* Und es werden nur die niederwertigen 16bit geschrieben. Bei >3KW gibt es einen überlauf
* Sowas von Pfusch
* Shelly3EM (und andere shellys) - Kann aber anhand dem Beispiel einfach ergänzt werden
Was nett wäre:
* Das ganze in einen Tasmota Fork einpflegen
Mitarbeit und Ergänzungen Willkommen