mirror of
https://github.com/denshooter/nulleinspeisung.git
synced 2026-01-21 12:43:03 +01:00
add Dockerfile and python script
This commit is contained in:
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
||||
# Verwenden Sie ein offizielles Python-Image als Basis
|
||||
FROM python:3.12-alpine
|
||||
|
||||
# Arbeitsverzeichnis im Container festlegen
|
||||
WORKDIR /app
|
||||
|
||||
RUN pip install --upgrade pip
|
||||
|
||||
# Installieren Sie die benötigten Python-Bibliotheken
|
||||
RUN pip install requests
|
||||
|
||||
# Führen Sie das Python-Skript aus, wenn der Container gestartet wird
|
||||
CMD ["python", "/app/Nulleinspeisung.py"]
|
||||
|
||||
90
Nulleinspeisung.py
Normal file
90
Nulleinspeisung.py
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Nulleinspeisung Control Script for Hoymiles Wechselrichter with OpenDTU and Shelly3EM Pro
|
||||
Originally forked from: https://github.com/Selbstbau-PV/Selbstbau-PV-Hoymiles-nulleinspeisung-mit-OpenDTU-und-Shelly3EM
|
||||
|
||||
This script is a modified version, tailored for specific use-cases and enhancements.
|
||||
All original work and its credits belong to the authors of the referenced repository.
|
||||
"""
|
||||
|
||||
import requests, time, sys
|
||||
from requests.auth import HTTPBasicAuth
|
||||
|
||||
# User Configuration: Replace with your specific details
|
||||
serial = "<SERIAL_NUMBER>" # Serial number of Hoymiles Wechselrichter
|
||||
maximum_wr = <MAX_OUTPUT> # Maximum output of the Wechselrichter (Watts)
|
||||
minimum_wr = <MIN_OUTPUT> # Minimum output of the Wechselrichter (Watts)
|
||||
|
||||
# OpenDTU Configuration: Replace with your OpenDTU details
|
||||
dtu_ip = '<OPEN_DTU_IP>'
|
||||
dtu_user = '<OPEN_DTU_USERNAME>'
|
||||
dtu_password = '<OPEN_DTU_PASSWORD>'
|
||||
|
||||
# Shelly Device Configuration: Replace with your Shelly 3EM Pro IP
|
||||
shelly_ip = '<SHELLY_IP>'
|
||||
|
||||
while True:
|
||||
time.sleep(1) # Sleep for 1 second
|
||||
|
||||
try:
|
||||
# Retrieve data from OpenDTU REST API and parse it into JSON format
|
||||
dtu_response = requests.get(f'http://{dtu_ip}/api/livedata/status/inverters').json()
|
||||
|
||||
# Extract specific data from the JSON response
|
||||
reachable = dtu_response['inverters'][0]['reachable'] # Is DTU reachable?
|
||||
producing = int(dtu_response['inverters'][0]['producing']) # Is the Wechselrichter producing?
|
||||
old_limit = int(dtu_response['inverters'][0]['limit_absolute']) # Old limit
|
||||
power_dc = dtu_response['inverters'][0]['AC']['0']['Power DC']['v'] # DC power from panels
|
||||
power_ac = dtu_response['inverters'][0]['AC']['0']['Power']['v'] # AC power output to grid (Watts)
|
||||
except:
|
||||
print('Error retrieving data from OpenDTU')
|
||||
|
||||
try:
|
||||
# Retrieve data from Shelly 3EM REST API
|
||||
shelly_response = requests.get(f'http://{shelly_ip}/rpc/Shelly.GetStatus')
|
||||
|
||||
if shelly_response.status_code == 200:
|
||||
shelly_data = shelly_response.json()
|
||||
total_act_power = shelly_data['em:0']['total_act_power'] # Total active power
|
||||
else:
|
||||
print(f"Shelly request failed with status code: {shelly_response.status_code}")
|
||||
|
||||
grid_consumption = total_act_power - 100 # Total grid consumption (all phases)
|
||||
except:
|
||||
print('Error retrieving data from Shelly Pro3EM')
|
||||
|
||||
# Calculate and display power values
|
||||
print(f'\nGrid Consumption: {round(grid_consumption, 1)} W, Production: {round(power_ac, 1)} W, Total Consumption: {round(grid_consumption + power_ac, 1)} W')
|
||||
|
||||
if reachable:
|
||||
# Calculate new limit in Watts
|
||||
new_limit = grid_consumption + old_limit - 5
|
||||
|
||||
# Check and adjust the new limit against maximum and minimum thresholds
|
||||
if new_limit > maximum_wr:
|
||||
new_limit = maximum_wr
|
||||
print(f'Setpoint to maximum: {maximum_wr} W')
|
||||
elif new_limit < minimum_wr:
|
||||
new_limit = minimum_wr
|
||||
print(f'Setpoint to minimum: {minimum_wr} W')
|
||||
else:
|
||||
print(f'Calculated Setpoint: {round(grid_consumption, 1)} W + {round(old_limit, 1)} W - 5 W = {round(new_limit, 1)} W')
|
||||
|
||||
# Update the inverter limit if it has changed
|
||||
if new_limit != old_limit:
|
||||
print(f'Setting inverter limit from {round(old_limit, 1)} W to {round(new_limit, 1)} W... ', end='')
|
||||
try:
|
||||
# Send the new limit to the inverter
|
||||
dtu_limit_response = requests.post(
|
||||
url=f'http://{dtu_ip}/api/limit/config',
|
||||
data=f'data={{"serial":"{serial}", "limit_type":0, "limit_value":{new_limit}}}',
|
||||
auth=HTTPBasicAuth(dtu_user, dtu_password),
|
||||
headers={'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
)
|
||||
print(f'Configuration sent ({dtu_limit_response.json()["type"]})')
|
||||
except:
|
||||
print('Error sending configuration')
|
||||
|
||||
sys.stdout.flush() # Flush cached messages to stdout
|
||||
time.sleep(5) # Sleep for 5 seconds
|
||||
Reference in New Issue
Block a user