in ,

Balkonkraftwerk Datenaufbereitung – Teil 1

Einleitung

Unser neues Projekt ist ein kleines Balkonkraftwerk: Eine Firma wurde für die Dachinstallation sowie den Anschluss des Wechselrichters an die Hauselektrik beauftragt – damit alles fachgerecht erledigt wird.

Die Installationsfirma wird dann auch ein Prüfprotokoll erstellen und das Balkonkraftwerk beim Netzbetreiber für uns anmelden.

Verwendete Hardware:

  • 2 Solarmodule mit 450Wp (entsprechen 0,9 kWp)
  • Ausrichtung: Ost/West, jeweils 1 Modul auf einer Dachschräge von ca. 30°
    (auf der Südseite ist eine Installation der Module leider nicht möglich)
  • Wechselrichter mit 0,8kW (ist ausreichend bei Ost/West)
  • DTU (DataTransferUnit, Datenübertragungseinheit) für die Kommunikation zwischen Wechselrichter und WLAN (und weiter in die Cloud)

Da wir bereits die Datenaufbereitung für eine PV-Anlage mit ähnlichen Daten (Ost/West mit 8,8kWp an 8kW Wechselrichter) gemacht haben, sollten die Werte des Balkonkraftwerks ~ 1/10 der PV-Anlage entsprechen.

Hier nochmals die Links zu unseren PV-Anlagen Blogs:

https://www.bi4you.org/artikel/photovoltaikanlage-daten-visualisieren-teil-1-daten-importieren/

https://www.bi4you.org/artikel/photovoltaikanlage-daten-visualisieren-teil-2-superset/

 

Was ist geplant?

Im Vergleich zu der PV-Anlage haben wir keine Übersicht über den Verbrauch unseres selbst erzeugten Stroms, bekommen auch keine Einspeisevergütung – können aber für die Produktion ein paar Charts basteln.

Dazu könnten wir uns über die Webseite des Wechselrichterherstellers die täglichen Werte exportieren – diese sind alle 15min, allerdings müssten wir das für jeden Tag einzeln machen.

Alternativ könnten wir auch monatlich die Tageswerte exportieren (so wie bei der PV-Anlage) – wir haben aber im Internet eine nette Alternative gefunden: das Auslesen der Wechselrichterdaten direkt über WLAN von der DTU.

Verwenden werden wir das Python-Tool https://github.com/suaveolent/hoymiles-wifi

Die Werte werden wir in unsere MariaDB speichern, in unsere DorisDB synchronisieren, Views erstellen und mit Superset Charts und ein Dashboard erstellen.

 

Python Environment erstellen

Nachdem die Installationsfirma die Errichtung und Einrichtung abgeschlossen hat, können wir uns unsere Daten über die Handy-App anschauen.

D.h. wir müssten jetzt unsere DTU auch im internen Netzwerk erreichen können.

Über unseren Router können wir die IP-Adresse raussuchen und auf unserem Server einen ping ausprobieren:

Die DTU ist also erreichbar, also können wir uns ein Python Environment für das Hoymiles-Tool anlegen:

  • python3 -m venv hoymiles
  • . hoymiles/bin/activate
  • pip install –upgrade setuptools pip
  • pip install hoymiles-wifi
  • deactivate

Unsere Werte können wir mit get-real-data-new auslesen:

  • ~/hoymiles/bin/hoymiles-wifi –host 192.168.42.72 get-real-data-new |grep -v serial_number

Get-real-data-new Response:

timestamp: 1760010955
ap: 1
firmware_version: 1
sgs_data {
firmware_version: 1
voltage: 2299
frequency: 5000
active_power: 1155
reactive_power: -150
current: 53
power_factor: 64545
temperature: 180
warning_number: 148
link_status: 1
modulation_index_signal: -47
}


pv_data {
port_number: 1
voltage: 327
current: 193
power: 632
energy_total: 26300
energy_daily: 175
error_code: 50986752
}


pv_data {
port_number: 2
voltage: 327
current: 179
power: 587
energy_total: 29278
energy_daily: 175
error_code: 50986752
}

sgs_data: Zeigt uns die aktuellen Wechselrichter-Daten und unsere AC-Werte

pv_data: Zeigt uns die aktuellen DC-Daten der Module (port_number 1 = Ost, port_number 2 = West) sowie die Tages-/Gesamtwerte

Datenaufbereitung und Import in unsere MariaDB

Wir werden den Großteil des Outputs in unsere MariaDB schreiben, über die einzelnen Werte und deren Format machen wir uns dann beim Einstellen unserer View Gedanken.

Sollten wir Werte nicht verwenden oder benötigen, können wir sie trotzdem wegspeichern – bei unseren Datenmengen sollte das kein Problem darstellen.

Unsere MariaDB Tabelle nennen wir hoymiles_dtu und legen sie mit folgenden Feldern an:


