6.8 KiB
Mesh America configurator — provider catalog
ZephCore firmware is published to the Mesh America Device Configurator as a third-party provider catalog. Users pick a board in the app and flash ZephCore directly from the browser.
What to send Mesh America
Provider name: ZephCore
Catalog URL: https://raw.githubusercontent.com/liquidraver/ZephCore/firmware-dist/catalog.json
(Send this once, after the first master build has run and created the firmware-dist
branch. Validate first at https://apps.meshamerica.com/validate.)
How it works
gen_provider_catalog.py turns a release's firmware assets into catalog.json
(the provider-spec schema: version -> {notes, files:[{type,name,url}]} with
absolute HTTPS URLs). The build firmware workflow runs it in the
publish-catalog job and force-pushes the firmware + catalog to the
firmware-dist orphan branch on every master build.
Hosting / CORS. The configurator runs in the browser and fetch()es both the
catalog and each firmware binary, so every response needs
Access-Control-Allow-Origin: *. GitHub Release assets do not send it (they
redirect to release-assets.githubusercontent.com, which omits the header), so we
cannot serve firmware from the normal release. Instead:
| Artifact | Host | Why |
|---|---|---|
catalog.json |
raw.githubusercontent.com/.../firmware-dist/catalog.json |
CORS *, always fresh (raw doesn't cache branch refs) |
| firmware binaries | cdn.jsdelivr.net/gh/liquidraver/ZephCore@firmware-dist/<file> |
CORS *, CDN-backed; filenames carry the git hash so they're effectively immutable |
The normal timestamped GitHub Release (with all the same binaries) is still created for manual downloads and OTA — the configurator pipeline is additive.
Device mapping
Boards whose name matches an official MeshCore device fold into that device
(our firmware shows as extra options under the existing tile). Boards MeshCore
doesn't have become new ZephCore-badged tiles. The mapping table lives in
BOARDS in gen_provider_catalog.py; adjust it there when boards are added or
renamed. Names must match MeshCore's canonical config.json
(meshcore-dev/flasher.meshcore.io) exactly to fold — the validator flags
mismatches.
Notes on the mapping:
-
ESP32 offers both
flash-wipeandflash-update.flash-wipe= the-merged.bin(MCUboot + app) written at0x0.flash-update= the-update.bin(MCUboot-signed app) written at0x10000. As of 2026-07-09 ZephCore's ESP32 app slot is at0x10000(seeboards/esp32/<board>/partitions.overlay), matching Mesh America's fixed flash-update offset — so app-only updates that keep settings now work.build.shships-update.binfor both ESP32 companion and repeater roles. Classic-ESP32 (T-Beam) uses simple boot (no MCUboot), produces no-update.bin, and is naturally flash-wipe-only. -
Companion firmware is one image serving BLE + USB; it's listed under both
companionBleandcompanionUsb(same file). Native-Linux companions use a customcompanionTcprole. -
Heltec T114 lists screen and "No screen" variants (subTitle) under one tile.
-
Native-Linux boards (femtofox, rak6421) are
noflashdownload-only tiles. -
nRF54L15 boards (ME25LS02) are
noflashtoo, for a different reason: the SoC has no USB peripheral, so no bootloader exists and nothing the configurator can drive is possible. They publish a.hexas a plain download, flashed over SWD, and the companion is listed undercompanionBleonly — there is no USB transport to offer. -
MG24 and STM32WL are
noflashdownload-only for the same reason as the nRF54L15 — no USB device peripheral, so no bootloader and no browser-flashable path. Both publish a.hexflashed over SWD. XIAO MG24 has BLE (Silabs controller blob) so its companion iscompanionBle. LoRa-E5 mini has neither BLE nor USB: its companion speaks MeshCore serial framing on USART1, which reaches the host as an ordinary serial port through the board's USB-UART bridge, so it is listed undercompanionUsb. Neither board exists in MeshCore's catalog at all, so both are ZephCore-only tiles. -
Thumbnails: folded devices inherit MeshCore's image automatically (device-level fields come from the official entry on merge), so only the new tiles set a
tooltip. Those reuse the configurator's own image set via jsDelivr (IMG_BASEin the script); boards without dedicated art fall back to a neutral LoRa icon.- To ship art of our own, drop the file in the repo's
img/dir and setown_imgto its filename.build.shcopiesimg/*intofirmware/alongside the firmware, and the generator resolvesown_imgagainst--url-base— so it lands on the samefirmware-distbranch and CDN as everything else, with no host hardcoded anywhere. - Copy vendor product shots in, don't hot-link them. A vendor CDN path is theirs to
reshuffle, and a tile whose picture 404s is worse than one that never had a picture.
img/meshtracker_x1.jpg(Seeed's SenseCAP MeshTracker X1 photo) is the first of these.
- To ship art of our own, drop the file in the repo's
-
Erase / "wipe settings" (nRF52) uses ZephCore's own formatter. MeshCore's official erase targets a different flash layout and only partially wipes a ZephCore node (observed on a Wio Tracker L1: nuked
channels, left identity/prefs/contacts, LittleFS half-corrupted). Since spec §4a we override it: each nRF52 firmware option carries anerasepointing at ZephCore's formatter. The formatter is SoftDevice-specific (v6 and v7 have different partition maps), soSOFTDEVICEin the generator maps every nRF52 board toSoftDevice_v6_formatter.ziporSoftDevice_v7_formatter.zip;build.shpublishes both fromformatter/under stable, un-hashed names so the erase URLs never change. The.zipdrives the automated DFU erase flow; the.uf2is published too as the manual drag-and-drop fallback.erasegoes on the firmware option, never the device object — a device-leveleraseis an official-only field that providers get silently ignored + warned for (§4a).- ESP32 has no
erase(the field is nRF52-only);flash-wipealready reinstalls cleanly. - Users can still factory-reset on-device without the flasher: the
erasecommand over the USB serial CLI, the app's factory reset, or a reflash (ZephCore auto-formats on first boot when it detects an incompatible/blank FS). All format/lfs+/ext+ the NVS bond partition.
Local test
python gen_provider_catalog.py --firmware-dir firmware \
--url-base "https://cdn.jsdelivr.net/gh/liquidraver/ZephCore@firmware-dist" \
--version v0.0.0 --out catalog.json
It validates the output against the spec's hard requirements and prints a fold/new summary; a non-zero exit means a schema error.