Advertisement
jgoy

Stroomprijzen API - ESP32-3248S035

May 10th, 2024 (edited)
923
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.53 KB | Source Code | 0 0
  1. /* ==================================================================================
  2.  Arduino IDE - board: ESP32 Dev Module of DOIT ESP32 DEVKIT V1
  3.  sketch voor ESP32-3248S035 -  https://nl.aliexpress.com/item/1005006398547061.html
  4.  De ESP moet de huidige tijd hebben, om de string te kunnen samenstellen
  5.  om de juiste link aan te maken (met epochtijd in dit voorbeeld):
  6.  https://api.energy-charts.info/price?bzn=BE&start=1715503187&end=1715632787
  7.  =====================================================================================
  8.  In de JSON die de API retourneert zit per paar
  9.  - UNIX-tijd (epochtijd: aantal seconden sinds 1/1/1970 middernacht), per uur oplopend
  10.  - de prijs per MWh voor dat uur
  11.  =====================================================================================
  12.  Zie https://shorturl.at/gjlLX voor een grafische weergave van dezelfde gegevens
  13.  De API geeft niet altijd evenveel elementen terug. Dit varieert volgens het uur
  14.  tussen 11 en 36 items. De code moet daar uiteraard op inspelen.
  15.  Elk uur (HH:01:02) wordt de ESP herstart (opzettelijk niet HH:00:00 gekozen)
  16.  =====================================================================================
  17.  De sketch kan de gegevens weergeven op het display
  18.  * cijfermatig in een lijst
  19.  * in een grafiek
  20.  De gebruiker kan dit kiezen met de flashknop (toggle). De voorkeur wordt opgeslagen in
  21.  het flash-geheugen, zodat bij herstart de keuze onthouden wordt.
  22. */
  23.  
  24. #include <TFT_eSPI.h>     // https://github.com/Bodmer/TFT_eSPI
  25. #include <WiFiManager.h>  // https://github.com/tzapu/WiFiManager/
  26. #include <ArduinoJson.h>  // https://github.com/bblanchon/ArduinoJson
  27. #include <HTTPClient.h>   // voor verbinding met API
  28. #include <Preferences.h>  // https://github.com/vshymanskyy/Preferences
  29.  
  30. TFT_eSPI tft = TFT_eSPI();  // User_Setup.h instellingen kan je vinden op https://espgo.be bij ESP32-3248S035
  31. WiFiManager myWiFi;
  32. Preferences flash;
  33.  
  34. #define API_ITEMS 36     // max aantal API-records die je wil verwerken
  35. #define WAARDE_ROOD 100  // stroomprijs in rode kleur indien hoger dan deze waarde
  36. #define UTC_OFFSET_ZOMER 7200
  37. #define UTC_OFFSET_WINTER 3600
  38. struct tm tInfo;                                       // https://cplusplus.com/reference/ctime/tm/
  39. bool grafiek = false;                                  // er is weergave in cijfers en ook in grafiek (toggle met flashknop)
  40. const char* time_Zone = "CET-1CEST,M3.5.0,M10.5.0/3";  // https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
  41. char* verbind[] = { "WiFi: geen verbinding", "Verbind met hotspot", "S035_ESP", "Start een browser op adres",
  42.                     "192.168.4.1", "om netwerk en paswoord", "in te brengen" };
  43. double prijzen[API_ITEMS];                                               // de prijzen in de API
  44. time_t epo[API_ITEMS];                                                   // voor de epochtijden uit de Json
  45. String mijnLink = "https://api.energy-charts.info/price?bzn=BE&start=";  // link wordt verderop aangevuld met de tijden
  46.  
  47. void setup() {
  48.   Serial.begin(115200);
  49.   pinMode(16, OUTPUT), digitalWrite(16, HIGH);  // LED groen uit
  50.   pinMode(17, OUTPUT), digitalWrite(17, HIGH);  // LED blauw uit
  51.   tft.init();
  52.   tft.setRotation(3);         // USB bovenaan
  53.   tft.fillScreen(TFT_BLACK);  // schermen van vorige sessies wissen
  54.   showLogoWiFi(TFT_GREEN);
  55.   myWiFi.setAPCallback(toonBerichtGeenVerbinding);  // indien geen WiFi gevonden wordt
  56.   myWiFi.autoConnect("S035_ESP");                   // verbinden met laatst gekende WiFi, zoniet start access point "S035_ESP"
  57.   configTzTime(time_Zone, "be.pool.ntp.org");
  58.   tft.fillScreen(TFT_BLACK);
  59.   tft.drawCentreString("Tijd SNTP Ophalen", 240, 160, 4);
  60.   getLocalTime(&tInfo);
  61.   tft.fillScreen(TFT_BLACK);
  62.   tft.setTextColor(TFT_ORANGE);
  63.   tft.drawCentreString("Json Data Ophalen", 240, 160, 4);
  64.   ophalen_Data();
  65.   flash.begin("grafi", true);             // flash uitlezen (true = read only)
  66.   grafiek = flash.getBool("grafiek", 0);  // voorkeur weergave ophalen - default naar "false"
  67.   flash.end();
  68.   (grafiek) ? tonen_Grafiek() : tonen_Data();  // weergeven volgens eerder opgeslagen voorkeur
  69. }
  70.  
  71. void loop() {
  72.   toonTijd();
  73.   if (!digitalRead(0)) wijzigWeergave();  // flashknop wijzigt tussen grafiek of lijst met cijfers
  74.   // if (prijzen[0] < 0) opladenThuisBatterij();  // prijzen[0] = prijs tijdens het actuele uur
  75. }
  76.  
  77. void wijzigWeergave() {
  78.   grafiek = !grafiek;
  79.   (grafiek) ? tonen_Grafiek() : tonen_Data();
  80.   flash.begin("grafi");               // flashgeheugen, ook schrijven want geen 2de parameter
  81.   flash.putBool("grafiek", grafiek);  // voorkeur opslaan
  82.   flash.end();
  83.   delay(800);  // UI debouncing voor indrukken knop
  84. }
  85.  
  86. void showLogoWiFi(uint32_t myColor) {  // 3 lijnen code = kleiner en sneller dan grafisch bestand laden
  87.   tft.fillCircle(240, 160, 6, myColor);
  88.   for (byte i = 0; i < 4; i++) tft.drawSmoothArc(240, 160, 37 - i * 7, 35 - i * 7, 135, 225, myColor, myColor, true);
  89. }
  90.  
  91. void toonTijd() {  // toont ook de actuele stroomprijs
  92.   char theDate[11];
  93.   getLocalTime(&tInfo);                                                    // SNTP bij opstart en daarna elke 3 uur op een ESP32
  94.   tft.drawRect(-1, 26, 482, 2, WiFi.isConnected() ? TFT_GREEN : TFT_RED);  // lijnen zijn groen als WiFi verbonden is
  95.   tft.setTextColor(TFT_CYAN, TFT_BLACK);
  96.   tft.setCursor(0, 0, 4);
  97.   strftime(theDate, sizeof(theDate), "%d-%m-%G", &tInfo);  // https://cplusplus.com/reference/ctime/strftime/
  98.   tft.print(theDate);
  99.   tft.setCursor(tft.getCursorX() + 8, 0);
  100.   tft.printf("%02d:%02d:%02d", tInfo.tm_hour, tInfo.tm_min, tInfo.tm_sec);
  101.   tft.setCursor(tft.getCursorX() + 35, 0);
  102.   tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
  103.   tft.print("/MWh: ");
  104.   tft.setTextColor(prijzen[0] > 100 ? TFT_RED : TFT_GREEN);
  105.   if (prijzen[0] < 0) tft.setTextColor(TFT_YELLOW);
  106.   tft.printf("%3.2F", prijzen[0]);
  107.   if ((tInfo.tm_min == 1) && (tInfo.tm_sec == 2)) ESP.restart();  // refresh elk uur gegevens
  108. }
  109.  
  110. void ophalen_Data() {                                                     // string met tijden klaarzetten en energiedata opvragen
  111.   time_t now;                                                             // time_t is eigenlijk een uint32_t
  112.   time(&now);                                                             // epochtijd toekennen
  113.   now = now - (now % 3600);                                               // naar onder afronden op gehele uur
  114.   now = now + ((tInfo.tm_isdst) ? UTC_OFFSET_ZOMER : UTC_OFFSET_WINTER);  // eerst weergegeven gegevens bij voorkeur in lokale tijd
  115.   mijnLink = mijnLink + String(now) + "&end=" + String(now + (API_ITEMS * 3600));
  116.   Serial.println(mijnLink);
  117.   if (mijnLink.length() > 51) get_JsonData();  // lege invoer niet versturen (bvb. als SNTP een timeout geeft)
  118.   else {                                       // samenstellen string (om naar API te versturen) = mislukt
  119.     tft.fillRect(0, 200, 320, 40, TFT_BLACK);
  120.     tft.drawCentreString("Link API onvolledig", 160, 200, 4);
  121.   }
  122.   tft.fillCircle(255, 9, 9, TFT_MAGENTA);  // euro symbool: zit niet bij de fonts
  123.   tft.fillCircle(255, 9, 7, TFT_BLACK), tft.fillRect(258, 4, 8, 12, TFT_BLACK);
  124.   tft.drawRect(247, 7, 9, 2, TFT_MAGENTA), tft.drawRect(249, 10, 6, 2, TFT_MAGENTA);
  125. }
  126.  
  127. void tonen_Grafiek() {  // Json gegevens in grafiek tonen op display
  128.   tft.fillRect(0, 28, 480, 290, TFT_BLACK);
  129.   tft.setTextColor(TFT_WHITE);
  130.   for (uint8_t i = 0; i < 6; i++) {  // lijnen met waarden tekenen: i voor de verticale coördinaten
  131.     tft.drawFastHLine(0, 40 + i * 50, 480, tft.color565(64, 64, 64));
  132.     for (uint8_t j = 0; j < 3; j++)  // j verwerkt de horizontale coördinaat
  133.       tft.drawRightString(String(i * 50 - 50), j * 228 + 23, 286 - i * 50, 1);
  134.   }
  135.   for (uint8_t i = 0; i < API_ITEMS; i++) {
  136.     if (epo[i]) {  // lege waarden niet weergeven
  137.       uint16_t mijnKleur = prijzen[i] < WAARDE_ROOD ? TFT_GREEN : TFT_RED;
  138.       if (prijzen[i] < 0) mijnKleur = TFT_YELLOW, tft.fillRect(i * 14, 240, 13, 0 - prijzen[i], mijnKleur);
  139.       else tft.fillRect(i * 14, 240 - prijzen[i], 13, prijzen[i], mijnKleur);
  140.       struct tm* cor;            // om de epochtijden om te zetten naar tm-structuur in lokale (geCORrigeerde) tijd
  141.       cor = localtime(&epo[i]);  // epochtijden in de lijst aanpassen aan lokale tijd / zomertijd
  142.       tft.setTextColor(prijzen[i] > 0 ? TFT_BLACK : TFT_YELLOW);
  143.       tft.setCursor(1 + i * 14, 230, 1);  // uren onderaan grafiek
  144.       tft.printf("%02d", cor->tm_hour);
  145.       tft.setTextColor(TFT_RED);
  146.       tft.setCursor(1 + i * 14, 243, 1);
  147.       tft.printf("%02d", cor->tm_hour);
  148.     }
  149.   }
  150. }
  151.  
  152. void tonen_Data() {  // Json gegevens weergeven in lijst met 2 rijen van uren / prijzen
  153.   tft.fillRect(0, 28, 480, 290, TFT_BLACK);
  154.   tft.drawRect(240, 26, 2, 292, WiFi.isConnected() ? TFT_GREEN : TFT_RED);
  155.   for (uint8_t i = 0; i < API_ITEMS; i++) {
  156.     if (epo[i]) {  // er worden niet altijd evenveel waarden geretourneerd door de API - lege items niet weergeven
  157.       tft.setTextColor(TFT_LIGHTGREY, TFT_BLACK);
  158.       tft.setCursor(((i < 18) ? 0 : 260), 33 + (i % 18) * 16, 2);
  159.       tft.printf(" %02d. ", i + 1);
  160.       tft.setTextColor(TFT_CYAN, TFT_BLACK);
  161.       struct tm* cor;            // om de epochtijden om te zetten naar tm-structuur in lokale (geCORrigeerde) tijd
  162.       cor = localtime(&epo[i]);  // epochtijden in de lijst aanpassen aan lokale tijd / zomertijd
  163.       tft.printf("%02d-%02d-%02d %02d:%02d", cor->tm_mday, cor->tm_mon + 1, cor->tm_year + 1900, cor->tm_hour, cor->tm_min);
  164.       tft.setTextColor((prijzen[i] < WAARDE_ROOD) ? TFT_GREEN : TFT_RED);  // geel < 0 - blauw tss 0/100 - rood > 100
  165.       if (prijzen[i] < 0) tft.setTextColor(TFT_YELLOW, TFT_BLACK);
  166.       tft.drawRightString(String(prijzen[i]), (i < 18 ? 220 : 480), 33 + (i % 18) * 16, 2);
  167.     }
  168.   }
  169. }
  170.  
  171. void get_JsonData() {
  172.   HTTPClient http;
  173.   http.begin(mijnLink);
  174.   if (http.GET() == 200) {
  175.     DynamicJsonDocument doc(4096);  // waarde groot genoeg kiezen om de data te bevatten
  176.     auto error = deserializeJson(doc, http.getString());
  177.     if (error) {
  178.       tft.drawCentreString("deserializeJson() failed", 240, 200, 4);
  179.       tft.drawCentreString(error.c_str(), 240, 250, 4);
  180.     }
  181.     for (uint8_t i = 0; i < API_ITEMS; i++) {
  182.       prijzen[i] = doc["price"][i];
  183.       epo[i] = doc["unix_seconds"][i];
  184.     }
  185.   } else tft.drawCentreString("Error in API response", 240, 160, 4);
  186.   http.end();
  187. }
  188.  
  189. void toonBerichtGeenVerbinding(WiFiManager* myWiFi) {  // gestart als WiFi-verbinding niet lukt
  190.   tft.fillScreen(TFT_NAVY);
  191.   tft.setTextColor(TFT_YELLOW), tft.setTextFont(4);
  192.   for (uint8_t i = 0; i < 7; i++) tft.drawCentreString(verbind[i], 240, 40 + i * 30, 4);
  193. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement