/*
* Sciensano Virus Barometer voor Wokwi ESP32 + 2.9" E-Paper
* Deze versie gebruikt de GxEPD2 library en is geschikt voor de Wokwi simulatie.
*/
// --- KERN BIBLIOTHEKEN ---
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// --- DISPLAY BIBLIOTHEKEN (voor de Wokwi simulatie) ---
#include <GxEPD2_BW.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSansBold9pt7b.h> // Een iets vetter lettertype kan helpen
#include <Fonts/FreeMonoBold9pt7b.h>
// --- CONFIGURATIE ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* api_key = "45c5e5d376dc2689f99154c759fcdb3b6043bcda53e16b7f"; // Jouw API key uit de screenshot
const char* api_endpoint = "https://iotsolutions.be/api/iot/virus-data";
// --- DISPLAY CONFIGURATIE (voor Wokwi) ---
// Deze pinnen moeten overeenkomen met hoe je de draden hebt aangesloten in Wokwi.
// Standaard pinnen voor veel voorbeelden:
#define EPD_CS 15
#define EPD_DC 27
#define EPD_RST 26
#define EPD_BUSY 25
// Let op: Pas deze pinnen aan als je ze anders hebt aangesloten!
GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
// Hulpfunctie om tekst te centreren
void drawCentered(String text, int y) {
int16_t tbx, tby; uint16_t tbw, tbh;
display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh);
uint16_t x = (display.width() - tbw) / 2 - tbx;
display.setCursor(x, y);
display.print(text);
}
void setup() {
Serial.begin(115200);
Serial.println("Sciensano E-Paper Barometer (Wokwi) opstarten...");
display.init(115200);
showLoadingScreen("Verbinden met WiFi...");
connectWiFi();
fetchDataAndUpdate("België");
promptForInput();
}
void loop() {
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input.length() > 0) {
fetchDataAndUpdate(input);
promptForInput();
}
}
}
void promptForInput() {
Serial.println("\nVoer een stationsnaam in en druk op Enter:");
}
void connectWiFi() {
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() != WL_CONNECTED) {
showError("WiFi Fout");
} else {
Serial.println(" Verbonden!");
}
}
void showLoadingScreen(String message) {
display.setRotation(1); // 2.9 inch scherm is staand, dus draaien naar landschap
display.setFont(&FreeSans9pt7b);
display.setTextColor(GxEPD_BLACK);
display.setFullWindow();
display.firstPage();
do {
display.fillScreen(GxEPD_WHITE);
drawCentered(message, display.height() / 2);
} while (display.nextPage());
}
void showError(String message) {
showLoadingScreen(message);
display.hibernate();
}
void fetchDataAndUpdate(String station) {
if (WiFi.status() != WL_CONNECTED) {
showLoadingScreen("WiFi opnieuw verbinden...");
connectWiFi();
if (WiFi.status() != WL_CONNECTED) return;
}
showLoadingScreen("Data ophalen...");
WiFiClientSecure client;
client.setInsecure(); // Nodig voor Wokwi
HTTPClient http;
if (http.begin(client, api_endpoint)) {
http.addHeader("Content-Type", "application/json");
http.addHeader("X-API-KEY", api_key);
String jsonPayload = "{\"station\":\"" + station + "\"}";
int httpCode = http.POST(jsonPayload);
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
DynamicJsonDocument doc(2048);
DeserializationError error = deserializeJson(doc, payload);
if (!error && doc["success"]) {
String last_update = doc["data"]["last_update"];
String station_name = doc["data"]["station_name"];
String covid_level = doc["data"]["covid"]["activity_level"];
String griep_level = doc["data"]["influenza"]["activity_level"];
String rsv_level = doc["data"]["rsv"]["activity_level"];
drawFinalDisplay(station_name, last_update, covid_level, griep_level, rsv_level);
} else {
showError("JSON Fout");
}
} else {
showError("HTTP Fout: " + String(httpCode));
}
http.end();
} else {
showError("Verbindingsfout");
}
}
void drawFinalDisplay(String station_name, String last_update, String covid_level, String griep_level, String rsv_level) {
display.setRotation(1);
display.setTextColor(GxEPD_BLACK);
station_name.replace("ë", "e"); // Noodzakelijk voor veel standaard fonts
display.setFullWindow();
display.firstPage();
do {
display.fillScreen(GxEPD_WHITE);
display.setFont(&FreeSansBold9pt7b);
drawCentered("Sciensano Barometer", 15);
display.setFont(&FreeSans9pt7b);
String subtitle = station_name + " (" + last_update + ")";
drawCentered(subtitle, 35);
display.drawLine(10, 45, display.width() - 10, 45, GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(10, 65); display.print("COVID-19:");
display.setCursor(10, 85); display.print("INFLUENZA:");
display.setCursor(10, 105); display.print("RSV:");
display.setFont(&FreeSansBold9pt7b);
display.setCursor(150, 65); display.print(covid_level.toUpperCase());
display.setCursor(150, 85); display.print(griep_level.toUpperCase());
display.setCursor(150, 105); display.print(rsv_level.toUpperCase());
} while (display.nextPage());
Serial.println("Display bijgewerkt!");
display.hibernate();
}
Loading
epaper-2in9
epaper-2in9