Hallo Dieter,
darf ich Dir als Anregung meine Lösung vorstellen?
Basis ist der Code aus #15.
Vier Tankstellen, die Abfrage (noch) nicht in einer Funktion, Ausgabe nur auf die serielle Schnittstelle, Intervall 10min.
//
// https://forum.arduino.cc/t/projektvorstellung-spritpreis-von-deiner-heimtankstelle-mit-esp32-auf-display-anzeigen/924802/57
//
/*
* Ergebnis der Abfrage (17.11.2021, 23:11)
*
23:11:19.635 -> C:\Daten\Projects\Sketchbook\sketches\Tankerkoenig\tankListe\tankListe.ino
23:11:19.776 -> Connecting
23:11:20.244 -> .....
23:11:22.241 -> Connected to WiFi network with IP Address: 192.168.178.85
23:11:22.287 -> https://creativecommons.tankerkoenig.de/json/prices.php?ids=3c034790-3d2a-4093-8417-032a48cb9f25,e1a15081-24c2-9107-e040-0b0a3dfe563c,51d4b5e1-a095-1aa0-e100-80009459e03a,1a1ec4ba-cc2a-4663-8330-81efc48b9256&apikey=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
23:11:23.453 -> HTTP Response code: 200
23:11:23.453 -> {"ok":true,"license":"CC BY 4.0 - https:\/\/creativecommons.tankerkoenig.de","data":"MTS-K","prices":{"e1a15081-24c2-9107-e040-0b0a3dfe563c":{"status":"closed"},"1a1ec4ba-cc2a-4663-8330-81efc48b9256":{"status":"open","e5":1.799,"e10":1.739,"diesel":1.609},"51d4b5e1-a095-1aa0-e100-80009459e03a":{"status":"closed"},"3c034790-3d2a-4093-8417-032a48cb9f25":{"status":"closed"}}}
23:11:23.499 -> Jantzon Holle ist geschlossen.
23:11:23.499 -> HEM Groß Düngen ist geschlossen.
23:11:23.499 -> Jet Hi Ochtersum ist geschlossen.
23:11:23.499 -> ARAL Hi Alfelder Straße
23:11:23.499 -> Super E5 : 1.799
23:11:23.499 -> Super E10: 1.739
23:11:23.499 -> Diesel : 1.609
*/
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <ArduinoOTA.h>
// Netzwerkdaten
constexpr char ssid[] { "SSID" };
constexpr char password[] { "PASSWORT" };
// Tankerkoenig ApiKey
String TankerkoenigApiKey { "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" };
// Tankerkönig Tankstellenliste
// TODO: Liste aus nvs oder Filesystem lesen - am besten im Tankerkönig-Format
/*
{
"id": "3c034790-3d2a-4093-8417-032a48cb9f25",
"name": "Tankstelle Holle",
"brand": "Jantzon Tankstelle",
"street": "Bindersche Str.",
"house_number": "2",
"post_code": 31188,
"place": "Holle",
"lat": 52.089633,
"lng": 10.161023,
"isOpen": false
},
...
*/
struct Tanke
{
const char* stationId;
const char* stationName;
};
constexpr Tanke tankstellenListe[]
{
{
"3c034790-3d2a-4093-8417-032a48cb9f25",
"Jantzon Holle"
},
{
"e1a15081-24c2-9107-e040-0b0a3dfe563c",
"HEM Groß Düngen"
},
{
"51d4b5e1-a095-1aa0-e100-80009459e03a",
"Jet Hi Ochtersum"
},
{
"1a1ec4ba-cc2a-4663-8330-81efc48b9256",
"ARAL Hi Alfelder Straße"
}
};
// Preisschwelle für Alarm
// TODO: Alarmschwellen einstellbar machen (nvs oder Filesystem).
constexpr float preisalarmDiesel { 1.500 }; // icke
constexpr float preisalarmE5 { 1.700 }; // Frau & Sohn
// RootCA von Tankerkoenig
const char* root_ca = \
"-----BEGIN CERTIFICATE-----\n" \
"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\n" \
"-----END CERTIFICATE-----\n";
// Abfragetimer, laut Nutzungsbedingungen darf die API alle 5 Minuten abgefragt werden
unsigned long lastTime = 0;
// 10 Minuten (600000)
constexpr unsigned long timerDelay { 600000 };
// Um die ersten 10 Minuten zu überspringen
bool skiptimer = true;
String jsonBuffer;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
WiFi.begin(ssid, password);
Serial.println(F("Connecting"));
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print('.');
}
Serial.println("");
Serial.print(F("Connected to WiFi network with IP Address: "));
Serial.println(WiFi.localIP());
ArduinoOTA.begin();
}
void loop()
{
ArduinoOTA.handle();
if ((millis() - lastTime) > timerDelay || skiptimer == true)
{
// Send an HTTP GET request
skiptimer = false;
lastTime = millis();
// Check WiFi connection status
if (WiFi.status() == WL_CONNECTED)
{
String serverPath = "https://creativecommons.tankerkoenig.de/json/prices.php?ids=";
for (const auto& tanke : tankstellenListe)
{
serverPath += tanke.stationId;
serverPath += ',';
}
// ersetze das letzte Komma durch ein & (was vorher am Anfang des apikey-Strings stand)
int lastKomma = serverPath.lastIndexOf(',');
serverPath[lastKomma] = '&';
serverPath += "apikey=" + TankerkoenigApiKey;
Serial.println(serverPath);
// TEST: don't call server until request string is correct
// return;
jsonBuffer = httpGETRequest(serverPath.c_str());
Serial.println(jsonBuffer);
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, jsonBuffer);
if (error)
{
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
// von Tommy
bool isOk = doc["ok"];
if (!isOk)
{
String msg = doc["message"];
Serial.println(msg);
return;
}
JsonObject prices = doc["prices"];
for (const auto& tanke : tankstellenListe)
{
Serial.print(tanke.stationName);
JsonObject station = prices[tanke.stationId];
if (station["status"] == "closed")
{
Serial.println(F(" ist geschlossen."));
continue;
}
if (station["status"] == "no prices")
{
Serial.println(F(": keine Preise verfügbar."));
continue;
}
Serial.println();
float stationE5 = station["e5"];
float stationE10 = station["e10"];
float stationDiesel = station["diesel"];
Serial.print(F("\tSuper E5 : "));
Serial.println(stationE5, 3);
Serial.print(F("\tSuper E10: "));
Serial.println(stationE10, 3);
Serial.print(F("\tDiesel : "));
Serial.println(stationDiesel, 3);
if (stationDiesel <= preisalarmDiesel)
{
Serial.println(F("Mein Auto tanken!"));
}
if (stationE5 <= preisalarmE5)
{
Serial.println(F("Familienautos tanken!"));
}
}
}
else
{
Serial.println("WiFi Disconnected");
}
}
}
String httpGETRequest(const char* serverName)
{
WiFiClient client;
HTTPClient http;
// Your Domain name with URL path or IP address with path
http.begin(serverName, root_ca);
// Send HTTP POST request
int httpResponseCode = http.GET();
String payload = "{}";
if (httpResponseCode > 0)
{
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else
{
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
return payload;
}
Gruß Walter