Günstigste X Stunden in den nächsten Y Stunden bei aWATTar finden

Problem

Ich möchte mein E-Auto bis zu einer gewissen Uhrzeit (z.B. 7:00) bis zu einer bestimmten Ladung (z.B. 90%) aufladen. Und das zu den möglichst günstigsten Zeiten lt. aWATTar, da ich dort einen stündliche ändernden Bezugstarif habe.

Das lässt sich auf alle Verbraucher übertragen, die 1) unterbrechbar sind und 2) nicht durchgängig laufen müssen. z.B. wenn eine Wärmepumpe 10h am Tag laufen soll, dann "Stunden bis Zielladung" auf 24 setzen und die Wärmepumpe nur dann einschalten, wenn der Rang des aktuellen Preises <= 10 ist.

Lösung

Zunächst einmal die Anzahl der Stunden bis zu der gewünschten Uhrzeit berechnen:

Und danach ein Pico-C Programm einbinden:

mit untenstehendem Programmcode.

Damit sieht man immer den Rang des aktuellen Preises in den nächsten X Stunden (bzw. den Rang in allen kommenden vorhandenen Stunden (bis 24:00 bzw. ab 14:00 bis nächster Tag 24:00) bzw. den Rang am heutigen Tag).

Möchte man das Auto z.B. 5h bis zum gewünschten Zeitpunkt laden, dann einfach dann, wenn der Rang <= 5 ist.

Pico-C Programm

Hier das Pico-C Programm. Es ist so optimiert, dass es nur 1x pro Stunde die Daten von aWATTar holt, es sei denn der Eingangswert ändert sich (was bei obigem Beispiel auch 1x pro Stunde der Fall ist):

// This pico-c program returns the rank of the current energy price in the next nrHours. // This is useful if you want to e.g. charge your car for 5 hours over night until 7AM: // just call this program with the number of hours until 7AM and check if the result is <= 5 // Apache License 2.0 // v0.3 // input0 = number of hours to check rank of current price // output0 = current price // output1 = rank of current price in given numbers of upcoming hours to check (1-based) // output2 = rank of current price in all available upcoming prices (1-based) // output3 = rank of current price in all todays prices (1-based) // NOTE: change "api.awattar.at" to "api.awattar.de" if you are in Germany //get the rank of a given price in an array of prices up to maxRank int getRank(float price, int maxRank, float *prices) { int n; // counter for hours int newn; int i; // counter float tmpPrice; int rank; //bubble sort the first nHours prices for (n = maxRank-1; n>0; n = newn) { newn = 0; for (i=0; i<n; i++) { if (prices[i] > prices[i+1]) { tmpPrice = prices[i+1]; prices[i+1] = prices[i]; prices[i] = tmpPrice; newn = i; } } } //determine the rank of the current price amongst the first nHours of the sorted prices for (i=0; i<maxRank; i++) { if (price == prices[i]) { return i+1; } } return maxRank; } //declaration of all variables outside of loop to prevent out-of-memory errors int nrHours; // number of hours to take into account char* webContent; //content of http://api.awattar.at/v1/marketdata/current.yaml?tomorrow=include char* marketprice; //marketprice content of http://api.awattar.at/v1/marketdata/current.yaml?tomorrow=include char hournum[33]; //string to search for in webContent to get the marketprice of a specific hour float prices[35]; // prices according to aWATTar API - up to 35 hours including current hour (API returns prices until EOD up to 14:00, later until end of next day) float currentPrice; // the current price i.e. the price of the 0th hour int n; // counter for hours //for testing with pico-c interpreter see https://loxwiki.atlassian.net/wiki/spaces/LOX/pages/1520762981/PicoC+Interpreter //though most functions will not work in interpreter getinputevent(); //to clear buffer of changed inputs (to not run the loop twice) while(TRUE) { sleeps(30); //sleep some seconds to not fetch data again while input still changes and get correct data when aWATTar is late if (getinput(0)<0 || getinput(0)>34) { errorprintf("ERROR: PicoC aWATTar price rank - illegal number of hours to check (%d)\n", getinput(0)); break; } webContent = httpget("api.awattar.at", "/v1/marketdata/current.yaml?tomorrow=include"); //fetch all available data //find rank of currentPrice in nrHours / all upcoming hours for (n=0; n<35; n++) { sprintf(hournum, "data_price_hour_rel_+%02d_amount: ", n); marketprice = strstrskip(webContent, hournum); if (marketprice == 0) break; prices[n] = atof(marketprice); } currentPrice = prices[0]; setoutput(0, currentPrice); if (getinput(0) < n) { nrHours = getinput(0)+1; } else { nrHours = n; } setoutput(1, getRank(currentPrice, nrHours, prices)); setoutput(2, getRank(currentPrice, n, prices)); //find rank of currentPrice on this day for (n=0; n<24; n++) { sprintf(hournum, "price_threshold_%02d: ", n); marketprice = strstrskip(webContent, hournum); if (marketprice == 0) break; if (atof(marketprice) == currentPrice) { setoutput(3, n+1); } } free(webContent); //sleep until next hour (or nrHours changes) so we need to fetch only once an hour while(getcurrenttime()%3600 && !getinputevent()) { sleeps(1); } }