Skip to content

ESP32 web console and browser OTA - 2026-10-05

This is a local qualification checkpoint, not a release approval. GitHub writes and publication of 1.17.1.9 remain on hold. Firmware source for the final runs is 7821329851f69b6b945f061bc4d15212d43c3198.

Coverage gap and reproduced failures

Earlier component and simulated-peripheral tests did not establish the complete V4 browser flow. In particular, accepting a Started reply did not prove that a normal WiFi client could discover the hotspot or connect to its HTTP server. The actual embedded uploader also had to receive its completion response before the radio restarted. Those boundaries needed physical qualification.

The physical V4 runs found three failures:

  • ESP-NOW could leave the AP protocol mask at 15, including the proprietary LR bit. OTA returned an IP, but an ordinary WiFi client could not discover it. Explicitly restoring the AP to b/g/n (mask 7) made it discoverable.
  • The old AsyncElegantOTA implementation restarted from its network callback. A real browser upload installed the new image but timed out waiting for its completion response. The fixed implementation lets the response finish and schedules the reboot outside that callback.
  • Repeated stop/start could leave port 80 unavailable while CLI still reported success. The private, source-pinned AsyncTCP build now allows rebinding past completed connections, and OTA verifies that the listener actually started.

Host regressions also cover background ESP-NOW retries undoing an OTA pause, WebConfig teardown retaining OTA's WiFi, upload ownership and interruption, failed binds, and complete CRLF replies through the stock web console client. Negative controls fail with the old AP protocol, TCP binding, callback reboot, USB sleep guard, or line delimiter behavior.

Final physical observations

Check Result and boundary
V4 actual browser upload PASS. Chromium ran the unchanged embedded AsyncElegantOTA page. Multipart upload returned HTTP 200 OK; normal reboot loaded a distinct target version. USB answered afterward without another reset or unplug.
V4 OTA startup PASS for WiFi off -> OTA, WebConfig setup AP -> OTA, ESP-NOW coexistence, WebConfig LAN -> OTA, and an active LAN uploader -> OTA AP. The returned URLs served real pages across deferred cleanup.
V4 USB idle PASS for 600 seconds with no transmitted commands or keepalives, power saving on, USB logging on, and DTR asserted. Subsequent query and close/reopen passed; uptime advanced from 111 to 717 seconds.
V4 DTR deasserted PASS for immediate queries, 30 seconds idle, and reopen using an opener that established RTS low before deasserting DTR. No reset or startup delay was added.
XIAO S3 WIO Companion Restored from the temporary Repeater test role using an application-only flash. Partition signature and identity were preserved. All 60 read-only replies met the two-second deadline, including 10 held query pairs and 10 reopen pairs; maximum latency was 22 ms.

The V4 console runs above use the unchanged official SerialConsole through Node Web Streams and a physical Linux serial transport on Mercerwood. They do not exercise Chromium's OS Web Serial backend on that remote V4. Earlier physical XIAO browser tests are separate evidence, not a substitute for it. The client is pinned to meshcore-dev/flasher.meshcore.io revision 45a5257bf792b11a83f4c51c18d4f312addfb677, with lib/console.js SHA-256 107d3ad867915aea8b2454c324327397a0f9e2f0469656046054011bc64475f9.

The first disposable LAN association failed. A separate run with a fresh SSID, explicit WPA2/RSN CCMP configuration, AP readiness, and credential readback passed on the same firmware. The first failure is retained; these observations do not identify which test-network difference caused it.

Two DTR-deasserted first-query runs also failed. Their original pyserial opener briefly presented the USB hardware reset combination; the boot log recorded USB_UART_CHIP_RESET. Correcting the opener's line-state order passed without a reset or settle delay. These are retained test-fixture failures, not evidence that the user's intermittent console hang has been fixed.

During the 600-second idle run, dispatcher flags changed from 0 to 8. The radio remained in RX with no receive errors, zero received packets, and a configured five-minute receive-silence watchdog. This is consistent with the existing radio recovery policy on a quiet channel; uptime proves the MCU did not reboot. It is not an error-free RF stress qualification.

Artifacts and host checks

V4 application installed by the successful browser run:

  • Version: v1.17.1.9-hil-ota-upload-78213298.
  • Size: 2,093,336 bytes.
  • SHA-256: ebee70b05528b21aaaeddf8bc80f2762b7ad767ff5b6f29eadf8e2a78e90859d.

XIAO application restored after console testing:

  • Version: v1.17.1.9-hil-web-ota-78213298.
  • Size: 2,082,584 bytes.
  • SHA-256: 605a6b904756ab6d8dcdee8fd9288a996103c59e4f339d7768ece3497c57cfb3.

Both firmware builds passed. On this source, focused host checks passed: OTA startup 7, OTA lifecycle 15, async web lifecycle 2, official web console 3, WebConfig 40, and V4 partition migrator 4. PlatformIO was run serially.

Private raw logs and safe reports are retained under /tmp/meshcore-hil-20261004/web-console-investigation, including the failed runs. The index 782-evidence-index-safe.json records evidence hashes. Temporary V4 settings and the Pi network are restored after testing. The G2, its recovery ACLs, and its running MQTT services were not changed by this run.

Remaining limits

The subsequent current Full V4 native browser qualification adds actual Pi Chromium Web Serial, the unchanged setup GUI's five-second deadline, and measured fresh-flash and power-saving console idle results. The older source and boundaries above remain historical evidence. Neither report qualifies every host OS, physical USB adapter, cold power cycle, ESP32 board, firmware profile, or radio traffic load. USB-attached console checks do not establish CPU sleep, measured current or button wake. The subsequent V4 button-wake profile correction passed host/build validation and another native GUI fresh-flash plus 180-second open/closed console check, as recorded in that linked report. On 2026-10-06 the user separately confirmed V4 button screen wake; its firmware revision and CPU sleep state were not specified. The operator USB tests included no actual button press or sleep/current measurement.

Release candidate follow-up recorded 2026-10-07

The following source-scoped observations were originally recorded in the 1.17.1.9 candidate release notes. They are retained here as historical test results, including failed attempts and their separate recoveries. Build and publication status in this snapshot does not override the final release notes. Older passing images do not qualify a later firmware revision or turn an earlier failure into a pass. Latest-source V4 hardware was unavailable for a repeat; that is a physical coverage limitation, not a failed latest-source test.

The earlier c5 GitHub unit workflow passed all four jobs. Host regressions exercise production OTA callbacks, the official configuration GUI and app protocol behavior, including MD5 ordering, rejected second files, incomplete POSTs, cleanup and subsequent valid uploads. Sanitizer fixtures cover these OTA lifecycle cases. These checks use MeshCore's actual-code fixtures; MeshBench is not integrated.

For 1e421ff4, the coupled production WebConfig credential interception, NVS commit, CLI routing and MQTT consumer fixture passed four tests, including fresh portal-only setup, legacy fallback, reconnects, raw-PSK boundaries, failed and interrupted writes, and mutations that restore the old credential lookup. The broader WiFi and MQTT host suites passed 62 and 14 cases, respectively, with some overlap. The WebConfig host suite passed 53 cases, including the embedded page in an isolated Chromium headless browser. Seven infrastructure power-lifecycle cases and six portal-ownership cases passed. Five V4 setup-page cases include actual button/session handling under both signed and unsigned char. The new tests are explicitly included in the unit workflow. The current GitHub unit workflow at documentation and host-test commit 4c5f58f4 passed all four jobs; its firmware source remains 1e421ff4. The completed local release passed the strict package checks below; V4 OTA and G2/V4 portal-to-MQTT hardware checks remain pending.

The completed local all-board release has 463 qualified recipes and 926 firmware files. Its complete checksum inventory, capability and memory checks passed independent read-only revalidation. All 94 exact ESP32 board/role migration ZIPs and their combined archive passed validation. The 114 nRF52 infrastructure targets each have a qualified Full/Reduced pair with matching actual DFU identity, firmware and flash layout. These results qualify local packages from 1e421ff4; they do not qualify the pending physical upgrade paths or publish the release. The newer bd4cbf281 source protects ordinary setup/OTA APs from the SDK's shared long-range WiFi flag, defers conflicting ESP-NOW starts and keeps long-range protocol writes out of saved WiFi settings. It reports an active ESP-NOW conflict before starting an AP. The subsequent 8c4e09275 source also defers MQTT station maintenance and Full Companion station recovery while an AP owns WiFi. Final builds and hardware qualification of this candidate remain pending. Final public assets and catalogs still require their separate inventory and digest checks.

The physical G2 and V4 tests used the unchanged embedded browser uploader and the normal host console, retaining the stock 5-second first-command deadline. The earlier c5fe8a0e applications passed AP uploads with HTTP 200/OK, automatic restart, and preserved identities, ACLs and saved settings. The G2's initial upload completed in 19.053 seconds; the V4's completed in 16.392 seconds. First ordinary replies took 1.385 and 1.010 seconds, respectively, without a cable replug or reset rescue.

On the G2, a full valid first file followed by a second file returned HTTP 409 without an observed MCU restart. A full-file request with an incomplete closing multipart boundary also left uptime continuous. A valid upload then passed through that same running listener in 18.767 seconds. Full-image wrong-MD5 requests had already returned HTTP 400 without restart on parent 70bf4bdf. The tests do not claim that rejected requests leave the inactive flash slot untouched. A fresh 385-second sample of unmodified Cisien meshcoretomqtt had all four brokers connected, zero publish failures and no service restarts; both the original and recovery Admin ACLs were preserved. The earlier G2 LAN upload stall is treated as a local slow-WiFi limitation, not a release blocker. LAN upload was not qualified by these AP tests.

The new 1e421ff4 G2 Full Observer application also passed the unchanged native AP uploader: HTTP 200/OK in 18.437 seconds, firmware-owned restart, and first ordinary ver reply in 1.304 seconds. Live EndF body identity, the exact G2 target and source were verified, with the original 15 settings, both Admin ACLs, services and the Pi's exact SlowFi connection preserved. This qualifies that AP update, not fresh WebConfig provisioning into the on-device MQTT consumer; that check and the new-source V4 checks remain pending.

On parent 70bf4bdf, both G2 and V4 passed four 600-second quiet intervals: port open and closed with logging off, then open and closed with USB logging, all with power saving enabled. Uptime remained continuous, with no host keepalive writes during the intervals. The V4 reported radio-watchdog event bit 8; this was not an MCU reset or an all-zero-error result. Its USB-logging open interval received 26 bytes. The V4 also passed the first unchanged native setup-GUI connection immediately after a fresh flash, with the first clock reply in 73.3 ms. These quiet and fresh-flash checks were not repeated on c5fe8a0e, whose change was confined to OTA completion behavior. The newer canonical-WiFi source 1e421ff4 has the narrower G2 results below.

On 1e421ff4, the G2 passed one 600.022-second open-port quiet interval with USB logging and power saving enabled, with no host writes and continuous uptime. The following 600-second closed-port interval ended in a stock-browser reopen failure at the test helper's 5-second acquisition gate, before ver was sent. The host then had VMIN=1/VTIME=0; the ordinary exclusive serial client still replied in 21 ms, with continuous uptime and unchanged core error flags. This is an unresolved browser/native-port acquisition result, not a qualified closed-port pass or evidence of an MCU crash. A cleanup-overlay bug in that test helper was also found and fixed for the instrumented repeat; the earlier failed receipt is retained.

The instrumented G2 repeat on the same 1e421ff4 source passed both 600-second open and closed quiet intervals with USB logging and power saving enabled, continuous uptime and no host keepalive writes. Original settings and the host were restored. The maximum stock Enter-to-reply time was 3.584 seconds. The second native port open took 5.532 seconds; click-to-connected took 8.201 seconds. That acquisition time is separate from the unchanged 5-second command deadline, and the helper's connected wait started after its click RPC returned. This repeat does not reclassify the earlier failure or establish its cause. The separate logging-off run also passed both 600-second open and closed quiet intervals with power saving enabled, 85 successful queries, continuous uptime and restored original settings. Together the completed runs qualify all four quiet intervals on this G2 and source.

