Commit Graph
188 Commits
Author SHA1 Message Date
mikecarper 95aca52b4e Add per-profile TX routing and bridge filtering
Persist Companion TX preferences per contact and channel. Default repeater,
room, and sensor replies to both active TX profiles, with a reply-only force
option for an RX-only secondary profile. Track both reply copies before a
temporary-radio handoff and account for OTA copies under queue backpressure.

Add bridge/crossover filter modes and the third built-in wardriving filter,
plus compact filter CLI syntax, documentation, and CI coverage.

Fix quoted target names being interpreted as slot/key selectors, partial
recovery of invalid saved reply settings, filter suspension during tempradio2,
and unnecessary packet allocation while OTA traffic is throttled.

Validation: 1,477 native tests, 52 Python integration tests, 29 filter UI tests,
and five firmware builds covering ESP32, nRF52, and STM32 passed.
2026-09-15 01:58:43 -07:00
mikecarper 794cf15395 Preserve Full USB packet logging and verify packaged firmware 2026-09-13 15:34:00 -07:00
mikecarper a7f58dd437 Refresh 1.17.1.6 picker metadata and preserve capacity directions 2026-09-13 12:51:12 -07:00
mikecarper fff92f0588 Report portable-slot exclusions alongside release failures 2026-09-13 11:31:05 -07:00
mikecarper 2dcc8ac6d7 Publish qualified partial release matrices with explicit failure reports 2026-09-13 09:19:17 -07:00
mikecarper fa010196b1 Merge PR #7 with reviewed ExpressLRS power and memory fixes
Integrate ExpressLRS TX module support and its stacked ESP32 heap changes.
Use the approved Linkflow calibration (17-30 dBm), preserve the PA drive
and output path after radio recovery, and keep LoRa OTA enabled.

Preserve stored ACLs and filters on allocation failure, release owned
client/filter buffers, service heap OTA contexts on Companions, release
self-serving workspaces after TempRadio, and reset staged-resume state
when a context is released. Keep manual staging and active operations
alive. Account for all moved allocations in the runtime RAM gate.

Validation: 1,393 native cases; radio-power, heap-context, ACL persistence,
shared-queue transfer, display/inbox, radio receive, and memory regressions.
Firmware builds passed for Linkflow, Heltec V2 Companion, T-Beam MQTT
repeater, Heltec V4 R8 MQTT repeater, RAK4631 repeater, and Indicator Full.
Physical verification awaits access to the currently offline lab Pi.
2026-09-10 22:06:16 -07:00
mikecarper 602dbfe3d9 Fix inherited nRF52 USB READY hang in build-local TinyUSB driver 2026-09-10 02:37:15 -07:00
MUSTARDTIGERFPV c6d71b969a Enable the on-demand mOTA context for every classic ESP32 build
Move OTA_HEAP_CONTEXT from two hand-edited envs to a pre-script gated on
build.mcu == "esp32", so every classic ESP32 image gets it and none can drift.
S2/S3/C-series and nRF52 keep the .bss singleton: they have no equivalent
static-DRAM ceiling, so there a guaranteed-present workspace is the better
trade for what is ultimately a recovery path. It has to be a build flag rather
than a header default, because OTA_HEAP_CONTEXT must hold the same value in
every translation unit that sees OtaContext.h - OtaContext.cpp included - and a
header test on CONFIG_IDF_TARGET_ESP32 would depend on include order relative
to sdkconfig.h. The script defers to OTA_SHARED_COMPANION_QUEUE where a Full
Companion recipe already owns the storage.

Fix a gap this exposes in the roles that now use it. Only CLI entry points
acquire the context, so once it was released, a repeater with the temporary
radio profile up would no longer serve or announce its own firmware - LoRa OTA
would look enabled and silently do nothing. ota_service_temp_radio_context()
holds the workspace for exactly the temp-radio window and hands it back
outside it, which is where the saving was coming from anyway. Wired into the
repeater, room server and sensor loops; the Companion keeps its own
acquire-on-host-demand policy, since its context is borrowed from the offline
message queue and must not be taken speculatively.

Static DRAM, classic ESP32 (bytes occupied of a 124,580 region):
  Heltec_v2_repeater                   108,332 -> 70,732
  Heltec_v2_room_server                 83,716 -> 68,300
  Heltec_v2_companion_radio_ble        123,236 -> 107,772  (was failing on main)
  Tbeam_SX1262_repeater                 86,932 -> 71,468
  Tbeam_SX1262_repeater_observer_mqtt  121,132 -> 83,532   (was failing)
