Giter Club home page Giter Club logo

selbstbau-pv / selbstbau-pv-hoymiles-nulleinspeisung-mit-opendtu-und-shelly3em Goto Github PK

View Code? Open in Web Editor NEW
61.0 9.0 24.0 114 KB

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.

Python 100.00%
nulleinspeisung opendtu python shelly-3em solar

selbstbau-pv-hoymiles-nulleinspeisung-mit-opendtu-und-shelly3em's Introduction

Achtung! bei OpenDTU gab es eine API Anpassung

Dieses Skript ist nur kompatibel bis einschließlich Version V24.1.26

Nulleinspeisung Hoymiles HM-1500 mit OpenDTU & Python Steuerung

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.

diagramm

Autoren und Anerkennung

Wiki

selbstbau-pv-hoymiles-nulleinspeisung-mit-opendtu-und-shelly3em's People

Contributors

selbstbau-pv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

selbstbau-pv-hoymiles-nulleinspeisung-mit-opendtu-und-shelly3em's Issues

Python Script change for Shelly 3EM Pro API

Hello, it would be very helpful for me, if sombody could modify this python script for a shelly 3EM pro, which has a different API than shelly 3EM.

Thanks in advance Markus

Python script update for two Hoymiles at one OpenDTU

Hi, thank you very much for updateing with the shelly 3EM Pro. It is working perfectly.

Now I want to use it for 2x HM-1500 which are in Line at one phase and are connected to one openDTU.
Is that possible?

Many thankx Markus

Fehlermeldung: NameError: name 'power' is not defined

Hallo zusammen,
ich hab jetzt schon einiges gelesen rund um diesen Code aber eine Lösung hat nicht geklappt.
hat einer eine Idee wie ich das zum laufen bekomme (der Raspberry und die DTU sind schon
neu aufgesetzt)?
Durch ChatGPT hab ich das auch schon gejagt, da kam aber auch nicht wirklich
was funktionsfähiges bei rum.
Danke schonmal,
Stefan

die Fehelermeldung sieht wie folgt aus:
In [1] runfile('/home/stefan/Nulleinspeisung/nulleinspeisung.py', wdir='/home/stefan/Nulleinspeisung')
Fehler beim Abrufen der Daten von openDTU
Traceback (most recent call last):

File /usr/lib/python3/dist-packages/spyder_kernels/py3compat.py:356 in compat_exec
exec(code, globals, locals)

File ~/Nulleinspeisung/nulleinspeisung.py:41
print(f'\nBezug: {round(grid_sum, 1)} W, Produktion: {round(power, 1)} W, Verbrauch: {round(grid_sum + power, 1)} W')

NameError: name 'power' is not defined


und der Code ist dieser:

`#!/usr/bin/env python3
import requests, time, sys
from requests.auth import HTTPBasicAuth

Diese Daten müssen angepasst werden:

serial = "114190639469" # Seriennummer des Hoymiles Wechselrichters
maximum_wr = 100 # Maximale Ausgabe des Wechselrichters
minimum_wr = 10 # Minimale Ausgabe des Wechselrichters

dtu_ip = '192.168.101.83' # IP Adresse von OpenDTU
dtu_nutzer = 'admin' # OpenDTU Nutzername
dtu_passwort = 'openDTU42' # OpenDTU Passwort

shelly_ip = '192.168.101.85' # IP Adresse von Shelly 3EM

while True:
try:
# Nimmt Daten von der openDTU Rest-API und übersetzt sie in ein json-Format
r = requests.get(url = f'http://{dtu_ip}/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']) # Altes Limit
    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
except:
    print('Fehler beim Abrufen der Daten von openDTU')
try:
    # Nimmt Daten von der Shelly 3EM Rest-API und übersetzt sie in ein json-Format
    phase_a     = requests.get(f'http://{shelly_ip}/emeter/0', headers={'Content-Type': 'application/json'}).json()['power']
    phase_b     = requests.get(f'http://{shelly_ip}/emeter/1', headers={'Content-Type': 'application/json'}).json()['power']
    phase_c     = requests.get(f'http://{shelly_ip}/emeter/2', headers={'Content-Type': 'application/json'}).json()['power']
    grid_sum    = phase_a + phase_b + phase_c # Aktueller Bezug - rechnet alle Phasen zusammen
except:
    print('Fehler beim Abrufen der Daten von Shelly 3EM')

# Werte setzen
print(f'\nBezug: {round(grid_sum, 1)} W, Produktion: {round(power, 1)} W, Verbrauch: {round(grid_sum + power, 1)} W')
if reachable:
    setpoint = grid_sum + altes_limit - 5 # Neues Limit in Watt

    # Fange oberes Limit ab
    if setpoint > maximum_wr:
        setpoint = maximum_wr
        print(f'Setpoint auf Maximum: {maximum_wr} W')
    # Fange unteres Limit ab
    elif setpoint < minimum_wr:
        setpoint = minimum_wr
        print(f'Setpoint auf Minimum: {minimum_wr} W')
    else:
        print(f'Setpoint berechnet: {round(grid_sum, 1)} W + {round(altes_limit, 1)} W - 5 W = {round(setpoint, 1)} W')

    if setpoint != altes_limit:
        print(f'Setze Inverterlimit von {round(altes_limit, 1)} W auf {round(setpoint, 1)} W... ', end='')
        # Neues Limit setzen
        try:
            r = requests.post(
                url = f'http://{dtu_ip}/api/limit/config',
                data = f'data={{"serial":"{serial}", "limit_type":0, "limit_value":{setpoint}}}',
                auth = HTTPBasicAuth(dtu_nutzer, dtu_passwort),
                headers = {'Content-Type': 'application/x-www-form-urlencoded'}
            )
            print(f'Konfiguration gesendet ({r.json()["type"]})')
        except:
            print('Fehler beim Senden der Konfiguration')

sys.stdout.flush() # write out cached messages to stdout
time.sleep(5) # wait`

