Phase 2 - Flasher Web Goal: flash an ESP32 from a browser using Web Serial and a firmware ".bin" uploaded through the Phase 1 controller. Implemented scope: - "/flasher" page. - Firmware catalog loaded from "GET /api/v1/firmware". - Firmware cards display name, version, application, compatible hardware, size, and SHA-256. - Firmware selection. - Firmware download from "GET /api/v1/firmware/{id}/download". - Web Serial connection flow. - ESP32 flashing flow through Espressif "esptool-js". - Progress bar and status messages. - User-readable errors for unsupported browser/context, denied access, missing port, disconnection, download failure, and write failure. Out of scope for Phase 2: - OTA. - Provisioning. - Fleet Management. - Edge OS. - Firmware generation. Secure Context Web Serial requires a secure browser context. Accessing the VM directly through plain HTTP by IP address is not enough for real Web Serial use: http://192.168.1.62:88/flasher Observed behavior on that URL: - "/flasher" loads. - Firmware catalog loads. - Web Serial is blocked by browser context. - The page displays a warning. Minimal approved test path for Phase 2 is a local SSH tunnel from the Mac: ssh -N -L 18888:127.0.0.1:88 codex@192.168.1.62 Then open: http://localhost:18888/flasher Observed behavior through localhost tunnel: - "/flasher" loads. - No secure-context warning is shown. - The Connect ESP32 button is enabled. For real use through "iot.aeizoon.com", HTTPS must be configured. Flash Address The current firmware catalog does not yet store a flash address. The Flasher page therefore provides an operational "Flash address" field with default value: 0x0 If a provided ".bin" requires a different address, set it manually before flashing. HTTPS Validation Route As of 2026-07-06, HTTPS access is configured through NPM. Operational URLs: https://iot.aeizoon.com/ https://iot.aeizoon.com/flasher http://192.168.1.62:88/ # internal access only Physical Phase 2 validation must be performed from: https://iot.aeizoon.com/flasher Do not use the localhost tunnel except for punctual diagnostics. Browser pre-check performed: - "https://iot.aeizoon.com/flasher" loads. - Page protocol is "https:". - The insecure-context warning is not shown. - The Connect ESP32 button is enabled by the page. - Firmware catalog currently loads with "0" items until a real ".bin" is uploaded. Physical Validation Adjustment After testing an ESP32 Ethernet/WiFi AliExpress board through an external USB-TTL adapter, the default baudrate was changed to "115200" because this board was stable at "115200" and unstable at "921600". The Flasher also now resolves "Auto-detected" flash size before calling "writeFlash()" instead of passing "detect" directly to "esptool-js". Cache and Fit-Check Adjustment - 2026-07-06 A repeated physical test still showed "File 1 doesn't fit in the available flash", and the browser log did not include the latest diagnostic messages. This indicated that the HTTPS path was serving an older cached Flasher script. Applied correction: - "/flasher" now references "/js/flasher.js?v=phase2-20260706-3". - "/flasher" now references "/css/app.css?v=phase2-20260706-3". - "flasher.js" logs "Flasher build: phase2-20260706-3" on load. - Static resources served by the Spring backend are configured with no-cache headers. - Because NPM may still add external cache headers, asset version query strings must be bumped after Flasher JS/CSS changes. - Flash size now defaults to "Keep firmware setting", avoiding the "esptool-js" fit check that can reject a valid image before writing. - "Auto-detected size check" remains available for diagnostics. Next validation should use: - URL: "https://iot.aeizoon.com/flasher" - Baudrate: "115200" - Flash size: "Keep firmware setting" - Confirm first log line: "Flasher build: phase2-20260706-3"