2026-09-09 01:24:00 -07:00
mikecarper b9138c13b2 Allow local CLI maintenance across direct connections 2026-09-08 21:44:57 -07:00
mikecarper 5e6a74be50 Enable the shared terminal on WiFi-only Companions 2026-09-08 19:56:12 -07:00
mikecarper d178cf1474 Share the Companion terminal with the WiFi console 2026-09-08 19:48:15 -07:00
mikecarper cb79dcd4e3 Preserve MQTT settings across slot changes 2026-09-08 18:55:00 -07:00
mikecarper aa8caa4ed2 Unify device controls and restore the WiFi console 2026-09-08 18:36:23 -07:00
mikecarper eeea15ef01 Use compact message text and sender lines on all small displays 2026-09-08 13:36:40 -07:00
mikecarper a7f088290b Add a V4 Picopixel message font trial with longer previews 2026-09-08 13:22:53 -07:00
mikecarper b68aa1c685 Enable dual WiFi OTA slots for the smaller 4 MiB NimBLE trials 2026-09-08 12:36:43 -07:00
mikecarper e0a229fb91 Publish memory-corrected 1.17.1.5 catalogs and picker directions 2026-09-08 02:53:48 -07:00
mikecarper aa20e9278e Gate every firmware build on runtime RAM and share nRF52 mOTA storage 2026-09-08 02:09:26 -07:00
mikecarper 27616e2e5b Report nRF52 LoRa mOTA capabilities and storage requirements 2026-09-06 23:50:24 -07:00
mikecarper b781b3df89 Show role-specific feature commands in firmware picker 2026-09-06 04:52:02 -07:00
mikecarper 2630379365 Stage 1.17.1.5 local release assets and document OTAFIX 2.4.6
Firmware Builder / create-release (push) Canceled after 0s
Firmware Builder / build (push) Canceled after 0s
Firmware Builder / generate-build-matrix (push) Canceled after 0s
Build Repeater Firmwares / build-repeater-firmwares (push) Canceled after 0s
2026-09-05 14:04:39 -07:00
mikecarper 49dcba5c6e Add retained-RAM staging for nRF52 mOTA 2026-09-05 12:08:21 -07:00
mikecarper d4c8890eae Match Halo Keymind Cascade dev release naming and include WM1110 DFU packages 2026-09-05 09:08:42 -07:00
mikecarper 02020513f4 Prepare 1.17.1.5 USA Cascade release and verify update capabilities 2026-09-05 08:59:50 -07:00
mikecarper f8dfcaa240 Enforce classic ESP32 memory budgets and safe image merging 2026-09-05 08:22:56 -07:00
mikecarper 7782bd562f Embed fixed ESP32 firmware identity 2026-09-03 12:16:40 -07:00
agessaman cdde4bf673 feat(mqtt): add link diagnostics and improve network logging 2026-09-02 21:37:30 -07:00
mikecarper 9e874917b4 Fix Windows Full firmware builds 2026-09-02 11:41:24 -07:00
agessaman 50e2b2acba feat: add automatic network failover 2026-09-01 21:18:22 -07:00
mikecarper fcd1f8cc6c Unify companion BLE and WiFi setup flows 2026-09-01 01:25:00 -07:00
mikecarper 8f413b0610 Add SenseCAP Indicator N16R2 profile 2026-08-31 18:29:38 -07:00
mikecarper 9fd580c89e Harden marathon-tested OTA and hardware paths
Add durable TempRadio, ACL, clock, bridge, GPS/I2C, USB logging, and Indicator recovery safeguards together with expanded automation, build/profile contracts, release metadata, and the hardware validation ledger.
2026-08-30 19:26:15 -07:00
mikecarper e26d48e4ca Fix ESP32 Full Companion partition policy 2026-08-29 20:26:27 -07:00
mikecarper 6d6c89e411 fix: harden ESP-NOW and full companion networking
Add selectable shared ESP-NOW channels, raw/wrapped bridge compatibility, and bounded fragmentation for maximum-size packets.\n\nGive ESP32 Full profiles WiFi coexistence, stabilize WebConfig and USB terminal lifecycles, and keep disabled bridges stopped during observer updates.\n\nUpdate generated UI, firmware selection, documentation, and regression coverage.
2026-08-28 16:36:34 -07:00
mikecarper d6519baa0f feat: consolidate full companion runtime profiles 2026-08-28 08:47:26 -07:00
mikecarper 1d836c0473 feat: unify companion builds and USB runtime modes 2026-08-27 15:06:26 -07:00
mikecarper f1515ef1c6 feat: retain multi-channel voltage telemetry 2026-08-25 22:51:22 -07:00
mikecarper c95a6249be feat: order flood rules by channel specificity 2026-08-25 21:58:08 -07:00
mikecarper 8705e7f551 feat: add selective flood retry rules 2026-08-25 21:38:23 -07:00
mikecarper ba2170d21b feat: add capability-aware firmware build profiles 2026-08-25 20:07:09 -07:00
mikecarper 177eb06745 Add shared-slot nRF52 bootloader updates 2026-08-21 00:55:01 -07:00
mikecarper 7a4da3ccfb Fix Cascade power saving, USB Companion, and mOTA flows 2026-08-18 14:02:10 -07:00
mikecarper a514b2a6d5 Stabilize T-Beam full companion startup 2026-08-16 11:00:55 -07:00
mikecarper 933697f65c Fix Companion device power saving 2026-08-15 17:58:37 -07:00
mikecarper 9161dfd7d5 Expose RX power saving in WebConfig 2026-08-15 09:07:41 -07:00
agessaman 74a3df3206 build(tls): bind the reduced-TLS archives to the framework they were built against
The manifest said "rebuild these for every espressif32 platform bump" and nothing
enforced it. mbedtls_4k.py verified the staged archives against the manifest's own
hashes, which proves the pair agrees with itself and nothing more: bump the
platform without rebuilding and every check still passes while the link takes
mbedTLS built against a different IDF. That fails at runtime on struct-layout
drift, not at the link, which is the failure the mechanism claimed to prevent.

Fingerprint the framework's own mbedTLS archives — the ones ours displace — as
stock: lines in the manifest and check them before the build. If the framework
moves, the staged pair is stale by construction and the build stops with the
replacement hashes printed ready to paste. Stronger than comparing a version
string: framework-arduinoespressif32 versions independently of the platform, and
its archives are what actually has to match.

The lib directory is resolved by trying the layouts espressif32 has used rather
than hardcoding one, and failing closed if none holds all four archives. The fetch
script ignores the new lines; its known-arches hint skips them so they cannot be
reported as architectures.
2026-08-14 18:41:29 -07:00
agessaman daec2e4edd fix(mqtt): address review — stopped clients, late allocation, fail-open map check
Three defects found reviewing the preceding commits.

1. reconnectSlotClient() stranded a STOPPED client, reintroducing the very bug
   this branch fixes. It only rebuilt when isStarted() was true and otherwise
   fell through to reconnect(), which is a documented no-op on a stopped client
   — so nothing restarted it, at any rung, including the breaker probe. The
   WiFi-transition teardown reaches exactly this state: it calls the hard
   disconnect(), clearing _started while initial_connect_done stays set, so
   after WiFi returned the slot could never come back. Now a stopped client is
   started with connect() before the rebuild/reuse decision is considered.

   The post-NTP credential refresh had the same exposure — it called
   reconnect() directly — so it now goes through the helper too, still reusing
   the transport since its fault is stale credentials, not the transport.

2. Allocating the neighbors buffer on first use let a stopped bridge allocate.
   A neighbour discovery started before a stop can complete after it, and
   neither caller rechecks bridge state, so requestPublishNeighbors() would
   allocate 4 KB after releaseRuntimeBuffers() had already run and strand
   _neighbors_publish_pending with no task to consume it. end() then returns
   early on !_initialized, retaining the buffer until a later begin/end or a
   reboot. Guarded on isRunning(), the same flag end() checks.

   The release/acquire handoff itself was confirmed sound: the allocation and
   copy precede the release store, and the task loop reads the pointer only
   after its acquire load, so a half-published pointer is not observable.

3. The post-link map check failed open, contradicting the fail-closed claim in
   its own commit message. A missing map, an unrecognised map format, or a
   partial archive list each warned and passed; and it hardcoded firmware.map
   while the post-action target used ${PROGNAME}, so a renamed program could
   inspect a stale or absent file and still succeed. All four now fail the
   build, and it requires every one of the four archives to appear rather than
   at least one.

Rebuilt Heltec_v3_repeater_observer_mqtt, Heltec_v3_repeater and
heltec_v4_repeater_observer_mqtt; the opt-in path still reports all 4 archives
linked from .mbedtls-4k/.

