Add WiFi provisioning, admin web UI, MQTT publisher, and chat decoder for ESP32-S3 boards#2623
Open
zfouts wants to merge 12 commits into
Open
Add WiFi provisioning, admin web UI, MQTT publisher, and chat decoder for ESP32-S3 boards#2623zfouts wants to merge 12 commits into
zfouts wants to merge 12 commits into
Conversation
Removed links to outdated resources and links
Include the 'ver' command for retrieving the firmware version
… for Xiao S3 WIO
New helpers under src/helpers/esp32/:
- WifiProvisioning.{h,cpp}: AP-first captive portal (SSID MeshCore-Setup-XXXX,
password meshcore123), NVS-persisted STA credentials in namespace mc-wifi,
3-attempt STA fallback to AP, USER_BTN long-press wipe, defensive
WiFi.disconnect + setAutoReconnect to recover from first-attempt auth fails
seen on some routers.
- WifiAdminUI.{h,cpp}: AsyncWebServer admin UI with WebSocket packet feed at
/ws, chat panel for decoded GRP_TXT messages, console (CLI over /api/cmd),
status/stats/radio/packets/neighbours/radio-config endpoints, /channels
page (manage group PSKs), /blacklist page (wildcard name patterns to drop
ADVERTs from), inline editors for TX power / coding rate / path hash mode.
Shared /style.css with dark-mode CSS variables; sub-pages link to it.
- WifiCliBridge.{h,cpp}: line-based TCP CLI server on port 5050, routes
CR-terminated lines through handleCommand.
- MqttPublisher.{h,cpp}: PubSubClient-based publisher with 16-slot async
queue (drops oldest under burst), NVS broker config in namespace mc-mqtt,
publishes RX (logRxRaw) and TX (logTx) packets to <topic>/rx and
<topic>/tx as JSON with rssi/snr/raw-hex.
Role wiring:
- examples/companion_radio/main.cpp: WIFI_PROVISIONING gate replaces the
baked WIFI_SSID/WIFI_PWD WiFi.begin() path; SerialWifiInterface still
runs on TCP 5000 once STA is up. Optional WIFI_SSID/WIFI_PWD become
bootstrap defaults seeded into NVS on first boot.
- examples/simple_repeater/main.cpp: full wiring of provisioning, admin UI,
TCP CLI bridge, and MQTT publisher under WIFI_PROVISIONING + MQTT_PUBLISHER.
_RepeaterMeshInfo adapter delegates listChannels/addChannel/listBlocked/
addBlocked/removeBlocked/formatRadioConfig to MyMesh.
- examples/simple_repeater/MyMesh.{h,cpp}: chat decoder (Public channel
pre-configured with the well-known PSK; user channels added via /channels
and stored in NVS namespace mc-chans). NVS-persisted forwarding blacklist
in namespace mc-block with glob patterns (* and ?) matched against
advertised names; hits drop the ADVERT in allowPacketForward and skip
neighbour-table insert in onAdvertRecv. logRxRaw and logTx hook calls to
wifiAdmin* and mqtt* extern functions.
- examples/simple_room_server/main.cpp: WIFI_PROVISIONING brings up
provisioning, admin UI, and TCP CLI bridge (no MQTT, no chat decode).
Infrastructure:
- src/helpers/ESP32Board.cpp: move legacy OTA AsyncWebServer from port 80
to 8306 so it doesn't collide with provisioning's port 80 server when
both are running.
- variants/xiao_s3_wio/platformio.ini: override LoRa region defaults from
EU (869.618 MHz, SF8) to USA/Canada (910.525 MHz, SF7) at the Xiao_S3_WIO
base via build_unflags. Modify Xiao_S3_WIO_companion_radio_wifi to use
WIFI_PROVISIONING instead of compile-time SSID/PWD. New envs
Xiao_S3_WIO_repeater_wifi (with MQTT_PUBLISHER + densaugeo/base64 +
PubSubClient deps) and Xiao_S3_WIO_room_server_wifi.
Hardware-validated on a Seeed XIAO ESP32-S3 + Wio-SX1262: provisioning,
STA reconnect, web admin, chat decoding from Public channel, blacklist,
and live editing of TX power / coding rate / path hash mode all work.
MQTT publishing and full Companion/Room Server boots are code-compiled
but not yet hardware-tested.
variants/heltec_v4/platformio.ini:
- New env heltec_v4_repeater_wifi: WIFI_PROVISIONING + WifiAdminUI +
WifiCliBridge + MqttPublisher on the OLED variant. Mirrors
Xiao_S3_WIO_repeater_wifi.
- New env heltec_v4_room_server_wifi: provisioning + admin + CLI bridge
(no MQTT).
- New env heltec_v4_tft_repeater_wifi: same feature set as the OLED
repeater, on the ST7789LCDDisplay TFT variant.
- New env heltec_v4_tft_room_server_wifi: same as OLED room server, on TFT.
- Modify heltec_v4_companion_radio_wifi and heltec_v4_tft_companion_radio_wifi:
drop the baked WIFI_SSID/WIFI_PWD, switch to WIFI_PROVISIONING, add
${esp32_ota.lib_deps}. Optional bootstrap creds are now commented out.
examples/simple_repeater/UITask.cpp,
examples/simple_room_server/UITask.cpp:
- Add WiFi status to the home screen under freq/bw/cr (gated on
ESP_PLATFORM + WIFI_PROVISIONING). In STA mode shows IP + RSSI in
green; in AP mode shows the captive-portal SSID in yellow. Lets a
user with a display see whether the node is ready or still expecting
WiFi setup, without opening the web UI.
Builds verified clean for all six new/modified Heltec V4 envs plus a
Xiao_S3_WIO_repeater_wifi regression check.
…faults to upstream variants/xiao_s3_wio/platformio.ini: - Drop the build_unflags / -D LORA_FREQ=910.525 / -D LORA_SF=7 overrides. Xiao_S3_WIO base now inherits arduino_base defaults (869.618 MHz, BW62.5, SF8). Users pick their region at runtime from the admin UI instead of baking it into firmware at build time. src/helpers/esp32/WifiAdminUI.cpp: - Radio config card: Frequency is now a number input (150-2500 MHz, step 0.025). Bandwidth and Spreading Factor are selects with the full legal value sets (10 BW options for SX1262; SF5-12). Each change fires `set radio f,b,s,c` with the other current values, prompting reboot to apply. - Add region preset row below the card: USA/Canada (910.525/62.5/SF7/CR5), EU868 (869.618/62.5/SF8/CR5), Legacy Wide (869.525/250/SF11/CR5). Clicking a preset confirms then applies all four params in one call. - Refactor setCr to share a setRadio(freq,bw,sf,cr,reason) helper used by all four "set radio" callers (manual edits + presets). Verified: Xiao_S3_WIO_repeater_wifi, heltec_v4_repeater_wifi, and heltec_v4_tft_repeater_wifi all compile clean.
…iants
For every WiFi-capable ESP32-S3 board MeshCore supports, add the same env
pair we shipped for Xiao S3 WIO and Heltec V4:
- *_repeater_wifi: WifiProvisioning + WifiAdminUI + WifiCliBridge + MqttPublisher
- *_room_server_wifi: WifiProvisioning + WifiAdminUI + WifiCliBridge
Where the variant already had a *_companion_radio_wifi env with baked
WIFI_SSID/WIFI_PWD, switch it to -D WIFI_PROVISIONING=1 and add
${esp32_ota.lib_deps} (matches the Heltec V4 / Xiao change).
variants/heltec_v3/platformio.ini:
- Add Heltec_v3_repeater_wifi, Heltec_v3_room_server_wifi (SSD1306Display)
- Modify Heltec_v3_companion_radio_wifi to use provisioning
- WSL3 sub-family untouched
variants/heltec_tracker/platformio.ini:
- Add Heltec_Wireless_Tracker_repeater_wifi, _room_server_wifi (ST7735Display)
variants/heltec_tracker_v2/platformio.ini:
- Add heltec_tracker_v2_repeater_wifi, _room_server_wifi (ST7735Display)
- Modify heltec_tracker_v2_companion_radio_wifi to use provisioning
variants/heltec_wireless_paper/platformio.ini:
- Add Heltec_Wireless_Paper_repeater_wifi, _room_server_wifi (E213Display)
variants/heltec_t190/platformio.ini:
- Add Heltec_T190_repeater_wifi_, _room_server_wifi_ (ST7789Display inherited
from base; trailing underscore matches the existing env naming convention
in this file)
variants/rak3112/platformio.ini:
- Add RAK_3112_repeater_wifi, RAK_3112_room_server_wifi (headless, no display)
- Modify RAK_3112_companion_radio_wifi to use provisioning
- Bridge envs (rs232, espnow) untouched
variants/lilygo_teth_elite/platformio.ini:
- Add LilyGo_TETH_Elite_sx1262_repeater_wifi, _room_server_wifi (headless)
variants/heltec_e213/platformio.ini:
- Add Heltec_E213_repeater_wifi, Heltec_E213_room_server_wifi (E213Display)
variants/heltec_e290/platformio.ini:
- Add Heltec_E290_repeater_wifi, Heltec_E290_room_server_wifi (E290Display)
All new envs verified to compile clean. Existing BLE / USB / serial /
plain-repeater / plain-room-server / sensor / bridge envs unchanged: this
is purely additive, users pick their connectivity at flash time.
src/helpers/esp32/WifiAdminUI.cpp: - Pull the Radio config card out of the small `.cards` grid (which uses repeat(auto-fit, minmax(220px, 1fr)) and squeezed editor selects to the point that "2B (recommended)" was clipped and the MHz / dBm unit labels next to the freq and tx_power inputs were pushed offscreen). - New full-width `.rcard` section with looser inner grid (minmax(9em,11em) for the label column, auto for the value column). - Move unit suffixes into a dedicated `<span class=unit>` so they stay next to their input instead of disappearing under right-align width competition. - Region preset chips now render in a dedicated #rcfg-presets container with its own border-top, so they read as a related but separate row rather than a fourth column getting absorbed into the kv grid. - Drop the inappropriate `class=kv` on `#rcfg` itself (it now wraps a kv child instead of being the grid). Verified visually via Playwright screenshot before/after on a live Xiao S3 WIO repeater: editors aligned, units visible, presets fit on one row.
|
Have you seen https://github.com/agessaman/MeshCore/tree/mqtt-bridge-implementation-flex? It also adds native MQTT upload for ESP32-based units and has been in active development for a while now. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds runtime WiFi provisioning (AP captive portal → STA, NVS-persisted) and a
self-contained web admin / TCP-CLI / MQTT stack to MeshCore's ESP32-S3
variants. Everything is opt-in via build flags and gated by
#ifdef WIFI_PROVISIONING/#ifdef MQTT_PUBLISHER, so all existing envs areunchanged. New
_repeater_wifiand_room_server_wifienvs are added forevery WiFi-capable ESP32-S3 board MeshCore supports; existing
_companion_radio_wifienvs are migrated from bakedWIFI_SSID/WIFI_PWDto the provisioning portal.
Motivation
Today, getting a MeshCore node onto a network requires baking the SSID and
password into firmware at compile time, and there is no in-firmware
remote-admin surface beyond the serial CLI. For users running headless
repeaters and room servers - exactly the roles where being unable to plug
in a USB cable matters most - that means re-flashing to change networks
and no live visibility into mesh traffic without external tooling.
This PR closes that gap on the ESP32-S3 family (where the chip already has
WiFi + BLE silicon that today is mostly idle in repeater/room-server
roles):
pick a network, save. Falls back to AP automatically after 3 failed STA
attempts so a router password change doesn't brick the node.
Status, mesh/radio/packet stats, live decoded chat (Public channel +
user-added group PSKs), live raw packet feed, editable LoRa params,
region presets, name-pattern forwarding blacklist, MQTT publisher.
external dashboards / Grafana / Home Assistant.
What's included
New shared helpers (under
src/helpers/esp32/)WifiProvisioning.{h,cpp}MeshCore-Setup-XXXX, passwordmeshcore123), NVS-persisted STA creds in namespacemc-wifi, 3-attempt STA fallback to AP,USER_BTNlong-press wipe (graceful no-op ifPIN_USER_BTN<0), defensiveWiFi.disconnect(true,true)+setAutoReconnect(true)to recover from first-attempt auth failures observed on some routers.WifiAdminUI.{h,cpp}AsyncWebServeradmin UI: home (status / radio config / mesh stats / radio stats / packet stats / network),/channels(manage group PSKs),/blacklist(wildcard name patterns to drop ADVERTs from),/mqtt-setup. WebSocket/wsstreams every RX and TX packet plus decoded chat as JSON. Console panel with inline CLI input, command history (localStorage), preset buttons, and/api/cmdPOST routed through the samehandleCommandthe/style.csswith dark-mode CSS variables; all sub-pages link to it.WifiCliBridge.{h,cpp}MqttPublisher.{h,cpp}PubSubClient-based publisher with 16-slot async queue (drops oldest under burst), NVS broker config in namespacemc-mqtt, configurable via/mqtt-setup. Publishes RX (logRxRaw) to<topic>/rxand TXlogTx) to<topic>/txas JSON.Role wiring
examples/companion_radio/main.cpp—WIFI_PROVISIONINGgate replacesthe baked
WIFI_SSID/WIFI_PWDWiFi.begin()path.SerialWifiInterfacestill runs on TCP 5000 once STA is up. Optional
WIFI_SSID/WIFI_PWDbecome bootstrap defaults seeded into NVS on first boot.
examples/simple_repeater/main.cppandMyMesh.{h,cpp}— wiresprovisioning, admin UI, CLI bridge, MQTT publisher.
Publicgroup channelPSK;
loadPersistentChatChannels()reads user-added channels from NVSnamespace
mc-chanson boot.searchChannelsByHash+onGroupDataRecvoverrides extract sender + text from decryptedGRP_TXTpayloads and push to the WS feed.*and?) matched againstthe advertised node name. Hits drop the ADVERT in
allowPacketForwardand skip neighbour-table insert inonAdvertRecv. Persisted in NVS namespacemc-blockwith per-patternhit counters.
logRxRawandlogTxcallwifiAdminPush*andmqttPublish*externhelpers (no-ops if their respective modules aren't compiled in).
examples/simple_room_server/main.cpp— provisioning + admin + CLIbridge (no MQTT, no chat decode by default).
examples/{simple_repeater,simple_room_server}/UITask.cpp— render WiFistate on the home screen below freq/bw/cr: green
IP:+RSSI:in STAmode, yellow
AP:SSID in setup mode. Gated byWIFI_PROVISIONINGsonon-WiFi envs are unaffected.
Infrastructure
src/helpers/ESP32Board.cpp- move legacy WiFi-OTAAsyncWebServerfrom port 80 to 8306 to avoid colliding with the provisioning web
server when both code paths are present on the same boot.
New / modified build envs
Pattern: every WiFi-capable ESP32-S3 board gets a new
_repeater_wifiand_room_server_wifienv; the existing_companion_radio_wifi(wherepresent) flips from baked SSID/PWD to provisioning.
xiao_s3_wioXiao_S3_WIO_repeater_wifi,Xiao_S3_WIO_room_server_wifiXiao_S3_WIO_companion_radio_wifiheltec_v4(OLED + TFT)heltec_v4_repeater_wifi,heltec_v4_room_server_wifi,heltec_v4_tft_repeater_wifi,heltec_v4_tft_room_server_wifiheltec_v4_companion_radio_wifi,heltec_v4_tft_companion_radio_wifiheltec_v3Heltec_v3_repeater_wifi,Heltec_v3_room_server_wifiHeltec_v3_companion_radio_wifiheltec_trackerHeltec_Wireless_Tracker_repeater_wifi,_room_server_wifiheltec_tracker_v2heltec_tracker_v2_repeater_wifi,_room_server_wifiheltec_tracker_v2_companion_radio_wifiheltec_wireless_paperHeltec_Wireless_Paper_repeater_wifi,_room_server_wifiheltec_t190Heltec_T190_repeater_wifi_,_room_server_wifi_rak3112RAK_3112_repeater_wifi,RAK_3112_room_server_wifiRAK_3112_companion_radio_wifililygo_teth_eliteLilyGo_TETH_Elite_sx1262_repeater_wifi,_room_server_wifiheltec_e213Heltec_E213_repeater_wifi,Heltec_E213_room_server_wifiheltec_e290Heltec_E290_repeater_wifi,Heltec_E290_room_server_wifiNo existing envs were removed or had their existing behavior changed
beyond the explicit
_companion_radio_wifimigration noted above. BLE,USB, serial, plain-repeater, plain-room-server, sensor, and bridge envs
are all untouched.
Hardware testing
/ SF7 / BW62.5 / CR5): captive portal, STA reconnect (including a
first-attempt
WIFI_REASON_AUTH_FAILthat the defensive code nowrecovers from automatically), web admin UI, packet feed via WebSocket,
chat decoding from the Public channel, blacklist drops verified against
a live node, inline editing of TX power / coding rate / path hash mode,
region preset switching.
(
pio run -e <env>clean for every new_repeater_wifi; spot-builtCompanion + Room Server flavors of Heltec V4).
display variants, and most boards beyond Xiao have not yet been
hardware-tested. The shared modules are board-agnostic ESP32 code so
the per-board risk is limited to integration glue, but worth flagging
for reviewers.
Things explicitly NOT done in this PR
view stats, reboot, wipe creds, or run arbitrary CLI commands. This
matches the threat model assumed by today's serial CLI (trusted
physical/local access) but is worth a separate hardening pass before
recommending exposure to untrusted LANs.
PubSubClientover TCP,HTTP-only).
meshcore123, same on every device. Fine forinitial bring-up; a per-device-derived default would be a worthwhile
existing
UITaskcode paths for repeater and room server). Other TFTboards' UITasks would benefit from the same treatment in a follow-up.
have WiFi hardware or (for RP2040 + Pico W) don't expose it in
MeshCore today. The modules are ESP32-specific by design.
picked at compile time). Running both simultaneously is a bigger
refactor and isn't done here.
Test plan for reviewers
pio run -e Xiao_S3_WIO_repeater_wifi -e heltec_v4_repeater_wifi -e RAK_3112_repeater_wifiMeshCore-Setup-XXXXappears, password
meshcore123connects, captive portal pops up,/scanlists nearby networks, save → reboot → STA.transmits, confirm decoded chat appears from a Public-channel
message, confirm CLI commands (
neighbors,stats,set tx 20)run through
/api/cmdand through the TCP CLI bridge on port 5050./blacklist, add a glob matching another node's name andverify the hit counter increments while that node's adverts no
longer show up in
neighbors./mqtt-setup, point at a broker, reboot, confirm<base>/rxand<base>/txmessages flow.startOTAUpdate) still workson its new port 8306 and doesn't clash with the provisioning
server.
Process notes for maintainers
A few things I'd like to surface up front:
larger changes. Happy to open one and split this into smaller PRs if
you'd prefer — provisioning could land first, admin UI second, MQTT
third, blacklist + chat decoder fourth.
mainnotdev. Will rebase ontodevon request.use more modern C++ (range-for, lambdas,
String-based JSONassembly). Happy to refactor toward whatever matches the rest of the
esp32 helpers if there's a preferred style.