Berechnung Hausverbrauch

Der Gesamtverbrauch über die drei Ausenleiter wird mittels dem Shelly 3EM je nach Situation falsch angezeigt.
Sofern der Wechselrichter am gleichen Verteiler nach dem 3EM hängt zählt der 3EM nur die aktuelle Leistung am Hausanschluss. Die Leistung von der PV Anlage muss hier noch addiert werden um den Hausgesamtverbrauch zu erhalten.

grid_sum = phaseA + phaseB + phaseC # Aktueller Bezug im Chalet - rechnet alle Phasen zusammen
müsste korrekt lauten:
grid_sum = phaseA + phaseB + phaseC + power # Aktueller Bezug aller Phasen Netz + Leistung PV

Neustart der Scripts nach Unterbrechung durch leere Batterie geht nicht

Hallo Leute,

bei mir läuft das Standart Script schon einige Zeit auf dem Raspi und mit allen Standart Komponenten wie auf der Selbstbau PV Homepage.

Ich habe das Problem das sobald meine Batteriewächter abschaltet, da Nachts irgendwann die Batterie leer ist, das Script anzeigt:
Fehler beim abrufen der Daten bzw. Fehler beim Senden der Daten an die DTU.
Irgendwann stoppt das ganze aber startet nicht neu, wenn der Batteriewächter wieder Spannung frei gibt. Dann fällt der Wechselrichter bzw. die DTU zurück auf das ehemalige Limit was ich mal in der DTU eingestellt hatte
Wenn wenig Zeit vergeht ohne Spannung am Wechselrichter geht es.

Nur ab ein Paar Stunden klappt es nicht.

Danke für eure Hilfe!

Anfänger sucht Hilfe

Hallo,
ich betreibe einen HM 1500 mit openDTU und shelly 3em. Das funktioniert prima.
Leider komme ich jetzt mit dem Pi und dem python script nicht weiter, da mir
dazu die Grundlagen fehlen.
Das script habe, ich wie in einem Video beschrieben, in spyder3 kopiert und
entsprechend geändert .
Jetzt fehlen mir einfach die Kenntnisse um weiter fortzufahren.
Gibt es jemanden, der mich an die Hand nimmt und Hilfe leisten kann?

Vielen Dank

Auch mit EM24 möglich ?

Hallo,

könnte man das auch mit einem EM24 statt dem Shelly realisieren?
Immerhin spricht er Modbus RTU.

Verbrauchsmessung mit Shelly Plug S?

Hallo zusammen,
funktioniert das Ganze auch mit einer Shelly Plug S?

Problem:

  • Um einen Shelly 3EM zu montieren muss man an die Phasen dran. Eine Installation sollte von keinem Laien gemacht werden.
  • Oft hat man am Zählerschrank schlechten bis keinen Wifi empfang

Man könnte so an jedem großen Verbraucher (TV, Beleuchtung etc.) eine Plug S zwischenstecken und das gleiche Prinzip wie Ecoflow es bald machen wird umsetzen.

Code-Anpassung für dynamische WR-Leistung bei Verwendung mit Akkuspeicher

Hallo zusammen,

ich habe für die Nulleinspeisung in Verbindung mit einem Akku nachstehende Anpassung eingebaut.

