Selbstbau-PV / Selbstbau-PV-Hoymiles-nulleinspeisung-mit-OpenDTU-und-Shelly3EM

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.
61 stars 24 forks source link

Variable ´power` kann nicht definiert werden #26

Open Nutmeg0082 opened 4 months ago

Nutmeg0082 commented 4 months ago

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
Selbstbau-PV commented 4 months ago

The script works only with opnedtu lower than V24.1.26

flofresser commented 3 months ago

I think i have fixed the problem so the script should work with the new OpenDTU version

you only have to change some little things in the code:

you will see the changes in red in the attached picture

Script_changes

stravanti commented 3 months ago

hi, can you share which openDTU version you have used? For me this change in the script does not help. btw, I am running the version [v24.3.31] thanks Matthias

flofresser commented 3 months ago

At the moment i use V24.3.22 of openDTU on Battery

stravanti commented 2 months ago

Thanks for the info. After downgrade to this version it works again! Will not do any further changes.