Aktuell kann man für das Bundesland Bayern anhand einer einfachen Ampel die notwendigen Maßnahmen gegen die Corona-Pandemie ablesen. Da diese Daten auch als API zur Verfügung stehen, ist die Umsetzung mit einem internetfähigen Mikrocontroller, wie dem ESP32, recht einfach.
Über die freie API von corona-ampel-bayern.de
können die wichtigsten Daten ausgelesen und weiterverarbeitet werden.
URL: https://corona-ampel-bayern.de/data/data.json
Das Resultat ist ein JSON-String, der folgendermaßen aufgebaut ist:
{
"hospitalizationLast7Days": 366,
"hospitalizationLast7DaysIncidence": 2.8,
"currentIntensiveCarePatients": 282,
"lastSync": "2021-10-21T07:30:01.850Z",
"lastUpdate": "2021-10-21T07:00:02.708Z"
}
Der folgende Schaltplan zeigt einen sehr simplen Aufbau, denn es sind außer dem ESP32 nur drei verschiedenfarbige LEDs (inkl. Vorwiderstand) notwendig.
Anstatt der einzelnen LEDs kann auch ein sog. LED traffic light module verwendet werden, auf dem in einer kleinen Platine schon die richtigen LEDs inkl. Vorwiderstände verbaut sind.
Vorsicht: Einige dieser LED-Ampel-Module haben keine oder 0Ω Widerstände!
Hier sollten separate Vorwiderstände benutzt werden.
Der folgende Sketch verbindet sich alle 60 Minuten mit dem eingestellten, lokalen WLAN und ruft die
aktuellen Werte der API ab.
Zum Parsen der von der API gelieferten Daten wird hier die Library
ArduinoJson
verwendet, die es einfach macht, die benötigten Werte auszulesen.
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// Replace with your WiFI credentials
const char *WIFI_SSID = "**********";
const char *WIFI_PASSWORD = "**********";
const char *DATA_URL = "https://corona-ampel-bayern.de/data/data.json";
#define LED_PIN_RED 13
#define LED_PIN_YELLOW 12
#define LED_PIN_GREEN 14
#define CHECK_INTERVAL 60 // in minutes
#define MAX_INTENSIVE_CARE_PATIENTS 600
#define MAX_HOSPITALIZATION 1200
#define DEBUG true
#ifdef DEBUG
#define DEBUG_INIT() Serial.begin(9600)
#define DEBUG_PRINT(val) Serial.print(val)
#define DEBUG_PRINTLN(val) Serial.println(val)
#else
#define DEBUG_INIT()
#define DEBUG_PRINT(val)
#define DEBUG_PRINTLN(val)
#endif
#define lmillis() ((long)millis())
HTTPClient httpClient;
StaticJsonDocument<1000> jsonDoc;
long nextUpdate = 0;
void setup()
{
DEBUG_INIT();
pinMode(LED_PIN_RED, OUTPUT);
pinMode(LED_PIN_YELLOW, OUTPUT);
pinMode(LED_PIN_GREEN, OUTPUT);
for (byte i = 0; i < 30; i++) {
resetLeds();
digitalWrite(12 + i % 3, HIGH);
delay(50);
}
resetLeds();
nextUpdate = lmillis() + 1000;
}
void loop()
{
if (lmillis() - nextUpdate >= 0) {
nextUpdate = lmillis() + CHECK_INTERVAL * 60 * 1000;
updateCovLights();
}
}
void updateCovLights()
{
static bool hasError = false;
connectWifi();
DEBUG_PRINT("Requesting data...");
httpClient.begin(DATA_URL);
int httpCode = httpClient.GET();
if (httpCode == 200) {
DEBUG_PRINTLN("[ok]");
String payload = httpClient.getString();
DeserializationError jsonError = deserializeJson(jsonDoc, payload);
if (jsonError) {
DEBUG_PRINT("deserializeJson() failed: ");
DEBUG_PRINTLN(jsonError.c_str());
hasError = true;
} else {
int hospitalizationLast7Days = jsonDoc["hospitalizationLast7Days"];
int currentIntensiveCarePatients = jsonDoc["currentIntensiveCarePatients"];
DEBUG_PRINTLN("hospitalizationLast7Days = " + String(hospitalizationLast7Days));
DEBUG_PRINTLN("currentIntensiveCarePatients = " + String(currentIntensiveCarePatients));
resetLeds();
if (currentIntensiveCarePatients > MAX_INTENSIVE_CARE_PATIENTS) {
digitalWrite(LED_PIN_RED, HIGH);
} else if (hospitalizationLast7Days > MAX_HOSPITALIZATION) {
digitalWrite(LED_PIN_YELLOW, HIGH);
} else {
digitalWrite(LED_PIN_GREEN, HIGH);
}
}
} else {
DEBUG_PRINTLN("ERROR: " + String(httpCode));
hasError = true;
}
httpClient.end();
disconnectWifi();
if (hasError) {
resetLeds();
for (byte i = 0; i < 20; i++) {
digitalWrite(LED_PIN_YELLOW, !digitalRead(LED_PIN_YELLOW));
delay(500);
}
resetLeds();
}
}
void connectWifi()
{
DEBUG_PRINT("Connecting to WiFi.");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
DEBUG_PRINT(".");
}
DEBUG_PRINTLN("[ok]");
}
void disconnectWifi()
{
DEBUG_PRINT("Disconnecting WiFi...");
WiFi.disconnect();
while (WiFi.status() == WL_CONNECTED) {
delay(500);
DEBUG_PRINT(".");
}
DEBUG_PRINTLN("[ok]");
}
void resetLeds()
{
digitalWrite(LED_PIN_RED, LOW);
digitalWrite(LED_PIN_YELLOW, LOW);
digitalWrite(LED_PIN_GREEN, LOW);
}
Nach dem Kompilieren und Ausführen des Sketches sollten auf der seriellen Konsole die folgenden Debug-Ausgaben erscheinen und nach einigen Sekunden schaltet die Ampel auf die aktuelle Phase.
Für den Betrieb kann der Debug-Modul abgeschaltet werden, indem folgende Zeile geändert wird:
#define DEBUG false
Damit die Ampel auf eine bestimmte Phase schaltet sind folgende Bedingungen festgelegt worden.
(Angaben ohne Gewähr; Quelle: corona-ampel-bayern.de)
GRÜN | Die Werte für die gelbe und die rote Phase sind nicht erreicht. |
---|---|
GELB | Es wurden in einer Woche mehr als 1.200 neue COVID-19 Patienten in bayerischen Krankenhäusern aufgenommen. |
ROT | Es werden aktuell mehr als 600 COVID-19 Patienten auf Intensivstationen in Bayern versorgt. |
Je nachdem welche Farbe die Ampel anzeigt sind bestimmte Vorgaben zu erfüllen und Maßnahmen zu ergreifen.
(siehe: corona-ampel-bayern.de)