CREATE TABLE bme280.hoymiles_dtu (
Uhrzeit datetime,
Temperatur int(11) NULL,
Frequenz int(11) NULL,
Spannung int(11) NULL,
Strom int(11) NULL,
Leistung int(11) NULL,
Blindleistung int(11) NULL,
Leistungsfaktor int(11) NULL,
Ost_Spannung int(11) NULL,
Ost_Strom int(11) NULL,
Ost_Leistung int(11) NULL,
Ost_Energie_Tag int(11) NULL,
Ost_Energie_Gesamt int(11) NULL,
West_Spannung int(11) NULL,
West_Strom int(11) NULL,
West_Leistung int(11) NULL,
West_Energie_Tag int(11) NULL,
West_Energie_Gesamt int(11) NULL,
Message varchar(255) NULL,
PRIMARY KEY (Uhrzeit)
);

Skript: get_hoymiles_dtu.sh

Als Erstes definieren wir temporären Dateien für den Output des Python Skripts sowie die csv Datei für unseren Import.

Wir schreiben sie nach /tmp, nach einem reboot sind sie also weg – was uns hier aber nicht stört, da sie immer überschrieben werden.


#!/bin/bash
output_file=“/tmp/hoymiles.output“;
output_file_csv=“/tmp/hoymiles_dtu.csv“;

Das aktuelle Datum und unsere MariaDB Daten hinterlegen wir als Variablen.

DATETIME=`date +“%Y-%m-%d %H:%M“`
MARIADB_HOST=“localhost“
MARIADB_USER=“bme280″
MARIADB_PW=“bme280″
MARIADB_DB=“bme280″

Die IP unserer DTU und den Pfad zum Python Skript legen wir ebenfalls als Variablen an.

HOYMILES_IP=“192.168.42.72″;
HOYMILES_PYTHON=“/home/alarm/hoymiles/bin/hoymiles-wifi“

Mit der Funktion GetHoymilesHeartbeat prüfen wir, ob die DTU erreichbar ist – dazu können wir den Parameter heartbeat verwenden.

Sollte die DTU nicht erreichbar sein, warten wir 30 Sekunden und probieren es nochmal.

function GetHoymilesHeartbeat {
IP=$1;
LOOP=0;
HoymilesError=“No response or unable to retrieve response for heartbeat“;
HoymilesHeartbeat=`${HOYMILES_PYTHON} –host ${IP} heartbeat`;
while [[ ${HoymilesHeartbeat} == ${HoymilesError} ]]
do
if [[ ${LOOP} -eq 3 ]]
then
echo „No Connection to Host“;
fi
let LOOP++;
sleep 30;
HoymilesHeartbeat=`${HOYMILES_PYTHON} –host ${IP} heartbeat`;
done
echo „Connection Alive“
}

Wir lesen uns in die Variable HoymilesHeartbeat die Rückanwort der Funktion GetHoymilesHeartbeat ein.

Wenn wir eine Verbindung zur DTU haben („Connection Alive“), fragen wir die Daten von der DTU ab.

Sollte wir keine Verbindung zur DTU haben, schreiben wir in unsere MariaDB Felder Uhrzeit/Message unsere Uhrzeit und die Info über keine Verbindung.

Die restlichen Werte bleiben leer und werden vor dem Import noch durch \N ersetzt, damit wir NULL-Werte in unserer DB haben.

read HoymilesHeartbeat < <(GetHoymilesHeartbeat „${HOYMILES_IP}“);
if [[ ${HoymilesHeartbeat} == „Connection Alive“ ]]
then
${HOYMILES_PYTHON} –host ${HOYMILES_IP} get-real-data-new > ${output_file};
else
message=“No Wifi-Connection to Hoymiles DTU“;
echo „${DATETIME};;;;;;;;;;;;;;;;;;${message}“ | sed ’s/;;/;\\N;/g‘ | sed ’s/;;/;\\N;/g‘ |sed ’s/;$/;\\N/g‘ > ${output_file_csv};
mariadb-import –lines-terminated-by=’\n‘ –fields-terminated-by=‘;‘ –verbose –local -h${MARIADB_HOST} -u${MARIADB_USER} -p${MARIADB_PW} ${MARIADB_DB} ${output_file_csv};
exit 1;
fi

Gelegentlich kommt es vor, dass wir von der DTU keine bzw. leere Werte zurückbekommen (vielleicht werden hier nach erfolgreicher Übertragung die Werte von der DTU gelöscht, oder der Speicher wird voll, etc.)

Bespiel:

Normalerweise sind die Werte für Ost_Energie_Gesamt und West_Energie_Gesamt (energy_total im Output) aber immer befüllt, daher werden wir diese verwenden, um auf leere Werte zu prüfen.

Sollten die 2 Werte leer sein, warten wir eine Minute und holen uns die Werte nochmal (bei unseren Tests war das ausreichend).

Zusätzlich vermerken wir uns das als Message, um zu sehen, wie oft das vorkommt.

