Ako funguje HTTP OTA na ESP32

ESP32 obsahuje knižnicu HTTPUpdate, ktorá vie stiahnuť .bin súbor z HTTP/HTTPS servera a prepísať flash pamäť. Proces: ESP32 sa zobudí → zavolá /api/ota/version → porovná verziu → ak je nová, stiahne /api/ota/firmware.bin → reštartuje sa s novým firmware.

Tok OTA aktualizácie:

ESP32 (v1.0.2)
  └─ GET /api/ota/version?device=sensor-01
       │  Response: {"version":"1.0.3","url":"/api/ota/firmware/sensor-01"}
       │
  1.0.3 > 1.0.2 → stiahni firmware
       │
  GET /api/ota/firmware/sensor-01
  (s API kľúčom v hlavičke)
       │
  ESP32 prepíše flash → reštart → beží v1.0.3

1. Kompilácia firmware do .bin súboru

# Arduino IDE → Sketch → Export Compiled Binary
# PlatformIO (odporúčané)
pio run --target buildfs  # ak máš SPIFFS/LittleFS
pio run                    # skompiluje .pio/build/esp32dev/firmware.bin

2. PHP/Laravel OTA server

Routes

// routes/api.php
Route::middleware('ota.auth')->group(function () {
    Route::get('/ota/version', [OtaController::class, 'version']);
    Route::get('/ota/firmware/{device}', [OtaController::class, 'firmware']);
});

Middleware — autentifikácia zariadenia

// app/Http/Middleware/OtaAuth.php
public function handle(Request $request, Closure $next): Response
{
    $key = $request->header('X-OTA-Key');
    if ($key !== config('ota.secret_key')) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }
    return $next($request);
}

Controller

// app/Http/Controllers/OtaController.php
class OtaController extends Controller
{
    public function version(Request $request): JsonResponse
    {
        $device  = $request->query('device', 'default');
        $current = config("ota.devices.{$device}.version", '0.0.0');
        $url     = url("/api/ota/firmware/{$device}");

        return response()->json([
            'version' => $current,
            'url'     => $url,
        ]);
    }

    public function firmware(string $device): BinaryFileResponse
    {
        $path = storage_path("app/ota/{$device}/firmware.bin");

        if (!file_exists($path)) {
            abort(404);
        }

        return response()->file($path, [
            'Content-Type'        => 'application/octet-stream',
            'Content-Disposition' => 'attachment; filename="firmware.bin"',
            'X-MD5'               => md5_file($path),
        ]);
    }
}

Konfigurácia verzií (config/ota.php)

return [
    'secret_key' => env('OTA_SECRET_KEY'),
    'devices' => [
        'sensor-01' => ['version' => '1.0.3'],
        'sensor-02' => ['version' => '1.0.3'],
        'relay-01'  => ['version' => '2.1.0'],
    ],
];

3. ESP32 kód — kontrola a stiahnutie OTA

#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <HTTPUpdate.h>
#include <WiFiClientSecure.h>

const char* DEVICE_ID      = "sensor-01";
const char* CURRENT_VER    = "1.0.2";
const char* OTA_SERVER     = "https://api.gear.sk";
const char* OTA_KEY        = "tajny-ota-kluc";

void checkAndApplyOTA() {
    HTTPClient http;
    String url = String(OTA_SERVER) + "/api/ota/version?device=" + DEVICE_ID;
    http.begin(url);
    http.addHeader("X-OTA-Key", OTA_KEY);

    int code = http.GET();
    if (code != 200) { http.end(); return; }

    DynamicJsonDocument doc(256);
    deserializeJson(doc, http.getString());
    http.end();

    String newVer = doc["version"].as<String>();
    if (newVer == CURRENT_VER) {
        Serial.println("Firmware je aktuálny: " + newVer);
        return;
    }

    Serial.println("Nový firmware: " + newVer + " → sťahujem...");
    WiFiClientSecure client;
    client.setInsecure(); // na produkciu použi CA cert

    // Vlastné hlavičky: prekonfi guruj HTTPClient a odovzdaj ho httpUpdate
    String fwUrl = String(OTA_SERVER) + "/api/ota/firmware/" + DEVICE_ID;
    HTTPClient httpFw;
    httpFw.begin(client, fwUrl);
    httpFw.addHeader("X-OTA-Key", OTA_KEY);
    httpFw.addHeader("X-Device-ID", DEVICE_ID);

    // httpUpdate.update(HTTPClient&) akceptuje predkonfigurovaný klient
    t_httpUpdate_return ret = httpUpdate.update(httpFw, CURRENT_VER);
    switch (ret) {
        case HTTP_UPDATE_OK:      Serial.println("OTA OK — reštart"); break;
        case HTTP_UPDATE_FAILED:  Serial.println("OTA zlyhalo"); break;
        case HTTP_UPDATE_NO_UPDATES: Serial.println("Bez aktualizácie"); break;
    }
}

void setup() {
    WiFi.begin("SSID", "PASS");
    while (WiFi.status() != WL_CONNECTED) delay(500);
    checkAndApplyOTA();
    // ďalší kód zariadenia...
}

Nasadenie novej verzie — workflow

  1. Skompiluj firmware.bin cez PlatformIO: pio run
  2. Nahraj .bin na server: storage/app/ota/sensor-01/firmware.bin
  3. Zmeň verziu v config/ota.php na 1.0.3
  4. Pri ďalšom zobudení ESP32 automaticky stiahne a nainštaluje nový firmware

Bezpečnostné odporúčania