Wollte mich nochmal zurückmelden, habe gestern den Tibber Pulse bekommen und ab 1.Januar gehts bei mir endlich los mit Tibber <3
Da ich außer der Raspberrymatic keine weitere Hardware im Einsatz habe (ioBroker, etc.) habe ich mithilfe des Forums eine einfache, reine Skriptlösung erarbeitet, um die Tibber Strompreise aus der API per curl auszulesen und auszuwerten. In meinem Fall werden die teuren Stunden herausgesucht und während dieser die Heizung gesperrt (basierend auf dem von der API bereitgestellten Preisniveau
https://developer.tibber.com/docs/reference#pricelevel).
Es wird CUxD und dein persönlicher Tibber-API-Key
https://developer.tibber.com/docs/overview benötigt, sonst nichts weiter.
Es besteht aus zwei Skripten:
Das erste Skript läuft einmal täglich um die Strompreise für den Tag zu holen und in einer Systemvariable zu speichern. Sie werden ausgewertet und die Sperrzeiten für den Tag werden festgelegt und ebenfalls in Systemvariablen gespeichert.
Das zweite Skript läuft stündlich und schaut nur, ob die aktuelle Stunde gesperrt werden soll oder nicht.
Code: Alles auswählen
! == Tibber-Strompreise Skript v1.2 Mic4rd ((Tägliche Ausführung))==!
! Dank an MichaelN und Tyfys
! Quelle und Hinweise: https://homematic-forum.de/forum/viewtopic.php?f=19&t=79588&start=20#p787998
! Eingabe:
string apikey = "xxx"; ! Hier deinen persönlichen Tibber-API-Key eintragen
string cuxd = "CUxD.CUX2801001:1"; ! Hier dein CUXD-Device eintragen
string sysvar = "TIBBER_Strompreise"; ! Hier Namen der Systemvariablen (String) eintragen, in welche die Preise geschrieben werden sollen
string errorvar = "TIBBER_API-Fehler"; ! Hier Namen der Systemvariablen (Bool) eintragen, welchen einen API-Fehler anzeigt
string inhibitvar = "TIBBER_Sperrzeiten"; ! Hier Namen der Systemvariablen (String) eintragen, in den die Sperrzeiten eingetragen werden
string inhibithrs = "TIBBER_Sperrstundenanzahl"; ! Hier Namen der Systemvariablen (Integer) eintragen, in die die Anzahl der Sperrzeiten eingetragen wird
string inhibitprices = "TIBBER_Sperrzeitpreise"; ! Hier Namer der Systemvariablen (String) eintragen, in die die Preise der Sperrzeiten eingetragen wird
integer maxinhibit = 5; ! Hier die maximale Anzahl der Sperrstunden eintragen (=24, falls beliebig)
string inhibitstring1 = "EXPENSIVE"; ! Preisniveau, bei dem gesperrt werden soll (z.B. "VERY_EXPENSIVE" oder "EXPENSIVE" (es wird auch VERY_EXPENSIVE gesperrt))
string inhibitstring2 = "none"; ! Weiteres Preisniveau, bei dem gesperrt werden soll (z.B. "NORMAL" oder "none" falls nicht benötigt)
! Ausführung, ab hier nichts ändern
string period = "today";
object arr=""; ! Variable für das Sortierskript
dom.GetObject(sysvar).State("error"); ! Wert auf error setzen, falls mit dem Abrufen etwas schiefgehen sollte
dom.GetObject(errorvar).State(1); ! Fehlervariable auf true setzen, falls mit dem Abrufen etwas schiefgehen sollte
var tibberpriceurl="curl -H \"Authorization: Bearer "+apikey+"\" -H \"Content-Type: application/json\" -X POST -d '{ \"query\": \"{viewer {homes {currentSubscription {priceInfo {"+period+" {startsAt total level}}}}}}\" }' https://api.tibber.com/v1-beta/gql";
dom.GetObject(cuxd+".CMD_SETS").State(tibberpriceurl); ! Query-Ziel setzen
dom.GetObject(cuxd+".CMD_QUERY_RET").State(1);
string tibber_prices = dom.GetObject(""+cuxd+".CMD_RETS").State(); ! Tibber-API Query ausführen und in Variable speichern
!WriteLine("API-Antwort: "+tibber_prices);
! Falls keine Strompreise verfügbar sind
if (tibber_prices.Contains("error") || tibber_prices.Length()==0){
WriteLine("FEHLER: Kein Strompreis verfügbar!");}
else {
dom.GetObject(sysvar).State(tibber_prices);
dom.GetObject(errorvar).State(0); ! Fehler-Variable auf false setzen
WriteLine("Preise erfolgreich empfangen!");
string stdout; string stderr;
integer i = 0; integer exp_hrs = 0; string inh_hrs; string inh_prices;
while (i<24) { ! Jede Stunde des Tages auswerten
system.Exec( "node -e 'console.log( " # tibber_prices # ".data.viewer.homes[0].currentSubscription.priceInfo."+period+"["+i.ToString()+"].level );'",&stdout,&stderr); if (stderr) { Write(stderr); quit; } ! Preisniveau auslesen
! WriteLine(i.ToString()+" Uhr: "+stdout);
if (stdout.Contains(inhibitstring1) || stdout.Contains(inhibitstring2)) { ! Teure und ggf. normale Stromstunden zählen
exp_hrs=exp_hrs+1;
system.Exec( "node -e 'console.log( " # tibber_prices # ".data.viewer.homes[0].currentSubscription.priceInfo."+period+"["+i.ToString()+"].total );'",&stdout,&stderr); if (stderr) { Write(stderr); quit; } ! Preis auslesen
inh_prices=inh_prices+stdout+";"; ! Kosten der Sperrstunde eintragen
arr=arr + stdout + "/"; ! Kosten der Sperrstunde eintragen
system.Exec( "node -e 'console.log( " # tibber_prices # ".data.viewer.homes[0].currentSubscription.priceInfo."+period+"["+i.ToString()+"].startsAt );'",&stdout,&stderr); if (stderr) { Write(stderr); quit; } ! Zeitpunkte auslesen
inh_hrs=inh_hrs+stdout.Substr(11,2)+";"; ! Sperrzeiten eintragen
arr=arr + stdout.Substr(11,2) + ";"; ! Sperrzeiten eintragen
};
i=i+1;
}
inh_hrs=inh_hrs.Substr(0,inh_hrs.Length()-1); ! Letztes ; entfernen
inh_prices=inh_prices.Substr(0,inh_prices.Length()-1); ! Letztes ; entfernen
inh_prices=inh_prices.Replace("\n",""); ! Umbrüche entfernen
arr=arr.Replace("\n",""); ! Umbrüche entfernen
! Sortierskript von Tyfys zum Begrenzen der maximalen Sperrzeit
! ---------------------------------------------------------------------------
if (exp_hrs > maxinhibit) { ! Sperrstunden begrenzen falls nötig
WriteLine("Heizung würde heute für "+exp_hrs.ToString()+" Stunden gesperrt. Es wird auf die " # maxinhibit # " teuersten Stunden begrenzt.");
object arrtyp ="n;n"; ! Element Art n=numerisch / a=alphanumerisch
var sep1=";"; ! Trennzeichen für Stunden
var sep2="/"; ! Trennzeichen für Preis und Stunde
!Tauschstrings von > nach
string av;
string an;
integer len = web.webGetValueListCount(arr).ToInteger() - 1;
boolean swapped = true;
var elemart = "a";
string index;
integer von = 0;
integer bis = 1;
foreach(index, system.GenerateEnum(von, bis)) {
integer x = (von + bis) - index.ToInteger();
elemart = arrtyp.StrValueByIndex(sep1, x);
swapped = true;
while (swapped) {
i = 1;
swapped = false;
while (i <= len) {
if (((elemart <> "n") && ((arr.StrValueByIndex(sep1, i).StrValueByIndex(sep2, x).ToUpper()) < (arr.StrValueByIndex(sep1, i - 1).StrValueByIndex(sep2, x).ToUpper())))
|| ((elemart == "n") && ((arr.StrValueByIndex(sep1, i).StrValueByIndex(sep2, x).ToFloat()) < (arr.StrValueByIndex(sep1, i - 1).StrValueByIndex(sep2, x).ToFloat())))) {
av = arr.StrValueByIndex(sep1, i - 1) # sep1 # arr.StrValueByIndex(sep1, i);
an = arr.StrValueByIndex(sep1, i) # sep1 # arr.StrValueByIndex(sep1, i - 1);
arr = arr.Replace(av, an);
swapped = true;
}
i = i + 1;
}
}
}
string ix;
object arr2 = "";
string elem;
foreach(elem, arr.Split(";")) {
arr2 = elem # sep1 # arr2;
}
arr = arr2;
arr2="";
inh_hrs="";
inh_prices="";
WriteLine("Die teuersten " # maxinhibit # " Preise heute:");
foreach(ix, system.GenerateEnum(0, maxinhibit-1)) {
WriteLine((ix.ToInteger() + 1) # ". " # (arr.StrValueByIndex(sep1, ix).StrValueByIndex(sep2, 0)) # " EUR ab " # (arr.StrValueByIndex(sep1, ix).StrValueByIndex(sep2, 1)) # " Uhr" );
inh_hrs = inh_hrs + arr.StrValueByIndex(sep1, ix).StrValueByIndex(sep2, 1) + ";";
inh_prices = inh_prices + arr.StrValueByIndex(sep1, ix).StrValueByIndex(sep2, 0) + ";";
! arr2=arr2 # arr.StrValueByIndex(sep1, ix).StrValueByIndex(sep2, 0) # sep2 # arr.StrValueByIndex(sep1, ix).StrValueByIndex(sep2, 1) # sep1;
}
exp_hrs=maxinhibit;
inh_hrs=inh_hrs.Substr(0,inh_hrs.Length()-1); ! Letztes ; entfernen
inh_prices=inh_prices.Substr(0,inh_prices.Length()-1); ! Letztes ; entfernen
};
! ---------------------------------------------------------------------------
WriteLine("Heizung wird heute für "+exp_hrs.ToString()+" Stunden gesperrt.");
dom.GetObject(inhibitvar).State(inh_hrs); ! SV schreiben
dom.GetObject(inhibithrs).State(exp_hrs); ! SV schreiben
dom.GetObject(inhibitprices).State(inh_prices); ! SV schreiben
dom.GetObject(ID_PROGRAMS).Get("TIBBER-Strompreis stündlich auswerten").ProgramExecute(); ! Auswertung direkt starten
}
Dieses Skript wird einmal täglich um 00:01 ausgeführt, um die Strompreise für den aktuellen Tag zu holen und in einer Systemvariable zu speichern. Zusätzlich wird das Skript jede halbe Stunde ausgeführt, WENN eine Bool-Systemvariable TIBBER_API-Fehler auf true steht, also z.B. wenn die Internetverbindung unterbrochen oder die Tibber-API nicht erreichtbar ist. Es kann dann weitergehend z.B. ein Alarm oder eine Pushnachricht eingerichtet werden.
Zu Beginn jeder Stunde führt man dann dieses Skript aus:
Code: Alles auswählen
! == Tibber-Strompreise Skript v1.2 Mic4rd ((Stündliche Ausführung))==!
! Quelle und Hinweise: https://homematic-forum.de/forum/viewtopic.php?f=19&t=79588&start=20#p787998
! Eingabe:
string channel_inhibit = "Heizungssperre-Tibber"; ! Hier den Namen der Systemvariable oder des Kanals eintragen, der eine Sperre der Heizung bewirkt
string SV_pricing_today = "TIBBER_Strompreise"; ! Hier die Systemvariable eintragen, in welcher die Preise von heute sind
string SV_current_price = "TIBBER_Strompreis_aktuell"; ! Hier die Systemvariable eintragen, in welche der aktuelle Preis geschrieben werden soll
string SV_current_level = "TIBBER_Preisniveau_aktuell"; ! Hier die Systemvariable eintragen, in welche das aktuelle Preisniveau geschrieben werden soll
string inhibitvar = "TIBBER_Sperrzeiten"; ! Hier Namen der Systemvariablen eintragen, in den die Sperrzeiten eingetragen sind
string SV_errorvar = "TIBBER_API-Fehler"; ! Hier Namen der Systemvariablen eintragen, welchen einen API-Fehler anzeigt
! =================================
! Ausführung, ab hier nichts ändern
string period = "today";
string hour2check = system.Date("%H"); ! Aktuelle Stunde auslesen
string tibber_prices = dom.GetObject(SV_pricing_today).Value(); ! Strompreise auslesen
string stdout; string stderr; ! API Auslesevariablen
! Falls keine Strompreise verfügbar sind
if (tibber_prices.Contains("error") || tibber_prices.Length()==0){
WriteLine("FEHLER: Kein Strompreis verfügbar.");
dom.GetObject(SV_current_price).State("error");
dom.GetObject(SV_current_level).State("error");
dom.GetObject(SV_errorvar).State(1); ! API-Fehler setzen
quit;}
system.Exec( "node -e 'console.log( " # tibber_prices # ".data.viewer.homes[0].currentSubscription.priceInfo."+period+"["+hour2check+"].total );'",&stdout,&stderr); if (stderr) { Write(stderr); quit; } ! Aktuellen Strompreis auslesen
WriteLine("Strompreis ab "+hour2check+" Uhr: "+stdout.Replace("\n","")+" EUR/kWh");
dom.GetObject(SV_current_price).State(stdout.ToFloat()); ! Aktuellen Strompreis in die Systemvariable schreiben
system.Exec( "node -e 'console.log( " # tibber_prices # ".data.viewer.homes[0].currentSubscription.priceInfo."+period+"["+hour2check+"].level );'",&stdout,&stderr); if (stderr) { Write(stderr); quit; } ! Aktuelles Preisniveau auslesen
WriteLine("Preisniveau ab "+hour2check+" Uhr: "+stdout);
dom.GetObject(SV_current_level).State(stdout); ! Aktuelles Preisniveau in die Systemvariable schreiben
WriteLine("Sperrzeiten: "+dom.GetObject(inhibitvar).Value());
if (dom.GetObject(inhibitvar).Value().Contains(hour2check)) { ! Wenn aktuelle Stunde eine Sperrzeit ist
WriteLine("Teurer Strom erkannt, Heizung wird gesperrt!");
dom.GetObject(channel_inhibit).State(1); ! Heizung sperren
WriteLine("Sperrstatus: "#dom.GetObject(channel_inhibit).State());}
else { ! Aktuelle Stunde ist keine Sperrstunde
WriteLine("Strompreis normal oder günstig, Heizung wird freigegeben!");
dom.GetObject(channel_inhibit).State(0); ! Heizung freigeben
WriteLine("Sperrstatus: "#dom.GetObject(channel_inhibit).State());}
Im Falle der obigen Skripte müssen folgende Systemvariablen angelegt werden:
- TIBBER_API-Fehler (Logikwert) - Wird auf wahr gesetzt, falls die Strompreise nicht von der Tibber-API abgerufen werden können. Man kann es dann z.B. halbstündlich weiter probieren
- TIBBER_Preisniveau_aktuell (Zeichenkette) - Zeigt stündlich das aktuelle Preisniveau an
- TIBBER_Sperrstundenanzahl (Zahl) - Zeigt täglich die Anzahl der gesperrten Stunden an
- TIBBER_Sperrzeiten (Zeichenkette) - Zeigt täglich die Stunden der Sperrung als Liste an
- TIBBER_Strompreis_aktuell (Zahl) - Zeigt stündlich den aktuellen Strompreis in €/kWh an
- TIBBER_Strompreise (Zeichenkette) - Hier wird die JSON-Antwort der Tibber-API für den kompletten Tag abgelegt
Bei mir funktioniert das soweit sehr gut.
EDIT: V1.0: Um hier keinen falschen/verwirrenden Zwischenstand stehen zu lassen, habe ich die alten Zwischenstände entfernt und nur die aktuellste Version hier eingefügt
EDIT2: V1.1: API-Fehlererkennung mit Hilfe von MichaelN eingebaut, danke!
EDIT3: V1.2: Funktion zum Sperren der x teuersten Stunden hinzugefügt mit dem Sortierskript von Tyfys, vielen Dank!