Hi, schön das dir das Projekt gefällt, ich versuche mal deine Fragen zu beantworten...
- MP2 hängt aktuell nur am AC-IN da ich bisher noch keine Notstromfähigkeit nutze, kommt aber noch.
- Grid Zähler (Siemens PAC3200) hängt quasi vor dem EVU Zähler, könntest du so auch mit deinem EHZ Zähler mit IR Lesekopf abbilden. Wenn du die Werte schon im FHEM hast umso besser, musst sie nur auf einem MQTT Server bereitstellen. Das Python Script habe ich dir unten angehängt. Ist eine Anpassung von HIER, dort steht auch wie es installiert wird. Ich taste mit 1s ab, 5s gehen natürlich auch, da kann der MP2 natürlich einen Bedarf durchs Haus nicht so schnell ausregeln, prozentual gesehen ist das aber nicht die Welt... auch bei schnellerer Abtastung braucht der MP2 ein paar Sekunden bis er seine Leistung anpasst.
- Fronius müsste nicht unbedingt mit Venus reden, Venus weiß auch über den Grid zähler alles was nötig ist.
- Wenn du weitere Module verbauen willst kannst du einfach nen weiteren WR AC gekoppelt oder mit nem MPPT DC gekoppelt laden. DC gekoppelt hat halt den Charme das du "Schwarzstartfähig" bist bzw. bei einem Stromausfall der Akku auch geladen würde und der MP2 dich dann an seinem Notstrom Ausgang versorgen könnte. Ein 3-Phasen WR dürfte nur anspringen wenn er 3 Phasen sieht, da ein MP2 aber nur 1 Phasig arbeitet bräuchtest du 3 Stück oder Einphasige WRs damit du auch bei Stromausfall laden könntest.
- Genau, der MP2 speist eigentlich nicht ein, will den Strom ja selbst verbrauchen
Lediglich der Überschuss = ErtragPV - LadenAkku - EigenverbrauchHaus wird eingespeißt. Angemeldet werden muss die Anlage (meines Wissens nach) trotzdem. Schieflast ist soweit OK weil noch innerhalb der Regularien.
Hoffe ich konnte dir alles halbwegs beantworten :thumbup:
Gruß Eloeee
#!/usr/bin/env python
try:
import gobject # Python 2.x
except:
from gi.repository import GLib as gobject # Python 3.x
import platform
import logging
import time
import sys
import json
import os
import paho.mqtt.client as mqtt
try:
import thread # for daemon = True / Python 2.x
except:
import _thread as thread # for daemon = True / Python 3.x
our own packages
sys.path.insert(1, os.path.join(os.path.dirname(file), '../ext/velib_python'))
from vedbus import VeDbusService
path_UpdateIndex = '/UpdateIndex'
MQTT Setup
broker_address = "192.168.1.100"
port = 1883
MQTTNAME = "Iobroker"
Variblen setzen
verbunden = 0
durchlauf = 0
maxcellvoltage = 3.0
powercurr = 0
totalin = 0
totalout = 0
MQTT Abfragen:
def on_disconnect(client, userdata, rc):
global verbunden
print("Client Got Disconnected")
if rc != 0:
print('Unexpected MQTT disconnection. Will auto-reconnect')
else:
print('rc value:' + str(rc))
try:
print("Trying to Reconnect")
client.connect(broker_address)
verbunden = 1
except Exception as e:
logging.exception("Fehler beim reconnecten mit Broker")
print("Error in Retrying to Connect with Broker")
verbunden = 0
print(e)
def on_connect(client, userdata, flags, rc):
print("Verbunden mit IoBroker: " + broker_address)
client.subscribe("zaehler/strom/EVU/WirkleistungGesamt")
client.subscribe("zaehler/strom/EVU/WirkleistungL1")
client.subscribe("zaehler/strom/EVU/WirkleistungL2")
client.subscribe("zaehler/strom/EVU/WirkleistungL3")
client.subscribe("zaehler/strom/EVU/StromL1")
client.subscribe("zaehler/strom/EVU/StromL2")
client.subscribe("zaehler/strom/EVU/StromL3")
client.subscribe("zaehler/strom/EVU/Bezug")
client.subscribe("zaehler/strom/EVU/Einspeisung")
def on_message(client, userdata, message):
global powercurr,power_p1, power_p2, power_p3, totalin, totalout, i_p1, i_p2, i_p3
msg = str(message.payload.decode("utf-8"))
print("message received: ", msg)
print("message topic: ", message.topic)
if message.topic == "zaehler/strom/EVU/WirkleistungGesamt":
powercurr = float(msg)
if message.topic == "zaehler/strom/EVU/WirkleistungL1":
power_p1 = float(msg)
if message.topic == "zaehler/strom/EVU/WirkleistungL2":
power_p2 = float(msg)
if message.topic == "zaehler/strom/EVU/WirkleistungL3":
power_p3 = float(msg)
if message.topic == "zaehler/strom/EVU/StromL1":
i_p1 = float(msg)
if message.topic == "zaehler/strom/EVU/StromL2":
i_p2 = float(msg)
if message.topic == "zaehler/strom/EVU/StromL3":
i_p3 = float(msg)
if message.topic == "zaehler/strom/EVU/Bezug":
totalin = float(msg)
if message.topic == "zaehler/strom/EVU/Einspeisung":
totalout = float(msg)
class DbusDummyService:
def init(self, servicename, deviceinstance, paths, productname='Smart Meter', connection='MQTT'):
self._dbusservice = VeDbusService(servicename)
self._paths = paths
logging.debug("%s /DeviceInstance = %d" % (servicename, deviceinstance))
Create the management objects, as specified in the ccgx dbus-api document
self._dbusservice.add_path('/Mgmt/ProcessName', file)
self._dbusservice.add_path('/Mgmt/ProcessVersion', 'Unkown version, and running on Python ' + platform.python_version())
self._dbusservice.add_path('/Mgmt/Connection', connection)
Create the mandatory objects
self._dbusservice.add_path('/DeviceInstance', deviceinstance)
self._dbusservice.add_path('/ProductId', 45069) # value used in ac_sensor_bridge.cpp of dbus-cgwacs
self._dbusservice.add_path('/ProductName', productname)
self._dbusservice.add_path('/FirmwareVersion', 0.1)
self._dbusservice.add_path('/Role', 'grid')
self._dbusservice.add_path('/HardwareVersion', 0)
self._dbusservice.add_path('/Connected', 1)
_kwh = lambda p, v: (str(v) + 'kWh')
_a = lambda p, v: (str(v) + 'A')
_w = lambda p, v: (str(v) + 'W')
_v = lambda p, v: (str(v) + 'V')
_s = lambda p, v: (str(v) + 's')
_x = lambda p, v: (str(v))
self._dbusservice.add_path('/Ac/Energy/Forward', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/Energy/Reverse', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/L1/Current', None, gettextcallback=_a)
self._dbusservice.add_path('/Ac/L1/Energy/Forward', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/L1/Energy/Reverse', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/L1/Power', None, gettextcallback=_w)
self._dbusservice.add_path('/Ac/L1/Voltage', None, gettextcallback=_v)
self._dbusservice.add_path('/Ac/L2/Current', None, gettextcallback=_a)
self._dbusservice.add_path('/Ac/L2/Energy/Forward', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/L2/Energy/Reverse', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/L2/Power', None, gettextcallback=_w)
self._dbusservice.add_path('/Ac/L2/Voltage', None, gettextcallback=_v)
self._dbusservice.add_path('/Ac/L3/Current', None, gettextcallback=_a)
self._dbusservice.add_path('/Ac/L3/Energy/Forward', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/L3/Energy/Reverse', None, gettextcallback=_kwh)
self._dbusservice.add_path('/Ac/L3/Power', None, gettextcallback=_w)
self._dbusservice.add_path('/Ac/L3/Voltage', None, gettextcallback=_v)
self._dbusservice.add_path('/Ac/Power', None, gettextcallback=_w)
self._dbusservice.add_path('/Ac/Current', None, gettextcallback=_a)
self._dbusservice.add_path('/Ac/Voltage', None, gettextcallback=_v)
for path, settings in self._paths.items():
self._dbusservice.add_path(
path, settings['initial'], writeable=True, onchangecallback=self._handlechangedvalue)
gobject.timeout_add(1000, self._update) # pause 1000ms before the next request
def _update(self):
self._dbusservice['/Ac/Power'] = (str(round(powercurr, 2)) + 'W') # positive: consumption, negative: feed into grid
self._dbusservice['/Ac/L1/Voltage'] = (str(round(230, 2)) + 'V')
self._dbusservice['/Ac/L2/Voltage'] = (str(round(230, 2)) + 'V')
self._dbusservice['/Ac/L3/Voltage'] = (str(round(230, 2)) + 'V')
self._dbusservice['/Ac/L1/Current'] = (str(round(i_p1, 2)) + 'A')
self._dbusservice['/Ac/L2/Current'] = (str(round(i_p2, 2)) + 'A')
self._dbusservice['/Ac/L3/Current'] = (str(round(i_p3, 2)) + 'A')
self._dbusservice['/Ac/L1/Power'] = (str(round(power_p1, 2)) + 'W')
self._dbusservice['/Ac/L2/Power'] = (str(round(power_p2, 2)) + 'W')
self._dbusservice['/Ac/L3/Power'] = (str(round(power_p3, 2)) + 'W')
self._dbusservice['/Ac/Energy/Forward'] = (str(round(totalin/1000, 2)) + 'kWh')
self._dbusservice['/Ac/Energy/Reverse'] = (str(round(totalout/1000, 2)) + 'kWh')
self._dbusservice['/Ac/Power'] = round(powercurr, 2)
self._dbusservice['/Ac/Current'] = '{0:0.2f}'.format(i_p1+i_p2+i_p3)
self._dbusservice['/Ac/Voltage'] = '{0:0.2f}'.format(230)
self._dbusservice['/Ac/L1/Voltage'] = '{0:0.2f}'.format(230)
self._dbusservice['/Ac/L2/Voltage'] = '{0:0.2f}'.format(230)
self._dbusservice['/Ac/L3/Voltage'] = '{0:0.2f}'.format(230)
self._dbusservice['/Ac/L1/Current'] = '{0:0.2f}'.format(i_p1)
self._dbusservice['/Ac/L2/Current'] = '{0:0.2f}'.format(i_p2)
self._dbusservice['/Ac/L3/Current'] = '{0:0.2f}'.format(i_p3)
self._dbusservice['/Ac/L1/Power'] = round(power_p1, 2)
self._dbusservice['/Ac/L2/Power'] = round(power_p2, 2)
self._dbusservice['/Ac/L3/Power'] = round(power_p3, 2)
self._dbusservice['/Ac/Energy/Forward'] = '{0:0.2f}'.format(totalin/1000)
self._dbusservice['/Ac/Energy/Reverse'] = '{0:0.2f}'.format(totalout/1000)
logging.info("House Consumption: {:.0f}".format(powercurr))
increment UpdateIndex - to show that new data is available
index = self._dbusservice[path_UpdateIndex] + 1 # increment index
if index > 255: # maximum value of the index
index = 0 # overflow from 255 to 0
self._dbusservice[path_UpdateIndex] = index
return True
def _handlechangedvalue(self, path, value):
logging.debug("someone else updated %s to %s" % (path, value))
return True # accept the change
def main():
logging.basicConfig(level=logging.DEBUG) # use .INFO for less logging
thread.daemon = True # allow the program to quit
from dbus.mainloop.glib import DBusGMainLoop
Have a mainloop, so we can send/receive asynchronous calls to and from dbus
DBusGMainLoop(set_as_default=True)
#formatting
_kwh = lambda p, v: (str(round(v, 2)) + 'kWh')
_a = lambda p, v: (str(round(v, 1)) + 'A')
_w = lambda p, v: (str(round(v, 1)) + 'W')
_v = lambda p, v: (str(round(v, 1)) + 'V')
pvac_output = DbusDummyService(
servicename='com.victronenergy.grid.evu',
deviceinstance=21,
paths={
'/Ac/Power': {'initial': 0, 'textformat': _w},
'/Ac/L1/Voltage': {'initial': 0, 'textformat': _v},
'/Ac/L2/Voltage': {'initial': 0, 'textformat': _v},
'/Ac/L3/Voltage': {'initial': 0, 'textformat': _v},
'/Ac/L1/Current': {'initial': 0, 'textformat': _a},
'/Ac/L2/Current': {'initial': 0, 'textformat': _a},
'/Ac/L3/Current': {'initial': 0, 'textformat': _a},
'/Ac/L1/Power': {'initial': 0, 'textformat': _w},
'/Ac/L2/Power': {'initial': 0, 'textformat': _w},
'/Ac/L3/Power': {'initial': 0, 'textformat': _w},
'/Ac/Energy/Forward': {'initial': 0, 'textformat': _kwh}, # energy bought from the grid
'/Ac/Energy/Reverse': {'initial': 0, 'textformat': _kwh}, # energy sold to the grid
path_UpdateIndex: {'initial': 0},
})
pvac_output = DbusDummyService(
servicename='com.victronenergy.grid.cgwacs_ttyUSB0_di30_mb1',
deviceinstance=21,
paths={
})
logging.info('Connected to dbus, and switching over to gobject.MainLoop() (= event based)')
mainloop = gobject.MainLoop()
mainloop.run()
Konfiguration MQTT