#include <Arduino.h> #include <WiFi.h> #include <WiFiClientSecure.h> #include <HTTPClient.h> #include <pgmspace.h> // ===================== LAB CONFIG ===================== // Wi-Fi credentials const char* WIFI_SSID = "LAB_WIFI_SSID"; const char* WIFI_PASSWORD = "LAB_WIFI_PASSWORD"; // Server hostname and port. // Hostname MUST match the CN/SAN in your server certificate (e.g. "iot-lab.local"). const char* SERVER_HOST = "iot-lab.local"; const uint16_t SERVER_PORT = 8443; // URL used by HTTPClient (hostname + port + path) const char* SERVER_URL = "https://iot-lab.local:8443/ingest"; // Device identity const char* DEVICE_ID = "sparrow-01"; // MAC secret key – must match SECRET_KEY in secure_server.py const char* SECRET_KEY = "LAB2_SUPER_SECRET_MAC_KEY"; // Root CA certificate (PEM), copied from ca.crt. // Replace the placeholder contents with your actual CA cert. static const char LAB_ROOT_CA[] PROGMEM = R"EOF( -----BEGIN CERTIFICATE----- PASTE_YOUR_CA_CERT_HERE -----END CERTIFICATE----- )EOF"; // ====================================================== WiFiClientSecure secureClient; // Very simple, non-cryptographic MAC, must match server's compute_mac() uint32_t computeMac(const String& payload, const char* secret) { String data = payload + secret; uint32_t h = 0; for (size_t i = 0; i < data.length(); i++) { uint8_t b = static_cast<uint8_t>(data[i]); h = (h * 31) ^ b; } return h; } void connectToWiFi() { Serial.printf("Connecting to WiFi SSID: %s\n", WIFI_SSID); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); uint8_t retries = 0; while (WiFi.status() != WL_CONNECTED && retries < 30) { delay(500); Serial.print("."); retries++; } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nWiFi connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } else { Serial.println("\nFailed to connect to WiFi"); } } void setup() { Serial.begin(115200); delay(2000); connectToWiFi(); secureClient.setTimeout(15000); // Load CA certificate so the ESP32 can verify the server's cert. if (!secureClient.setCACert(LAB_ROOT_CA)) { Serial.println("Failed to load CA certificate!"); } else { Serial.println("CA certificate loaded."); } randomSeed(esp_random()); } void loop() { if (WiFi.status() != WL_CONNECTED) { Serial.println("WiFi disconnected, reconnecting..."); connectToWiFi(); } if (WiFi.status() == WL_CONNECTED) { // Fake sensor data (same ranges as before) float tempC = 20.0 + (random(0, 1000) / 100.0f); // 20.00–29.99 float humidity = 40.0 + (random(0, 1000) / 50.0f); // 40.0–59.9 int battery = random(60, 100); // 60–99 % // Build JSON WITHOUT MAC first, in canonical key order: // battery, device_id, humidity, temp_c // This must match the server's json.dumps(sort_keys=True,separators=(",",":")) String jsonNoMac = "{"; jsonNoMac += "\"battery\":" + String(battery) + ","; jsonNoMac += "\"device_id\":\"" + String(DEVICE_ID) + "\","; jsonNoMac += "\"humidity\":" + String(humidity, 1) + ","; jsonNoMac += "\"temp_c\":" + String(tempC, 2); jsonNoMac += "}"; // Compute MAC over jsonNoMac + SECRET_KEY uint32_t mac = computeMac(jsonNoMac, SECRET_KEY); // Full JSON payload including MAC String payload = "{"; payload += "\"battery\":" + String(battery) + ","; payload += "\"device_id\":\"" + String(DEVICE_ID) + "\","; payload += "\"humidity\":" + String(humidity, 1) + ","; payload += "\"temp_c\":" + String(tempC, 2) + ","; payload += "\"mac\":" + String(mac); payload += "}"; Serial.println("Sending HTTPS POST to server (with cert validation)..."); Serial.println("URL: " + String(SERVER_URL)); Serial.println("Payload: " + payload); HTTPClient http; // Begin HTTPS connection with certificate verification. if (!http.begin(secureClient, SERVER_URL)) { Serial.println("Failed to start HTTP connection"); } else { http.addHeader("Content-Type", "application/json"); int httpCode = http.POST(payload); if (httpCode > 0) { Serial.printf("HTTP response code: %d\n", httpCode); String response = http.getString(); Serial.println("Response body: " + response); } else { Serial.printf("HTTP POST failed, error: %s\n", http.errorToString(httpCode).c_str()); } Serial.println("-----------------------------"); http.end(); } } delay(5000); // send every 5 seconds }