#include #include #include #include // ====== LAB CONFIG: fill these in per-lab ====== const char* WIFI_SSID = "LAB_WIFI_SSID"; const char* WIFI_PASSWORD = "LAB_WIFI_PASSWORD"; // Replace with your server's IP const char* SERVER_URL = "https://192.168.1.100:8443/ingest"; const char* DEVICE_ID = "sparrow-01"; // This key must match SECRET_KEY on the server // NOTE: in real systems, putting secrets in firmware has risks → discussion later. const char* SECRET_KEY = "LAB2_SUPER_SECRET_MAC_KEY"; // =============================================== WiFiClientSecure secureClient; 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"); } } // 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(data[i]); h = (h * 31) ^ b; } return h; } void setup() { Serial.begin(115200); delay(2000); connectToWiFi(); // HTTPS client config: secureClient.setTimeout(15000); // For the lab, we disable certificate validation to keep // the code simple. This gives confidentiality but not strong // authenticity → good discussion point. secureClient.setInsecure(); // DO NOT DO THIS IN REAL PRODUCTS randomSeed(esp_random()); } void loop() { if (WiFi.status() != WL_CONNECTED) { Serial.println("WiFi disconnected, reconnecting..."); connectToWiFi(); } if (WiFi.status() == WL_CONNECTED) { // Fake sensor data, like in Lab 1 float tempC = 20.0 + (random(0, 1000) / 100.0f); float humidity = 40.0 + (random(0, 1000) / 50.0f); int battery = random(60, 100); // Build JSON without MAC first // We'll use this version to compute MAC both here and on the server. 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 uint32_t mac = computeMac(jsonNoMac, SECRET_KEY); // Full JSON payload with 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..."); Serial.println("URL: " + String(SERVER_URL)); Serial.println("Payload (with MAC): " + payload); HTTPClient http; 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); String response = http.getString(); Serial.printf("HTTP response code: %d\n", httpCode); Serial.println("Response body: " + response); Serial.println("-----------------------------"); http.end(); } } delay(5000); }