check1=`cat ${output_file} |grep -A20 „port_number: 1“ |grep -B20 „port_number: 2“ |grep „energy_total“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

check2=`cat ${output_file} |grep -A20 „port_number: 2“ |grep „energy_total“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

if [[ -z ${check1} ]] && [[ -z ${check2} ]]
then
sleep 60;
${HOYMILES_PYTHON} –host ${HOYMILES_IP} get-real-data-new > ${output_file};
message=“Empty Values from Hoymiles DTU“;
else
message=““;
fi

Nachdem wir jetzt unseren Output haben, schneiden wir uns die Felder raus die wir wollen.

Da der Output dynamisch ist (z.B., wenn die Ostseite keine Werte mehr liefert, sind die Werte nicht leer, sondern die Felder „verschwinden“ aus dem Output), müssen wir hier aufpassen und uns die Werte entsprechend der port_number rausfiltern – sonst würden wir z.B. die West-Werte als Ost-Werte importieren.

uhrzeit=${DATETIME};

temperatur=`cat ${output_file} |grep temperature |cut -d „:“ -f2 | sed -n 1p |xargs`;

gesamt_frequenz=`cat ${output_file} |grep -A20 „sgs_data“ |grep -B20 „port_number: 1“ |grep „frequency“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

gesamt_spannung=`cat ${output_file} |grep -A20 „sgs_data“ |grep -B20 „port_number: 1“ |grep „voltage“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

gesamt_strom=`cat ${output_file} |grep -A20 „sgs_data“ |grep -B20 „port_number: 1“ |grep „current“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

gesamt_leistung=`cat ${output_file} |grep -A20 „sgs_data“ |grep -B20 „port_number: 1“ |grep „active_power“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

gesamt_blindleistung=`cat ${output_file} |grep -A20 „sgs_data“ |grep -B20 „port_number: 1“ |grep „reactive_power“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

gesamt_leistungsfaktor=`cat ${output_file} |grep -A20 „sgs_data“ |grep -B20 „port_number: 1“ |grep „power_factor“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

ost_spannung=`cat ${output_file} |grep -A20 „port_number: 1“ |grep -B20 „port_number: 2“ |grep „voltage“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

ost_strom=`cat ${output_file} |grep -A20 „port_number: 1“ |grep -B20 „port_number: 2“ |grep „current“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

ost_leistung=`cat ${output_file} |grep -A20 „port_number: 1“ |grep -B20 „port_number: 2″ |grep “ power:“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

ost_energie_tag=`cat ${output_file} |grep -A20 „port_number: 1“ |grep -B20 „port_number: 2“ |grep „energy_daily“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

ost_energie_gesamt=`cat ${output_file} |grep -A20 „port_number: 1“ |grep -B20 „port_number: 2“ |grep „energy_total“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

west_spannung=`cat ${output_file} |grep -A20 „port_number: 2“ |grep „voltage“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

west_strom=`cat ${output_file} |grep -A20 „port_number: 2“ |grep „current“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

west_leistung=`cat ${output_file} |grep -A20 „port_number: 2″ |grep “ power:“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

west_energie_tag=`cat ${output_file} |grep -A20 „port_number: 2“ |grep „energy_daily“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

west_energie_gesamt=`cat ${output_file} |grep -A20 „port_number: 2“ |grep „energy_total“ |cut -d „:“ -f2 | sed -n 1p |xargs`;

Als Letztes schreiben wir uns die Werte in die temporäre csv Datei und importieren sie in unsere MariaDB:

echo „${uhrzeit};${temperatur};${gesamt_frequenz};${gesamt_spannung};${gesamt_strom};${gesamt_leistung};${gesamt_blindleistung};${gesamt_leistungsfaktor};${ost_spannung};${ost_strom};${ost_leistung};${ost_energie_tag};${ost_energie_gesamt};${west_spannung};${west_strom};${west_leistung};${west_energie_tag};${west_energie_gesamt};${message}“ | sed ’s/;;/;\\N;/g‘ | sed ’s/;;/;\\N;/g‘ |sed ’s/;$/;\\N/g‘ > ${output_file_csv};

mariadb-import –lines-terminated-by=’\n‘ –fields-terminated-by=‘;‘ –verbose –local -h${MARIADB_HOST} -u${MARIADB_USER} -p${MARIADB_PW} ${MARIADB_DB} ${output_file_csv};

 

Unser Skript lassen wir zwischen 5:00 und 20:55 Uhr alle 5 Minuten laufen:
*/5 05-20 * * * /home/alarm/get_hoymiles_dtu.sh > /dev/null 2>&1

Ab 21:00 bis 4:00 Uhr werden wir es nur stündlich laufen lassen, da wir hier keine relevanten Werte erwarten:
00 21,22,23,00,01,02,03,04 * * * /home/alarm/get_hoymiles_dtu.sh > /dev/null 2>&1

Weiter geht’s demnächst im 2. Teil.

Data Lakes vs. Data Warehouses