Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:laboratoare:2025_code:lab8_3 [2025/11/15 13:21] (current)
dan.tudose created
Line 1: Line 1:
 +<code C++ main.cpp>​
 +#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
 +}
 +
 +</​code>​
iothings/laboratoare/2025_code/lab8_3.txt · Last modified: 2025/11/15 13:21 by dan.tudose
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0