(cherry picked from commit 5b5f076e5e165997e8050f2be061c7c67340fcf7)
2026-08-14 09:47:40 -07:00
agessaman 8275512964 build(mqtt): make the reduced-TLS mbedTLS archives shippable, opt-in and verified
The reduced-TLS work was validated on hardware but only reachable through
PLATFORMIO_BUILD_FLAGS pointing at an absolute path in a developer's home
directory, so nothing outside that machine could reproduce it.

Distribute the archives as a release asset instead of committing them: ~6 MB
per architecture, and they must be rebuilt for every espressif32 bump, so
committing would grow history permanently and go stale without any signal.

  scripts/mbedtls_4k_manifest.txt  per-arch sha256 of each archive
  scripts/fetch_mbedtls_4k.sh      fetch into .mbedtls-4k/<arch>/, verify
  scripts/mbedtls_4k.py            pre-build wiring and post-link proof

Off by default. The script is attached to esp32_base but returns immediately
unless MESHCORE_REDUCED_TLS=1, so ordinary builds need no artifact and are
byte-for-byte unaffected — confirmed by building with it absent.

Both ways this can fail silently produce a firmware that looks fine and lacks
the change, so the opt-in path refuses to guess:

  - a -L at a missing or partial directory: the linker ignores an unusable
    search path and resolves mbedTLS from the framework. Now a hard error.
  - archives left over from an earlier platform version: now a sha256
    mismatch against the manifest, naming both hashes.
  - a -L that is present but outranked, leaving the flag inert: after the
    link, firmware.map must resolve every libmbed*.a into .mbedtls-4k/, or
    the build fails and prints the offending paths.

That last check earned its place immediately — it caught its own first
implementation comparing a relative map path against an absolute one, and an
earlier build flag in this investigation was accepted by the compiler while
no source read it. A flag reaching the compiler proves nothing about the link.

Verified all four paths on Heltec_v3_repeater_observer_mqtt: default build
unaffected; opted in with archives present links all four from .mbedtls-4k/
and says so; archives absent fails with a fetch hint; a single appended byte
fails on sha256.

Also removes platformio.local.ini.hold, which held the superseded approach of
pointing platform_packages at a whole custom framework. That installs over the
shared framework package and changes mbedTLS for every other ESP32 project on
the machine; the -L path keeps the change scoped to one env.

Note the inbound record buffer stays at 16 KiB, so this lowers per-connection
footprint by ~12 KiB but does not move the contiguous allocation a handshake
needs. It buys headroom, not a lower floor.

(cherry picked from commit a87faff6ff170c328fdd0550f4b4dd9089aa2ea0)
2026-08-14 09:47:40 -07:00
mikecarper 7605b12cc7 Merge remote-tracking branch 'review/observer-firmware' into keymindCascade
# Conflicts:
#	.github/workflows/build-observer-firmwares.yml
#	.gitignore
#	MQTT_IMPLEMENTATION.md
#	MQTT_INTERNALS.md
#	README.md
#	STABILITY_TESTABILITY_HANDOFF.md
#	docs/cli_commands.md
#	examples/companion_radio/MyMesh.cpp
#	examples/simple_repeater/MyMesh.cpp
#	examples/simple_repeater/UITask.cpp
#	examples/simple_room_server/MyMesh.cpp
#	examples/simple_room_server/UITask.cpp
#	examples/simple_sensor/SensorMesh.cpp
#	platformio.ini
#	scripts/generate_webconfig_html.py
#	scripts/webconfig_mock_server.py
#	src/helpers/CommonCLI.cpp
#	src/helpers/CommonCLI.h
#	src/helpers/JWTHelper.cpp
#	src/helpers/MQTTDefaults.h
#	src/helpers/MQTTMessageBuilder.cpp
#	src/helpers/MQTTPayloadBuilder.h
#	src/helpers/MQTTPresets.h
#	src/helpers/bridges/MQTTBridge.h
#	src/helpers/esp32/WebConfigServer.cpp
#	src/helpers/esp32/WebConfigServer.h
#	src/helpers/ui/SH1106Display.cpp
#	variants/lilygo_tbeam_SX1262/platformio.ini
#	variants/lilygo_tbeam_SX1276/platformio.ini
#	variants/lilygo_tlora_v2_1/platformio.ini
#	variants/thinknode_m7/platformio.ini
#	webui/index.html
2026-08-14 08:53:02 -07:00
mikecarper e92794eabc Decode raw telemetry packets 2026-08-14 00:01:38 -07:00