Durch die Anpassung wird die maximale WR-Leistung abhängig von der Akkuspannung in 3 Bereichen eingestellt um bei
vollem Akku eine hohe WR-Leistung zuzulassen und bei leerem Akku eine tiefenentladung zu vermeiden:

  1. Bereich: Viel Solarleistung bzw. Akku ist quasi voll, die WR Leistung darf sehr hoch sein.
  2. Bereich: Der Akku ist nicht sehr voll, jedoch noch oberhalb der Abschaltspannung (Die max. WR-Leistung wird etwas reduziert)
  3. Bereich: Der Akku hat seine Abschaltspannung erreicht, die max WR-Leistung wird auf den minimal möglichen Leistungswert von 10 W gesetzt, damit der Akku nicht tiefen entladen wird.

Dafür benötigen wir zwei Variablen im Bereich "# Diese Daten müssen angepasst werden" die die beiden Spannungsgrenzen bilden:

voltage_borderhigh = 26 # Spannungsgrenze für Erhöhung der WR-Leistung
voltage_borderlow = 24 # Spannungsgrenze für Setzen der WR-Leistung auf 10 W

ebenfalls benötigen wir eine Auslesung der DC Spannung am Eingang des Wechselrichters:
Im Bereich "# Selektiert spezifische Daten aus der json response":

voltage_dc = int(r['inverters'][0]['DC']['0']['Voltage']['v']) # DC-Spannung am WR Eingang auslesen

Und zuguter letzte die Anpassung der WR-Maximalleistung im Bereich "# Werte setzen"
if reachable:
#Abhängig von Akkuspannung wird die maximale WR-Leistung gesetzt

    if (voltage_dc >= voltage_borderhigh):      #Setze maximale Leistung für Spannung über 26 V
        maximum_wr = 540 
        print('WR-Leistung auf',maximum_wr,'gesetzt, da Akkuspannung:',voltage_dc, 'V', flush=True)
        
    if (voltage_borderlow < voltage_dc < voltage_borderhigh): # Setze maximale Leistung für Spannung von 24-26 V
        maximum_wr = 337
        print('WR-Leistung auf',maximum_wr,'gesetzt, da Akkuspannung:',voltage_dc, 'V', flush=True)
        
    if (voltage_dc < voltage_borderlow):#Setze maximale Leistung für Spannung unter 24 V
        maximum_wr = 10

Ab hier folgt der Code mit "# Setzen Sie den Grenzwert auf den höchsten Wert, wenn er über dem zulässigen Höchstwert liegt."

Die print-Befehle können natürlich noch entfernt werden wenn der Code bei euch läuft
Würde mich über Feedback freuen

