used solaredge api for start values
This commit is contained in:
parent
0c511cacd0
commit
1b617a1794
13
constants.py
13
constants.py
@ -5,3 +5,16 @@ mqtt_huidig_zon_topic = "HuidigZonWatt"
|
|||||||
mqtt_huidig_zonA_topic = "HuidigZonA"
|
mqtt_huidig_zonA_topic = "HuidigZonA"
|
||||||
mqtt_dag_zon_topic = "DagZonWh"
|
mqtt_dag_zon_topic = "DagZonWh"
|
||||||
mqtt_broker_ip = "192.168.200.26"
|
mqtt_broker_ip = "192.168.200.26"
|
||||||
|
solaredge_api_key = "XRUZJIR5AHJCDCOPZLYPC1XMR2W6XRBI"
|
||||||
|
solaredge_site_id = 457767
|
||||||
|
solaredge_monitoring_api_url = f'https://monitoringapi.solaredge.com/site/{solaredge_site_id}/energy'
|
||||||
|
linux_root = r'/mnt/ftpserver/solaredgedata'
|
||||||
|
windows_root = r'd:\temp\solaredgedata'
|
||||||
|
daily_data_file = r'dailysolaredgedata.csv'
|
||||||
|
monthly_data_file = r'monthlysolaredgedata.csv'
|
||||||
|
yearly_data_file = r'yearlysolaredgedata.csv'
|
||||||
|
|
||||||
|
# --- Configuratie ---
|
||||||
|
INVERTER_IP = "192.168.200.65"
|
||||||
|
INVERTER_PORT = 502 # Probeer 1502 als 502 niet werkt
|
||||||
|
TOPIC_PREFIX = "solaredge"
|
||||||
|
|||||||
68
service_helpers.py
Normal file
68
service_helpers.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import csv
|
||||||
|
import os
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from paho.mqtt import client as mqtt
|
||||||
|
|
||||||
|
from constants import solaredge_api_key, solaredge_monitoring_api_url, mqtt_username, mqtt_password, mqtt_broker_ip
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_dir(file_name):
|
||||||
|
""" Check/create the folder implied by the specified file.
|
||||||
|
|
||||||
|
If the directory does not exist it will be created.
|
||||||
|
:param file_name: basestring
|
||||||
|
"""
|
||||||
|
d = os.path.dirname(file_name)
|
||||||
|
if not os.path.exists(d):
|
||||||
|
os.makedirs(d)
|
||||||
|
|
||||||
|
|
||||||
|
def save_data_to_csv(file_name, data):
|
||||||
|
ensure_dir(file_name)
|
||||||
|
with open(file_name, mode='w', newline='') as file:
|
||||||
|
writer = csv.writer(file)
|
||||||
|
# Kolomkoppen (headers)
|
||||||
|
writer.writerow(['Datum', 'Energie (Wh)', 'Energie (kWh)'])
|
||||||
|
for entry in data:
|
||||||
|
datum = entry['date']
|
||||||
|
waarde_wh = entry.get('value', 0)
|
||||||
|
if waarde_wh is not None:
|
||||||
|
waarde_kwh = waarde_wh / 1000
|
||||||
|
writer.writerow([datum, waarde_wh, waarde_kwh])
|
||||||
|
|
||||||
|
|
||||||
|
def get_energy_totals(time_unit, start_date, end_date):
|
||||||
|
params = {
|
||||||
|
'api_key': solaredge_api_key,
|
||||||
|
'startDate': start_date,
|
||||||
|
'endDate': end_date,
|
||||||
|
'timeUnit': time_unit # Opties: DAY, MONTH, YEAR
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.get(solaredge_monitoring_api_url, params=params)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
full_json = response.json()
|
||||||
|
# Stap voor stap door de JSON structuur graven
|
||||||
|
energy_obj = full_json.get('energy', {})
|
||||||
|
values_list = energy_obj.get('values', [])
|
||||||
|
return values_list
|
||||||
|
|
||||||
|
|
||||||
|
def connect_mqtt():
|
||||||
|
c = mqtt.Client()
|
||||||
|
c.username_pw_set(mqtt_username, mqtt_password)
|
||||||
|
try:
|
||||||
|
# Stel in: probeer elke 1 tot 120 seconden opnieuw te verbinden
|
||||||
|
c.reconnect_delay_set(min_delay=1, max_delay=120)
|
||||||
|
c.connect(mqtt_broker_ip, 1883, 60)
|
||||||
|
c.loop_start() # Draait op de achtergrond en regelt de automatische reconnect
|
||||||
|
return c
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"MQTT Verbinding mislukt: {e}")
|
||||||
|
return None
|
||||||
@ -1,74 +1,146 @@
|
|||||||
import sunspec2.modbus.client as client
|
import sunspec2.modbus.client as client
|
||||||
import paho.mqtt.client as mqtt
|
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
from constants import mqtt_username, mqtt_password
|
from constants import (
|
||||||
|
INVERTER_IP, INVERTER_PORT, TOPIC_PREFIX, windows_root, linux_root,
|
||||||
# --- Configuratie ---
|
daily_data_file, monthly_data_file, yearly_data_file
|
||||||
INVERTER_IP = "192.168.200.65"
|
)
|
||||||
INVERTER_PORT = 502 # Probeer 1502 als 502 niet werkt
|
from service_helpers import save_data_to_csv, get_energy_totals, connect_mqtt
|
||||||
MQTT_BROKER = "10.0.0.3"
|
|
||||||
TOPIC_PREFIX = "solaredge/inverter"
|
|
||||||
|
|
||||||
# Logging instellen voor foutopsporing
|
# Logging instellen voor foutopsporing
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger("SolarEdgeService")
|
logger = logging.getLogger("SolarEdgeService")
|
||||||
|
|
||||||
|
|
||||||
def connect_mqtt():
|
class SolarEdgeReader:
|
||||||
c = mqtt.Client()
|
def __init__(self):
|
||||||
c.username_pw_set(mqtt_username, mqtt_password)
|
self.daily_data_path = None
|
||||||
try:
|
self.monthly_data_path = None
|
||||||
c.connect(MQTT_BROKER, 1883, 60)
|
self.yearly_data_path = None
|
||||||
return c
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"MQTT Verbinding mislukt: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def read_and_publish():
|
def set_data_paths(self):
|
||||||
inv_device = None
|
jaar_str = datetime.now().strftime('%Y')
|
||||||
mqtt_client = connect_mqtt()
|
if os.name == 'nt':
|
||||||
|
data_root = f"{windows_root}\\{jaar_str}"
|
||||||
|
else:
|
||||||
|
data_root = f"{linux_root}/{jaar_str}"
|
||||||
|
|
||||||
while True:
|
self.daily_data_path = os.path.join(data_root, daily_data_file)
|
||||||
|
self.monthly_data_path = os.path.join(data_root, monthly_data_file)
|
||||||
|
self.yearly_data_path = os.path.join(data_root, yearly_data_file)
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_energy_totals_from_solaredge_portal(self):
|
||||||
|
daily_data, monthly_data, yearly_data = None, None, None
|
||||||
try:
|
try:
|
||||||
# 1. Verbind met Inverter als dat nog niet is gebeurd
|
vandaag = datetime.now().strftime('%Y-%m-%d')
|
||||||
if inv_device is None:
|
start_maand = datetime.now().strftime('%Y-%m-01')
|
||||||
logger.info("Verbinden met SolarEdge...")
|
start_jaar = datetime.now().strftime('%Y-01-01')
|
||||||
inv_device = client.SunSpecModbusClientDeviceTCP(
|
start_install = datetime.now().strftime('2017-01-01')
|
||||||
slave_id=1, ipaddr=INVERTER_IP, ipport=INVERTER_PORT, timeout=5
|
daily_data = get_energy_totals('DAY', start_jaar, vandaag)
|
||||||
)
|
if daily_data is not None:
|
||||||
inv_device.scan()
|
save_data_to_csv(self.daily_data_path, daily_data)
|
||||||
|
|
||||||
# 2. Data lezen
|
monthly_data = get_energy_totals('MONTH', start_install, vandaag)
|
||||||
# Model 101/103 bevatten de inverter data
|
if monthly_data is not None:
|
||||||
# We zoeken dynamisch naar het juiste model
|
save_data_to_csv(self.monthly_data_path, monthly_data)
|
||||||
itf = inv_device.inverter[0]
|
|
||||||
itf.read()
|
|
||||||
|
|
||||||
power_w = itf.W.get_value()
|
|
||||||
energy_total = itf.WH.get_value()
|
|
||||||
status = itf.St.get_value()
|
|
||||||
|
|
||||||
# 3. Publiceren naar MQTT
|
|
||||||
if mqtt_client:
|
|
||||||
mqtt_client.publish(f"{TOPIC_PREFIX}/power", power_w)
|
|
||||||
mqtt_client.publish(f"{TOPIC_PREFIX}/total_energy", energy_total)
|
|
||||||
mqtt_client.publish(f"{TOPIC_PREFIX}/status", status)
|
|
||||||
logger.info(f"Update verzonden: {power_w}W total_energy: {energy_total}Wh status: {status}")
|
|
||||||
else:
|
|
||||||
mqtt_client = connect_mqtt() # Herstel MQTT verbinding
|
|
||||||
|
|
||||||
|
yearly_data = get_energy_totals('YEAR', start_install, vandaag)
|
||||||
|
if yearly_data is not None:
|
||||||
|
save_data_to_csv(self.yearly_data_path, yearly_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Fout tijdens uitlezen: {e}")
|
logger.error(f"Fout retrieving solaredge totals: {e}")
|
||||||
# Forceer nieuwe verbinding bij de volgende poging
|
|
||||||
if inv_device:
|
return daily_data, monthly_data, yearly_data
|
||||||
inv_device.close()
|
|
||||||
inv_device = None
|
def read_and_publish(self):
|
||||||
time.sleep(5) # Korte pauze bij fout om CPU te sparen
|
inv_device = None
|
||||||
|
mqtt_client = connect_mqtt() # runs a thread in the background to call loop() automatically.
|
||||||
|
# This frees up the main thread for other work that may be blocking.
|
||||||
|
# This call also handles reconnecting to the broker.
|
||||||
|
# Call loop_stop() to stop the background thread.
|
||||||
|
start_energy_total_wh = None
|
||||||
|
start_dag = None
|
||||||
|
start_maand = None
|
||||||
|
start_jaar = None
|
||||||
|
current_date = datetime.now()
|
||||||
|
prev_date = None
|
||||||
|
dag_total = 0
|
||||||
|
month_total = 0
|
||||||
|
year_total = 0
|
||||||
|
laatste_check = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
huidige_datum = datetime.now().date()
|
||||||
|
day_changed = laatste_check is None or huidige_datum > laatste_check
|
||||||
|
# 1. Verbind met Inverter als dat nog niet is gebeurd
|
||||||
|
if inv_device is None:
|
||||||
|
logger.info("Verbinden met SolarEdge...")
|
||||||
|
inv_device = client.SunSpecModbusClientDeviceTCP(
|
||||||
|
slave_id=1, ipaddr=INVERTER_IP, ipport=INVERTER_PORT, timeout=5
|
||||||
|
)
|
||||||
|
inv_device.scan()
|
||||||
|
|
||||||
|
# 2. Data lezen
|
||||||
|
# Model 101/103 bevatten de inverter data
|
||||||
|
# We zoeken dynamisch naar het juiste model
|
||||||
|
itf = inv_device.inverter_single_phase[0]
|
||||||
|
itf.read()
|
||||||
|
# odict_keys(['ID', 'L', 'A', 'AphA', 'AphB', 'AphC', 'A_SF', 'PPVphAB', 'PPVphBC', 'PPVphCA', 'PhVphA', 'PhVphB', 'PhVphC', 'V_SF', 'W', 'W_SF', 'Hz', 'Hz_SF', 'VA', 'VA_SF', 'VAr', 'VAr_SF', 'PF', 'PF_SF', 'WH', 'WH_SF', 'DCA', 'DCA_SF', 'DCV', 'DCV_SF', 'DCW', 'DCW_SF', 'TmpCab', 'TmpSnk', 'TmpTrns', 'TmpOt', 'Tmp_SF', 'St', 'StVnd', 'Evt1', 'Evt2', 'EvtVnd1', 'EvtVnd2', 'EvtVnd3', 'EvtVnd4'])
|
||||||
|
power_w = itf.W.get_value() / 100.0
|
||||||
|
energy_total_wh = itf.WH.get_value() /100.0
|
||||||
|
status = itf.St.get_value()
|
||||||
|
if start_energy_total_wh is None or day_changed:
|
||||||
|
self.set_data_paths()
|
||||||
|
start_energy_total_wh = energy_total_wh
|
||||||
|
logger.info("Retrieving totals from solaredge api")
|
||||||
|
daily_data, monthly_data, yearly_data = self.get_current_energy_totals_from_solaredge_portal()
|
||||||
|
start_dag = daily_data[-1].get('value', 0)
|
||||||
|
start_maand = monthly_data[-1].get('value', 0)
|
||||||
|
start_jaar = yearly_data[-1].get('value', 0)
|
||||||
|
dag_total = start_dag
|
||||||
|
month_total = start_maand
|
||||||
|
year_total = start_jaar
|
||||||
|
laatste_check = huidige_datum
|
||||||
|
else:
|
||||||
|
delta_energy_total_wh_dag = energy_total_wh - start_energy_total_wh
|
||||||
|
dag_total = start_dag + delta_energy_total_wh_dag
|
||||||
|
month_total = start_maand + delta_energy_total_wh_dag
|
||||||
|
year_total = start_jaar + delta_energy_total_wh_dag
|
||||||
|
logger.info(f"dag_totaal={dag_total/1000.0}kWh, month_total={month_total/1000.0}kWh, year_total={year_total/1000.0}kWh")
|
||||||
|
|
||||||
|
# 3. Publiceren naar MQTT
|
||||||
|
if mqtt_client:
|
||||||
|
mqtt_client.publish(f"{TOPIC_PREFIX}/power", power_w)
|
||||||
|
mqtt_client.publish(f"{TOPIC_PREFIX}/total_day_kwh", dag_total/1000.0)
|
||||||
|
mqtt_client.publish(f"{TOPIC_PREFIX}/total_month_kwh", month_total / 1000.0)
|
||||||
|
mqtt_client.publish(f"{TOPIC_PREFIX}/total_year_kwh", year_total / 1000.0)
|
||||||
|
mqtt_client.publish(f"{TOPIC_PREFIX}/total_energy_kWh", energy_total_wh/1000.0)
|
||||||
|
mqtt_client.publish(f"{TOPIC_PREFIX}/status", status)
|
||||||
|
logger.info(f"Update verzonden: Current power: {power_w}W total_day_kwh: {dag_total/1000.0}kWh status: {status}")
|
||||||
|
else:
|
||||||
|
mqtt_client = connect_mqtt() # Herstel MQTT verbinding
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Fout tijdens uitlezen: {e}")
|
||||||
|
# Forceer nieuwe verbinding bij de volgende poging
|
||||||
|
if inv_device:
|
||||||
|
inv_device.close()
|
||||||
|
inv_device = None
|
||||||
|
time.sleep(5) # Korte pauze bij fout om CPU te sparen
|
||||||
|
|
||||||
|
time.sleep(15) # Wacht 15 seconden voor de volgende update
|
||||||
|
finally:
|
||||||
|
if mqtt_client:
|
||||||
|
mqtt_client.loop_stop()
|
||||||
|
|
||||||
time.sleep(15) # Wacht 15 seconden voor de volgende update
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
read_and_publish()
|
reader = SolarEdgeReader()
|
||||||
|
reader.read_and_publish()
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user