The subsequent 100-cycle acceptance attempt stopped after 32 completed cycles. All 86 stock commands passed, with a maximum Enter-to-reply time of 450 ms and no observed MCU reset. The failure was an automation timeout while clicking the stock close-overlay button; this is separate from the stock command deadline. At the failed-trial snapshot, the UI had marked itself disconnected while native close had not started. Native close subsequently fulfilled in 105.5 ms, and the serial port and page closed. The cause of the earlier disconnect or click delay remains unproven. The failed receipt is retained; 100-cycle qualification and follow-up diagnosis remain pending.

A separate Linux Chromium 139 comparison isolated an inherited host TTY setting: VMIN=0/VTIME=0 produced device-lost stream termination, while changing only VMIN to 1 gave a stock ver reply in 154.1 ms without reset or replug. That finding does not establish the cause of the later reopen failure above. See the Linux Web Serial report for primary browser-source evidence and the bounded host preflight.

The physical RAK3401 Companion on 70bf4bdf passed 21 malformed-request cases with 217 request/reply frames. Its Full Repeater passed the official native setup GUI and 600-second open/closed quiet intervals with power saving on, continuous uptime and zero core error flags. It was returned to the then-current c5fe8a0e Full Companion; the first stock SDK reply took 25.9 ms without an initial retry or settling delay. Original identity, contacts, channels, custom variables, RX power-saving settings and actual packet-stream mode were restored. The planned reboot needed to restore stream mode was separate from the stability measurements. An initial SWD programming failure was recovered and verified; this was not a first-attempt programming pass. These tests did not qualify RAK3401 BLE DFU, LoRa OTA or bootloader updates.