Variable ´power` kann nicht definiert werden

Hallo zusammen,

ich bin gänzlich neu zu diesem ganzen Thema, habe bei allem Halbwissen, aber die nötige Ausdauer Probleme zu lösen.
Bei konnte in Zeile 41 die o.g. Variable nicht gefunden oder definiert werden. Nach langer Suche und viel ausprobieren kam dann das
folgende Script dank ChatGPT zu Tage, welches ohne Probleme funktioniert. Vielleicht kann mit diesen Anpassungen der ein oder andere etwas anfangen.

#!/usr/bin/env python3
import requests
import time
import sys
from requests.auth import HTTPBasicAuth

Diese Daten müssen angepasst werden:

serial = "114184500000" # Seriennummer des Hoymiles Wechselrichters
maximum_wr = 600 # Maximale Ausgabe des Wechselrichters
minimum_wr = 10# Minimale Ausgabe des Wechselrichters

dtu_ip = '192.168.0.59' # IP Adresse von OpenDTU
dtu_nutzer = 'admin' # OpenDTU Nutzername
dtu_passwort = 'openDTU42' # OpenDTU Passwort

shelly_ip = '192.168.0.230' # IP Adresse von Shelly 3EM

while True:
try:
# Nimmt Daten von der openDTU Rest-API und übersetzt sie in ein json-Format
r = requests.get(url=f'http://{dtu_ip}/api/livedata/status/inverters').json()

    # Selektiert spezifische Daten aus der json response
    inverters_data = r.get('inverters', [])
    if inverters_data:
        inverters_data = inverters_data[0]
        reachable = inverters_data.get('reachable', False)  # Ist DTU erreichbar?
        producing = int(inverters_data.get('producing', 0))  # Produziert der Wechselrichter etwas?
        altes_limit = int(inverters_data.get('limit_absolute', 0))  # Altes Limit
        power = r['total']['Power']['v'] if 'total' in r and 'Power' in r['total'] else 0  # Abgabe BKW AC in Watt
    else:
        raise KeyError("Inverters data not found")
    
except Exception as e:
    print('Fehler beim Abrufen der Daten von openDTU:', str(e))
    power = 0  # Setze power auf 0 im Fehlerfall
    
try:
    # Nimmt Daten von der Shelly 3EM Rest-API und übersetzt sie in ein json-Format
    phase_a = requests.get(f'http://{shelly_ip}/emeter/0', headers={'Content-Type': 'application/json'}).json()['power']
    phase_b = requests.get(f'http://{shelly_ip}/emeter/1', headers={'Content-Type': 'application/json'}).json()['power']
    phase_c = requests.get(f'http://{shelly_ip}/emeter/2', headers={'Content-Type': 'application/json'}).json()['power']
    grid_sum = phase_a + phase_b + phase_c  # Aktueller Bezug - rechnet alle Phasen zusammen
except Exception as e:
    print('Fehler beim Abrufen der Daten von Shelly 3EM:', str(e))

# Werte setzen
print(f'\nBezug: {round(grid_sum, 1)} W, Produktion: {round(power, 1)} W, Verbrauch: {round(grid_sum + power, 1)} W')
if reachable:
    setpoint = grid_sum + altes_limit - 5  # Neues Limit in Watt

    # Fange oberes Limit ab
    if setpoint > maximum_wr:
        setpoint = maximum_wr
        print(f'Setpoint auf Maximum: {maximum_wr} W')
    # Fange unteres Limit ab
    elif setpoint < minimum_wr:
        setpoint = minimum_wr
        print(f'Setpoint auf Minimum: {minimum_wr} W')
    else:
        print(
            f'Setpoint berechnet: {round(grid_sum, 1)} W + {round(altes_limit, 1)} W - 5 W = {round(setpoint, 1)} W')

    if setpoint != altes_limit:
        print(f'Setze Inverterlimit von {round(altes_limit, 1)} W auf {round(setpoint, 1)} W... ', end='')
        # Neues Limit setzen
        try:
            r = requests.post(
                url=f'http://{dtu_ip}/api/limit/config',
                data=f'data={{"serial":"{serial}", "limit_type":0, "limit_value":{setpoint}}}',
                auth=HTTPBasicAuth(dtu_nutzer, dtu_passwort),
                headers={'Content-Type': 'application/x-www-form-urlencoded'}
            )
            print(f'Konfiguration gesendet ({r.json()["type"]})')
        except Exception as e:
            print('Fehler beim Senden der Konfiguration:', str(e))

sys.stdout.flush()  # write out cached messages to stdout
time.sleep(5)  # wait

Feature Request: Variable für Offset

Hallo,

ich habe die gemessene Leistung des Shelly mit der angezeigten Leistung am Stromzähler verglichen und dabei hat sich gezeigt, dass der Shelly (bei mir) ca. 5W bei der Messung daneben liegt. Selbst wenn die Nulleinspeisung perfekt auf 0W (im Shelly) regelt beziehe ich 5 W aus dem Netz.

Ich habe dafür eine Variable mit dem Namen "offset" in meinem Code implementiert, bin allerdings kein Programmierer (es geht also sicherlich sauberer).

Aus den Zeilen:

wird weniger bezogen als maximum_wr dann neues Limit ausrechnen

    if (grid_sum + altes_limit) <= maximum_wr:

wird:

wird weniger bezogen als maximum_wr dann neues Limit ausrechnen

    gridandlimit = grid_sum + altes_limit + offset
    if (gridandlimit) <= maximum_wr:
  • Eine neue Variable "offset = eure Abweichung als Zahl in Watt " "im Bereich der anzupassenden Daten (ab Zeile 4)

Abschaltung von Hoymiles WR bei Signal über GPIO Pin

Hallo zusammen,

gleich vorweg, ich bin nicht wirklich gut im programmieren.
Ich kann mir zwar einiges zusammenreimen, aber verstehe noch längst nicht alles.

Vorweg möchte ich kurz erwähnen, dass ich den Code soweit angepasst habe, dass ich damit zwei Hoymiles HM400 Wechselrichter per Nulleinspeisung an einer Batterie betreiben kann.

Nun möchte ich gerne noch ein externes Signal via GPIO Pin einbinden um die Wechselrichter bei niedrigem Akkustand abzuschalten.
Die Pinabfrage habe ich bereits umgesetzt. Aktuell werden die Wechselrichter dabei auf den kleinsten Leistungswert (1W) gesetzt den die openDTU noch annimmt, was in der Realität leider ungefähr 8W Pro Wechselrichter entspricht.

Da es in der openDTU ja auch die Möglichkeit gibt, die Wechselrichter komplett aus bzw. anzuschalten, müsste dies doch auch über das python script machbar sein?

Leider habe ich hier keine Ahnung wie ich dies umsetzen könnte.
Hauptproblem ist hierbei der Abschalt- und Anschaltbefehl und wie ich diesen an die openDTU sende.
Vielleicht kann mir ja hier jemand von euch helfen?

Anbei mal meinen bisherigen Code als .txt im Anhang

Nulleinspeisung Script.txt

Nulleinspeisung mit Shelly 3EM Passwort Geschützt

Hallo,

Ich betrete hier nun komplettes "Neuland" für mich, und das in meinem alter :-)

Frage denke das es kein Problem für euch sein wird, wenn ich einen Shelly 3EM mit Passwort benutze funktioniert ja das nicht.
Hab mal temporär meinen Passwort Schutz aufgehoben alles ist wunderbar.
Gibt es eine Version die Passwörter unterstützt auch oder wird es sowas in Zukunft mal geben ?

danke für eure Hilfe,

Maybe some synergy with my project

Hi,
As I read about issues with the new OpenDTU version I would like to mention my little project where I am using the latest version of OpenDTU:
https://github.com/jaluebbe/balkonkraftwerk

Maybe you‘ll find some inspiration for this project.

Documentation is still mostly missing. To summarise:
Support for measurement via Shelly or myStrom plugs as well as OpenDTU. Optional Tibber Pulse.
Control of one or more Hoymiles inverters to feed power from a battery depending on demand of consumers.
Web interface for live data and daily reviews. Cloud setup to access own data via www using GitHub login for authentication.
IMG_6265
IMG_6262

"Fehler beim Abrufen der Daten von openDTU" bei 2 oder mehr WR und falscher Reihenfolge in Opendtu

Hallo,

ich habe 2 Wechselrichter im OpenDTU hinterlegt. Gesteuert werden soll nur der große WR. Soweit so gut.

Das Skript hat aber dann einmal funktioniert und dann nach ein paar Tagen wieder nicht mehr. Ich habe jetzt einiges ausprobiert und in den LOGS gesucht und bin nun auf den Fehler gekommen, warum das Skript immer den Minimum Wert verwendet hat ihn aber nicht mehr ändern konnte. Der Output sagte "Fehler beim Abrufen der Daten von openDTU". Ich hab mir dann den Output von http://192.168.XXX.YYY/api/livedata/status/inverters angesehen und gemerkt, dass das Skript immer die Daten des ersten opendtu Inverters im JSON abfragt. Dadurch bekam das File immer den Wert des kleineren WR und konnte dort auch den höheren Watt-Wert nicht mehr eintragen. Evtl. kann man das Skript so anpassen, dass es auf Basis der WR-ID das richtige JSON Element ausliest und dort den Wert einträgt. Aktuell scheint es mir als ob die Reihenfolge im JSON evtl. durch die Reihenfolge des Einschaltzeitpunktes definiert und das abundzu wechselt.

Alternativ habe ich schnell probiert den kleinen WR zu entfernen und wieder hinzuzufügen. Evtl. hilft auch diese Vorgehensweise bei der Reihung. Muss das die nächsten Tag noch beobachten.

LG

python script von Sn0w3y Nulleinspeisung

          > Moin hab die Consolenversion installiert 🙈 Sollte ich lieber auf die webbasierte wechseln? Irgendwie hat der Wechselrichter nur hochgeschaltet und nicht wieder runter aber es hat 2-3 mal eine automatische Regelung stattgefunden vom Script Vielen Dank schonmal

Achso, hast du gecheckt, ob die Werte im Log plausibel sind?

Originally posted by @Sn0w3y in #24 (comment)

Welche Logfiles meinst du ?

Ohne Raspi

Könnte das Script nich direkt auf dem ESP laufen? Der Raspi ist sehr teuer und verbraucht viel Strom!

limit_type=1 ist meines Erachtens falsch

limit_type=1 ist meines Erachtens falsch da dort der "relative" Wert gesetzt wird in %. Es müsste aber absolute gesetzt werden.
Kann das jemand verifizieren? Ich habe es bei mir jetzt angepasst und es funktioniert dann. (Mit abgewandelten Script speziell für Emlog)

Laut Quellcode:

AbsolutNonPersistent = 0x0000, // 0
RelativNonPersistent = 0x0001, // 1
AbsolutPersistent = 0x0100, // 256
RelativPersistent = 0x0101 // 257

Fehlermeldung NameError: name 'power' is not defined

Hallo,
als Neuling hab ich heute mein Rapsberry PI eingerichtet, so wie Roman Merz es in seinem Video beschrieben hat. Hab allerdings nicht den Spider3, sondern den Spider4 installiert, aber das sollte dem ja keinen Abbruch tun. Anschließend wurde das Script kopiert und die entsprechenden Änderungen (Seriennummer des WR und die IP-Adressen) gemacht.
Das Spript lässt sich nur mit dem Befehl "Zelle ausführen" starten, das Shelly EM3 wird korrekt ausgelesen, aber dann erscheint folgender Text:
_Python 3.9.2 (default, Mar 12 2021, 04:06:34)
Type "copyright", "credits" or "license" for more information.

IPython 7.20.0 -- An enhanced Interactive Python.

runcell(0, '/home/gardensteam/OpenDTU/nulleinspeisung.py')
Fehler beim Abrufen der Daten von openDTU
Traceback (most recent call last):

File "/home/gardensteam/OpenDTU/nulleinspeisung.py", line 41, in
print(f'\nBezug: {round(grid_sum, 1)} W, Produktion: {round(power, 1)} W, Verbrauch: {round(grid_sum + power, 1)} W')

NameError: name 'power' is not defined_

Über ein kleine Hilfestellung wäre ich Dankbar
LG Karlheinz

Update der berechneten Werte funzt nicht...

Ich habe HM 2250 mit openDTU (sichtbar und im Browser alles verstellbar) und kämpfe mit dem Skript.
Entweder scheint Skript zu funzen, aber die Änderung der Leistungswerte werden nicht übernommen.
Es wird ein "(warning) ausgegeben am Ende der Abfrage, wenn ich auf der Raspi-Console mitschaue.
Geräte sind auf 2m Sichtkontakt (openDTU und Raspi). Anbindung an Haus W-Lan wird mit 10.0.0.7(8 oder 11) stets durchgeführt.
Im Browser sind Shelly 3EM und openDTU immer ansprechbar.
Abfrage von Werten aus openDTU funzt, daher muss es sichtbar sein.
Ich habe die Werte mal fix mit 50 oder 100 gesetzt, falls relativ und absolut vertauscht sind, nope.
Anbei die Konsole mit den vergeblichen Versuchen, den Wert anzupassen.
Bin für jeden Hinweis sehr dankbar ;)
Skript-Warning

Error im Script?

Hallo,

super begeistert habe ich seit nun drei Tagen versucht, das Skriot ans laufen zu bekommen.
Von AhoyDTU auf OpenDTU etc...

Doch bekomme ich vom Python-Skript nur den Fehler:

simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Beim Start kommt folgendes:

====================== RESTART: /home/sense/Desktop/ne.py ======================
Traceback (most recent call last):
File "/home/sense/Desktop/ne.py", line 18, in
r = requests.get(url = f'http://{dtuIP}/api/livedata/status/inverters' ).json()
File "/usr/lib/python3/dist-packages/requests/models.py", line 900, in json
return complexjson.loads(self.text, **kwargs)
File "/usr/lib/python3/dist-packages/simplejson/init.py", line 525, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 370, in decode
obj, end = self.raw_decode(s)
File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 400, in raw_decode
return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Der DTU sieht folgendermaßen aus:

Hostname OpenDTU
v4.4.4
0.1.24
d508b41
New version available! Show changes!
Vbat power on reset
for APP CPU, reset by PRO CPU
18
0 days 20:58:33

Hostname OpenDTU
SDK Version v4.4.4
Config Version 0.1.24
Firmware Version / Git Hash d508b41
Firmware Update New version available! Show changes!
Reset Reason CPU 0 Vbat power on reset
Reset Reason CPU 1 for APP CPU, reset by PRO CPU
Config save count 18
Uptime 0 days 20:58:33

Muss der DTU die neuste FW bekommen?
Oder finde ich irgendwo das alte Skript?

Dankesehr.

LG,
Holger

Überlegungen zur Berechnung des zu setzenden Power Limits

Ich hab mir den Code mal angesehen und habe ein paar Verständnisfragen und nen Vorschlag wie man das Ganze vereinfachen könnte.
Bitte lasst mich wissen, was ihr dazu meint.

Was in Zeile 52 passieren soll ist mir nicht ganz klar.

  • Warum kann man die Leistung auf maximum_wr setzen wenn altes_limit >= maximum_wr ist?
  • Vom Wert grid_sum ist die erzeugte Energie (power) der Anlage bereits abgezogen. Um den tatsächlichen Verbrauch zu bestimmen, muss man beide Werte wieder addieren. Die Bedingung grid_sum >= maximum_wr ist also grundsätzlich verkehrt und würde anders als gewünscht unter Umständen doch etwas einspeisen.
  • Da "setpoint" auf jeden Fall 0 ist, ist die Bedingung setpoint >= maximum_wr nie erfüllt. (siehe Zeile 32)

Ich denke, dass man alles zwischen Zeile 51 und 64 durch Folgendes ersetzen kann.

aktuellerverbauch = grid_sum + power

if aktuellerverbauch >= maximum_wr:
    setpoint = maximum_wr
    print(f"setpoint auf Maximum ({maximum_wr}W) gesetzt.")
else:
    setpoint = aktuellerverbauch
    print(f"setpoint auf {aktuellerverbauch}W gesetzt.")

Richtiger limit_type?

Hallo zusammen,

ich bin mir nicht sicher, welche Funktion der Wert von limit_type hat. Ich habe gesehen, dass dort der Wert 0 oder auch 1 eingetragen wird. Ich vermute, es geht darum, ob der Wert temporär (bis zum Neustart) oder dauerhaft geschrieben werden soll. Leider finde ich dazu keine Dokumentation, aber in dem Nulleinspeise-Skript sollte unbedingt eine temporäre Limitierung erfolgen. Ich befürchte, dass der Wechselrichter das überhaupt nicht gut verträgt, wenn ständig neue Werte dauerhaft geschrieben werden. Hat jemand einen Link zur Dokumentation von limit_type?

Konkret geht es um diese Zeile:
data = f'data={{"serial":"{serial}", "limit_type":0, "limit_value":{setpoint}}}',

LG
Peter

Feature Request: zweiter Inverter

In Ticket #4 fragte @karrenbauer

wie bekomme ich Daten von WR2?

Hier die Antwort:

Die Daten des zweiten Inverters stehen schon in der Variable r drin.
Schau mal in die WebAPI von OpenDTU. Hier siehst Du die Struktur vom JSON. Die Inverter werden dort im "Array" Inverters[] nacheinander aufgeführt.
Du kannst also die Werte des zweiten Inverters auslesen, indem Du bei ['inverters'][0] statt der 0 eine 1 einträgst.

        reachable_2   = r['inverters'][1]['reachable'] # ist DTU erreichbar ?
        producing_2   = int(r['inverters'][1]['producing']) # produziert der Wechselrichter etwas ?
        altes_limit_2 = int(r['inverters'][1]['limit_absolute']) # wo war das alte Limit gesetzt
        power_dc _2   = r['inverters'][1]['AC']['0']['Power DC']['v']  # Lieferung DC vom Panel
        power_2      = r['inverters'][1]['AC']['0']['Power']['v'] # Abgabe BKW AC in **Watt**

Jetzt könnte zum Problem werden, wenn OpenDTU die Inverter nicht immer in der gleichen Reihenfolge liefert. Wenn Du die Inverter richtig benannt hast, sollte es allerdings kein Problem sein.
Den Namen sollte man so auslesen können:

        name_2 = r['inverters'][1]['name'] # Wie ist der Name?

Änderungen in aktuelle OpenDTU-Api

In der aktuellen OpenDTU-Api hat sich das json etwas geändert. DC/AC kam mit dazu.
Müsste angepasst werden:

power_dc    = r['inverters'][0]['DC']['0']['Power DC']['v']  # Lieferung DC vom Panel
power       = r['inverters'][0]['AC']['0']['Power']['v'] # Abgabe BKW AC in Watt

Feature Request: Leistungsreduzierung/Abschaltung bei Unterspannung

Hallo,

da eine Nulleinspeisung am meisten Sinn ergibt bei Betrieb des Balkonwechselrichters an einem Akku, möchte ich gerne eine Möglichkeit abfragen auf die PV-Spannung/Akkuspannung am DC-Eingang zuzugreifen und zu reagieren.

Eine Variante des Codes für Nutzung eines Speichers wäre klasse.

Vllt kann dort jemand aushelfen.

Meine Vorstellung der Funktion:

  • Abfrage der DC Spannung eines oder mehrerer Eingänge des WR via OpenDTU
  • Leistungsreduzierung bei Unterschreitung eines eingestellten Spannungswertes (1. Schritt)
  • Ausschalten des WR bei Unterschreitung eines eingestellten Spannungswertes (2. Schritt)

Leider kriege ich die Abfrage der beiden DC-Spannung am Eingang des Wechselrichters (HM-600) über den Service nicht hin.

Vllt hat ja jemand eine Idee.

Viele Grüße
Steffen

Script läuft nicht mit Shelly Pro 3EM

Hallo zusammen, in der irrigen Annahme es würde Laufen habe ich mir wegen der LAN Anbindung einen Shelly PRO 3EM besorgt.
Das Script ist auf dem Pi und läuft so lange ich die IP des Shelly nicht angebe. Versucht habe ich bereits:
curl http://192.168.1.53/emeter/1 -H "Accept: application/json"
und bekomme not fund zurück.
Kann es sein das die Abfragen sich geändert haben von emeter nach rpc/EMData
grafik

Update:
Die Abfrage im Pro funktioniert so nur weiß ich nicht wirklich wie das Script abgeändert werden müsste um die Daten zu verwerten.

wget -q -O - http://192.168.1.53/rpc/EM.GetStatus?id=0 {"id":0,"a_current":0.656,"a_voltage":231.2,"a_act_power":110.6,"a_aprt_power":151.6,"a_pf":-0.79,"b_current":0.438,"b_voltage":231.1,"b_act_power":49.5,"b_aprt_power":101.2,"b_pf":-0.66,"c_current":0.243,"c_voltage":231.2,"c_act_power":28.6,"c_aprt_power":56.2,"c_pf":-0.67,"n_current":null,"total_current":1.338,"total_act_power":188.716,"total_aprt_power":309.031, "user_calibrated_phase":[]}

Wehre sehr froh, wenn mir jemand helfen könnte

Corrections

The code doesn't work. I pass the code with corrections, although the comments are in Spanish. I have added the "exportar" variable, in case you want to export some energy to the grid. If you do not want to export anything, exportar=0

#!/usr/bin/env python3
import requests, time, sys
from requests.auth import HTTPBasicAuth

Ajustar estos datos

serial = "xxxxxxxxxxxxxxx" # numero serie microinversor
maximum_wr = 2000 # Máxima salida del microinversor
minimum_wr = 100 # Minima salida del microinversor
dtu_ip = 'xxxxxxxxxxxx' # IP Adresse OpenDTU
basicdtu = HTTPBasicAuth('admin', 'xxxxxxxx')
dtu_user = 'admin' # usuario openDTU
dtu_pass = 'xxxxxxxxxxx' # OpenDTU Password
basicShelly = HTTPBasicAuth('admin', 'xxxxxxx')
shelly_ip = 'xxxxxxxxxx' # IP Adresse Shelly 3EM
grid= 0
power = 0
reachable = 0
exportar = 1500
valor_seguridad = 0
while True:
try:
# Toma de datos de la API REST de openDTU y los convierte en json-Format
r = requests.get(url = f'http://{dtu_ip}/api/livedata/status/inverters', headers={'Content-Type': 'application/json'},auth=basicdtu).json()
# Selecciona los datos especificos de la respuesta json
reachable = r['inverters'][0]['reachable'] # es accesible la DTU?
producing = int(r['inverters'][0]['producing']) # El microinversor está produciendo?
viejo_limite = int(r['inverters'][0]['limit_absolute']) # Viejo límite
power = r['total']['Power']['v'] # Entrega de corriente alterna en W
except:
print('Error al recuperar datos de openDTU')
try:
# Toma datos de Shelly 3EM Rest API y los traduce a formato json
grid = requests.get(f'http://{shelly_ip}/emeter/2', headers={'Content-Type': 'application/json'},auth=basicShelly).json()['power']
except:
print('Error al recuperar datos de Shelly 3EM')
# Establecer valores
print(f'\nRed: {round(grid, 1)} W, Produccion: {round(power, 1)} W, Casa: {round(grid + power, 1)} W')
if reachable:
setpoint = grid + viejo_limite - valor_seguridad + exportar # Nuevos límites en W
# Límite superior de captura
if setpoint > maximum_wr:
setpoint = maximum_wr
print(f'Estableciendo Maximo: {maximum_wr} W')
# Límite inferior de captura
elif setpoint < minimum_wr:
setpoint = minimum_wr
print(f'Estableciendo Minimo: {minimum_wr} W')
else:
print(f'Ajuste Calculado: {round(grid, 1)} W + {round(viejo_limite, 1)} W - valor_seguridad W = {round(setpoint, 1)} W')
if setpoint != viejo_limite:
print(f'Establecer el límite del inversor de {round(viejo_limite, 1)} W a {round(setpoint, 1)} W... ', end='')
# Establecer un nuevo límite
try:
r = requests.post(
url = f'http://{dtu_ip}/api/limit/config',
data = f'data={{"serial":"{serial}", "limit_type":0, "limit_value":{setpoint}}}',
auth = HTTPBasicAuth(dtu_user, dtu_pass),
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
)
print(f'Configuracion enviada ({r.json()["type"]})')
except:
print('Error al enviar la configuracion')
sys.stdout.flush() # escribir mensajes almacenados en caché en stdout
time.sleep(5) # esperar

Hoymiles sehr träge

Die Lösung ist ganz nett. Leider sind die Hoymiles sehr sehr träge. An dieser Stelle müsste sich diese Lösung noch verbessern.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.