Automatischer Upload in VSCode für entspanntere Entwicklung der Web-UI

Hellou!

Angespornt von der vielen Aktivität im Forum, hab ich mich auch endlich mal wieder etwas freigeschaufelt und eine schon länger brodelnde Idee umgesetzt, bzw. unter Beobachtung umsetzen lassen :robot: :wink: .

Problem

Es geht konkrekt darum, dass die Entwicklung der Web-UI sehr mühsam ist. Volle Firmware-Builds dauern mitunter sehr lange, der Hack mit dem Remote Host läuft immer Gefahr, die eigene IP im Commit zu vergessen. Und schön ist es auch nicht, mit dem ganzen "http://" + remote_host + "/path" überall.

Mir ist da schon vor einiger Zeit aufgefallen, dass es eine Spezialbehandlung von Dateien auf der SD-Karte gibt, nämlich /.html/index.htm und /.html/logo.png. Den Ansatz hab ich spannend gefunden und entsprechend eingehakt.

Vorgeschlagene Lösung

Claude hat mir dann zwei VSCode Tasks und eine Anpassung vorgeschlagen:

  • Der Erste (Terminal > Run Task ... > Install watchdog) um das System vorzubereiten, da wird einfach per pip eine watchdog library installiert.
  • Und dann kann man unter Terminal > Run Task ... > Watch & upload /html den zweiten Task starten, der auf Änderungen im ESPuino/html/ Verzeichnis lauscht und entsprechend auf die SD-Karte ins Verzeichnis /.html/ hochlädt.
  • Im Web.cpp gibt es noch eine Änderung, die entsprechend nachschaut, ob Files von der SD-Karte in Frage kommen.

Da der Ordner /.html im Fileexplorer der WebUI nicht angezeigt wird (und ich das auch nicht ändern möchte), kann man hochgeladene Dateien aktuell nur via curl -X DELETE "http://<IP>/explorer?path=/.html/management.html" löschen.
Einen Task dafür hätte ich noch versucht, um das ein bisschen interaktiv zu gestalten, aber das würde Änderungen des Filterverhaltens im explorerHandleListRequest() (Web.cpp) benötigen, was ich eigentlich einen Overkill finde.

Stolperfalle

Vorsicht: Wenn man management.html hochladen lässt, muss man auch http://espuino.local/management.html im Browser ansurfen. Hat den Vorteil, dass man den aktuellen Stand der Box nicht überschreibt: Root (http://espuino.local) wird weiterhin die in der Firmware eingebackenen Version anzeigen.

Pull Request

PS

Ich war verwundert, wieso Claude Code nicht die bestehende Stelle im Code von Web.cpp angepasst hat, sondern eine andere Funktion gewählt hat, das war die Antwort:

Claudes Antwort
These two mechanisms serve genuinely different purposes, so let me lay out the tradeoff clearly.

  The /.html/index.htm check (line 452) overrides the root URL /, which has unique logic that serveProgmemFiles can't cover:
  - It branches on AP mode vs. STA mode (AP mode always serves accesspoint.html, never checks the SD card)
  - The comment explicitly notes that ETag must be skipped for SD-served files because their content changes independently of firmware

  serveProgmemFiles covers all the other registered routes (/management.html, /js/..., /vendor/..., etc.) via the generic /.html + uri pattern.

  They don't overlap — /.html/index.htm overrides / while the general mechanism would override /management.html. So:

  - Remove the /.html/index.htm block: The root URL loses its SD override entirely. Users who previously placed a custom index.htm on the card would be broken. Clean code, breaking
  change.
  - Keep both: Root URL still supports /.html/index.htm (special-cased, with correct ETag bypass), all other assets get the generic mechanism. No breakage, slightly duplicated pattern.
  - Unify by moving the general logic into webserverStart: Reverting the serveProgmemFiles change and inlining the SD check per-route would be more verbose with no real benefit — the
  architecture of serveProgmemFiles is exactly the right place for it.

  My recommendation: keep both as-is. The root / handler has genuinely different logic (AP/STA branch, ETag comment) that earns its own explicit handling, and removing the
  /.html/index.htm check would silently break existing users who customized that path. The two pieces complement rather than duplicate each other.

Und was ich noch vergessen habe …

Die Adresse, wohin hochgeladen werden soll ist der Reihe nach:

  1. Datei .vscode/espuino-device (Einzeiler, gitignored)
  2. Umgebungsvariable ESPUINO_HOST (env var)
  3. Und als Fallback der String "espuino.local" (der mDNS Default, wenn man den Hostnamen der Box nicht verändert hat)