The actual published 9053038f 1.17.1.8 Full V4 installed newer applications over both AP and a controlled shared WiFi LAN, but its old page did not receive HTTP completion. Check ver before retrying a stalled old page. These trials used already expanded application slots; actual phone-hotspot uploads remain untested. The requested legacy small-slot G2 trial now has a verified existing 16 MiB backup and genuinely programmed and verified the official 1.14.1 stock components and small-slot table while preserving NVS. Its first stock USB ver request reached the five-second host command limit; a later read-only probe replied without reset. A separately recorded stock setup restored and verified the original identity, 22 common settings and two Admin ACLs after normal reboots. Password setters were confirmed and the guest password persisted; stock has no admin-password getter. The final start ota returned its expected URL, but the test's AP scan timed out. A subsequent completed native scan found no MeshCore-OTA AP at any BSSID. A later read-only NVS audit identified the test starting-state problem: earlier preconditioning had saved the WiFi long-range protocol flag, which stock inherited. Its long-range AP beacons cannot be received by the ordinary WiFi clients used here. This does not establish a stock AP startup bug. A separately recorded correction changed only the fresh live NVS protocol flag and its entry CRC, with exact readback and unchanged stock components and small-slot table. After stock identity, common settings, ACL and guest/ private-identity checks, a completed fresh scan found the exact G2 OTA AP. This establishes the genuine stock WiFi-only starting boundary. The earlier failed receipts remain failed. The first native migration controller then failed on a missing host iw executable before any HTTP or image-upload step. It may already have associated with the AP; that outcome was not verified. Its return to SlowFi and owned guard cleanup passed. A separately reviewed retry retained the firmware/controller inputs, separately pinned the old runtime log and checked host executables before using fresh guards. It associated with the exact stock AP and observed one native bridge-image POST with the exact bytes, SHA256 and MD5, but the old embedded page did not complete its HTTP response before the uploader deadline. Browser closure, return to SlowFi and guard cleanup passed; that transaction remains failed. A later scan found the exact migration AP. A separately recorded stage2 continuation then verified the actual expanded-layout-ready page and uploaded the exact 1e421ff4 ordinary Full application through the unchanged native page, with matching MD5 and HTTP 200/OK in 14.526 seconds. That upload phase also passed its network return and guard cleanup. The subsequent controlled Pi AP phase failed on a host FileNotFoundError before any final HTTP request. The host's scheduled WiFi refresh also interrupted that AP phase. Its later guard-file cleanup refused an unproven network state; a separate read-only qualification and owned-file cleanup then verified the original network, dead controller and removal of all prior guard profiles and files. A new proof-only attempt stopped before AP activation because reloading services moved the host hold timer's relative deadline. Its failed receipt is retained, and the held host script was restored. The next proof used a fixed absolute hold deadline, but stopped before AP activation when a host-file permission check rejected the actual private service file; its failed receipt and host restoration are preserved. A third proof verified and ran the isolated Pi AP with the independent return timer armed, then reached the five-minute client/DHCP discovery deadline without a verified G2 client or any HTTP request. It returned to SlowFi, removed its owned network resources and restored the host's scheduled WiFi recovery script. Final running-image/layout/identity/settings HTTP verification remains unproven; the successful firmware upload does not establish that final verification. After that completed failed WiFi check, separate USB maintenance installed the 8c4e09275 ordinary Full Observer application. Full application readback and the normal running version matched, while the bootloader, partition table, NVS, OTA selection and checked filesystem region stayed unchanged. This maintenance does not qualify the WiFi-only upgrade. The saved-settings check found RX boosted gain off instead of its original on; the other 21 common settings, identity, passwords and two Admin ACLs matched. A separate checked CLI repair restored gain on and verified all 22 settings. The first extras restoration then missed the five-second CLI deadline while changing bridge source. A later read-only probe found continuous uptime, zero core error flags and the requested source value; it does not establish the missing command acknowledgment or its save duration. After checking that state, a separate restoration completed with the original WiFi pair, saved extras, all 22 common settings, identity, passwords and both Admin ACLs verified. The MQTT worker was running with valid effective configuration; broker connectivity was not tested. Original TTY settings, all three host services and SlowFi were restored, and the exact temporary host executable alias was removed. The earlier timeout and WiFi proof failure remain recorded. The loader correction is included in 88c851080. Its G2 ordinary Full Observer application was independently read back in full after installation, and normal boot matched the exact new runtime and EndF footer. The checked lower 64 KiB, OTA selection and first 64 KiB of the filesystem stayed unchanged. A separate read-only post-boot check verified the original identity, passwords, two Admin ACLs, all 22 common settings, seven supported bridge fields and saved extras. Core error flags were zero; the MQTT worker was running with valid configuration, without a broker-connectivity claim. Original TTY settings, all three host services and SlowFi were restored. This USB maintenance does not qualify the failed WiFi-only final verification. The fresh all-board build and V4 hardware checks remain pending. These are separate outcomes; the initial failed transactions remain failed. The earlier c5 AP upload success does not turn those old HTTP-completion failures into passes. The upgrade guide keeps the old and new updater behavior separate.

Original host services, temporary network changes and owned test resources were restored after the historical completed hardware checks. The current new-source V4 native AP OTA trial has not yet produced a verified result; its return to SlowFi and original host-service state also remain unverified. The legacy G2 check established the stock starting boundary with its original identity, common settings and ACLs verified, then completed the expansion and Full application upload over WiFi. It has not yet qualified the final running image through HTTP. Post-verdict 88c851080 G2 firmware readback, normal boot, original-settings acceptance and host restoration passed separately over USB. The all-board build and current V4 hardware qualification remain pending. These checks keep publication pending. Build qualification does not establish physical compatibility on every board. Quiet USB trials do not measure MCU sleep/current draw, stack high-water, sustained log backpressure or long-term fleet reliability. Linux native-browser tests required host TTY preparation; they do not qualify every browser or operating system. Hardware CDC has finite buffers, and closing a Linux TTY does not necessarily produce a hardware session reset. See the historical V4 console report and USB backpressure results for their exact source revisions and measured scope.