Script wurde am 28.03.23 für die neueste OpenDTU-Version aktualisiert.
Dies ist ein Python-Skript, das den aktuellen Hausverbrauch aus einem Shelly 3EM ausliest, die Nulleinspeisung berechnet und die Ausgangsleistung eines Hoymiles-Wechselrichters mit Hilfe der OpenDTU entsprechend anpasst. Somit wird kein unnötiger Strom ins Betreibernetz abgegeben.
Funktionsdiagramm:

Python Code
import requests, time
from requests.auth import HTTPBasicAuth
import os
# Diese Daten müssen angepasst werden: zeile 5 - 12
serial = "112182050470" # Seriennummern der Hoymiles Wechselrichter
maximum_wr = 300 # Maximum ausgabe des wechselrichters
dtuIP = '192.168.188.29' # IP Adresse von OpenDTU
dtuNutzer = 'admin' # OpenDTU Nutzername
dtuPasswort = 'openDTU42' # OpenDTU Passwort
shellyIP = '192.168.188.34' #IP Adresse von Shelly 3EM
while True:
# Nimmt Daten von der openDTU Rest-API und übersetzt sie in ein json-Format
r = requests.get(url = f'http://{dtuIP}/api/livedata/status/inverters' ).json()
# Selektiert spezifische Daten aus der json response
reachable = r['inverters'][0]['reachable'] # ist DTU erreichbar ?
producing = int(r['inverters'][0]['producing']) # produziert der Wechselrichter etwas ?
altes_limit = int(r['inverters'][0]['limit_absolute']) # wo war das alte Limit gesetzt
power_dc = r['inverters'][0]['AC']['0']['Power DC']['v'] # Lieferung DC vom Panel
power = r['inverters'][0]['AC']['0']['Power']['v'] # Abgabe BKW AC in Watt
# Nimmt Daten von der Shelly 3EM Rest-API und übersetzt sie in ein json-Format
phaseA = requests.get(f'http://{shellyIP}/emeter/0', headers={"Content-Type": "application/json"}).json()['power']
phaseB = requests.get(f'http://{shellyIP}/emeter/1', headers={"Content-Type": "application/json"}).json()['power']
phaseC = requests.get(f'http://{shellyIP}/emeter/2', headers={"Content-Type": "application/json"}).json()['power']
grid_sum = phaseA + phaseB + phaseC # Aktueller Bezug im Chalet - rechnet alle Phasen zusammen
setpoint = 0 # Neues Limit in Watt
# Setzt ein limit auf das Wechselrichter
def setLimit(Serial, Limit):
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
payload = f'''data={{"serial":"{Serial}", "limit_type":1, "limit_value":{Limit}}}'''
newLimit = requests.post(url=f'http://{dtuIP}/api/limit/config', data=payload, auth=HTTPBasicAuth(dtuNutzer, dtuPasswort), headers=headers)
print('Konfiguration Stauts:', newLimit.json()['type'])
# Werte setzen
print("aktueller Bezug - Haus: ",grid_sum)
if reachable:
# Setzen Sie den Grenzwert auf den höchsten Wert, wenn er über dem zulässigen Höchstwert liegt.
if (altes_limit >= maximum_wr or grid_sum >= maximum_wr or setpoint >= maximum_wr):
print("setze Limiter auf maximum")
setpoint = maximum_wr
# wir weniger bezogen als maximum_wr dann neues Limit ausrechnen
if (grid_sum+altes_limit) <= maximum_wr:
setpoint = grid_sum + altes_limit - 5
print("setpoint:",grid_sum,"+",altes_limit,"-5 ")
print("neues Limit berechnet auf ",setpoint)
if setpoint <= 100:
setpoint = 100
print("setpoint: 100 minimum gesetzt")
print("neues Limit festgelegt auf ",setpoint)
print("setze Einspeiselimit auf: ",setpoint)
# neues limit setzen
setLimit(serial, setpoint)
print("Solarzellenstrom:",power," Setpoint:",setpoint)
time.sleep(5) # wait
# Wenn der Wechselrichter nicht erreicht werden kann, wird der limit auf maximum gestellt
if setpoint == 0: setpoint = grid_sum
if not reachable: setpoint = maximum_wr
GitHub Repo: https://github.com/Selbstbau-PV/Selbstbau-PV-Hoymiles-nulleinspeisung-mit-OpenDTU-und-Shelly3EM
Einrichtung:
- Shelly 3EM: Sie müssen den Shelly 3EM mit dem Netzwerk verbinden, in dem sich Ihr Computer befindet. Sie können dies tun, indem Sie das Web-GUI Ihres Shelly-Produkts aufrufen → Internet & Sicherheit → WIFI-MODUS – CLIENT. Setzen Sie ein Häkchen, um das Shelly-Gerät mit einem bestehenden WiFi-Netzwerk zu verbinden, geben Sie den Namen und das Passwort Ihres Netzwerks in die entsprechenden Felder ein und klicken Sie auf Speichern.

- OpenDTU: Sie müssen die OpenDTU an das gleiche Netz wie Ihr eigenes anschließen. Dazu öffnen Sie die OpenDTU Web-GUI → Einstellungen → Netzwerkeinstellungen, füllen die entsprechenden Felder aus und drücken auf Speichern

- Python-Skript: Einige Parameter müssen noch im Python Skript angepasst werden. Danach übertragen Sie das Skript auf Ihren Raspberry PI.

Service anlegen: Um sicherzustellen, dass das Skript gestartet wird, wenn der Raspberry Pi neu startet, rebootet oder hochfährt, müssen Sie einen Service einrichten. Dazu benutzen sie den Befehl sudo nano /etc/systemd/system/nulleinspeisung.service
. Dadurch öffnet sich ein Texteditor, in den Sie den folgenden Text einfügen:
[Unit]
Description=Nulleinspeisung Service
After=multi-user.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/python3 /path/to/your/script.py
[Install]
WantedBy=multi-user.target
- natürlich, muss der Pfad zur Python-Datei entsprechend angepasst werden
- Skript-Abhängigkeiten: Um das Skript auszuführen wird eine Python Abhängigkeit benötigt. Benutzen sie das Kommando
sudo apt install python3-pip
um den Paketmanager auf ihrem System zu installieren. Mitsudo pip install requests
installieren sie die Abhängigkeit
- Service-Starten: Nun müssen Sie den Dienst initialisieren, dazu müssen Sie die folgenden Befehle in Ihre Konsole schreiben:
sudo systemctl daemon-reload
->sudo systemctl enable nulleinspeisung.service
->sudo systemctl start nulleinspeisung.service
. Nachdem Sie das getan haben, überprüfen Sie, ob Ihr Dienst läuft, indem Siesudo systemctl status nulleinspeisung.service
in Ihrer ssh eingeben. So sollte die Ausgabe aussehen:
● nulleinspeisung.service - Nulleinspeisung Service
Loaded: loaded (/etc/systemd/system/nulleinspeisung.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-01-27 14:31:08 GMT; 4s ago
Main PID: 32195 (python3)
Tasks: 1 (limit: 415)
CPU: 4.505s
CGroup: /system.slice/nulleinspeisung.service
└─32195 /usr/bin/python3 /home/nulleinspeisung/nulleinspeisung.py
Hinweis: Das es sich bei dem Skript um ein Python Skript handelt, muss dies nicht zwingend auf einem Raspberry Pi installiert und ausgeführt werden. Wenn sie ein anders System zum ausführen des Scripts benutzen wollen ist dies völlig in Ordnung. Das System muss nur Python fähig sein.