Record ESP-NOW diagnostic build and host validation

This commit is contained in:
mikecarper committed 2026-10-22 11:40:44 -07:00
1 parent 4008782078
commit e7b863494c
5 files changed
+175 -1

No files matched your search

+3 -1
View File
@@ -5612,13 +5612,15 @@ peer is reachable. The statistics pages use these keys:
| Default | `rx`: received callback frames; `mesh`: inbound MeshCore packets queued; `tx`: outbound MeshCore packets queued; `sent`: successful frame callbacks. |
| `rx` | `frames`: received callback frames; `decoded`: parsed MeshCore packets; `mesh`: queued for mesh processing; `crc`: checksum failures; `bad`: malformed frames; `parse`: packet parse failures. |
| `tx` | `req`: mesh TX requests; `queued`: mesh packets queued; `start`: SDK-accepted frames; `ok`: successful frame callbacks; `err`: SDK start failures; `cbfail`: failed frame callbacks; `timeout`: callback timeouts. |
| `drops` | `rxq`: RX queue drops; `foreign`: foreign-group packets; `filter`/`dupe`: inbound filter/duplicate drops; `txq`: total mesh TX drops; `txfilter`/`txdupe`: outbound filter/duplicate drops; `big`: oversize TX drops. |
| `drops` | `rxq`: RX queue drops; `foreign`: foreign-group packets; `filter`/`dupe`: inbound filter/duplicate drops; `txq`: recorded local mesh TX rejection/final-failure decisions; `txfilter`/`txdupe`: outbound filter/duplicate drops; `big`: oversize TX drops. |
| `test` | `queued`, `start`, `ok`, `fail`, `timeout`: probe TX stages; `rx`, `bad`: valid/invalid probes received; `txid`, `rxid`: last queued/received IDs in hexadecimal. |
Mesh admission means queued for normal processing, not confirmed LoRa
forwarding or end-to-end delivery. Packet and frame counters have different
units: fragmentation can produce several frames for one mesh packet. Counters
survive bridge stop/start; reboot or the explicit reset starts a new window.
Stopping or restarting the bridge clears pending queue work without classifying
its delivery. These counters are not a complete end-to-end delivery ledger.
**Local-only actions:**
+3
View File
@@ -198,6 +198,9 @@ Repeat in the opposite direction with a new message. Counters accumulate until
`espnow resetstats` or reboot and survive an ESP-NOW stop/start. Inspect changes
across the one message, rather than assuming old totals describe the current
attempt.
Stopping or restarting clears pending queue work without classifying delivery;
the TX drop counter records local rejection/final-failure decisions, not every
undelivered packet.
- **No source-side bridge TX request:** check the configured source.
`bridge.source rx` exports LoRa receptions; confirm the board heard the
@@ -0,0 +1,95 @@
<!-- meshcore-hosted-doc-link:start -->
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/test-results/espnow_bridge_diagnostics_2026-10-22/">View this page on MeshCore Docs</a>.</p>
<!-- meshcore-hosted-doc-link:end -->
# ESP-NOW bridge diagnostics, 22 October 2026
Status: **host tests and both Full repeater builds PASS**. No radio was
flashed or contacted in this work. The reported V4/V4 R8 TFT bridge delivery
failure remains physically unverified; matching saved settings and
`espnow.running on` do not establish peer receipt.
Clean firmware source
[`400878207`](https://github.com/mikecarper/MeshCore/commit/40087820781b189e0136b0ce73928a717752a5c8)
contains the diagnostics. Both canonical builds used the Full profile,
Cascade runtime defaults, USA Cascade radio preset and version
`v1.18.0.1-halo-keymind-cascade-dev-40087820`.
The [safe build receipt](espnow_bridge_diagnostics_2026-10-22.safe.json)
records source, artifact hashes and linked memory measurements. Later
documentation-only changes do not alter these firmware artifacts.
## Investigation and changes
Both V4 variants use the same ESP-NOW bridge implementation. No
display-specific forwarding difference was found. `bridge.source rx` is a
valid choice: it exports LoRa receptions. If both boards directly hear the
same LoRa message, normal mesh duplicate suppression can discard a later
bridged copy. This is a condition to measure, not an established cause of
the reported failure.
Normal builds previously compiled out the bridge's verbose debug path.
Runtime USB logging/debug can now produce bounded ESP-NOW summaries without
a special build flag. Status exposes the configured and actual 2.4 GHz
channel, SDK state, queue depths and historical error stage/code. Separate
counter pages locate RX decode/admission, TX queue/start/completion and
filter/duplicate decisions. No secret is printed.
The local-only `espnow test` command sends a single bounded diagnostic
probe. The peer consumes it before mesh allocation or LoRa forwarding. It
has no echo or retry and does not modify saved settings. The probe checks
2.4 GHz reachability only; it is unauthenticated and does not validate the
wrapped secret or normal packet format. Confirm receipt using the peer's
increased `rx` count and matching `rxid`, then test the other direction.
SDK send success alone is not application receipt; see the
[Espressif ESP-NOW documentation](https://docs.espressif.com/projects/esp-idf/en/v4.4.7/esp32s3/api-reference/network/esp_now.html).
Use [the diagnostic procedure](../espnow_bridge_setup.md#locate-a-mesh-forwarding-failure)
and [CLI reference](../cli_commands.md#bridge-when-bridge-support-is-compiled-in)
for the counters and exact command grammar. The USB summary requires both
`usb.logging on` and `usb.debug on`; record and restore both original values
after a short capture. Counter pages and probes need neither logging gate.
## Build results
| Canonical target | Selected Full environment | Available internal bytes | Required heap bytes | Result |
| --- | --- | ---: | ---: | --- |
| `heltec_v4_repeater` | `heltec_v4_repeater_observer_mqtt` | 202,576 | 192,656 | PASS |
| `heltec_v4_r8_tft_repeater` | `heltec_v4_r8_tft_repeater_observer_mqtt` | 200,344 | 190,608 | PASS |
The largest linked internal regions are 169,808 and 167,576 bytes respectively,
against a required contiguous allocation of 21,184 bytes. These are linked
capacity estimates, not runtime free-heap, fragmentation or maximum-load
measurements. Application and merged packages, memory gates, OTA packaging
and linked capability verification pass for both targets. Both capability
receipts report the Full profile with no feature reductions.
An initial attempt at source `14682de00` compiled but was rejected by the
immutable-input packaging guard because generation changed the embedded web
page header. That header was committed in `400878207`; both qualifying builds
then passed from clean source. The rejected attempt is retained privately and
is excluded from the safe receipt.
## Verification and limits
The host validation passed for:
- Diagnostic codec and actual bridge runtime: strict input/CRC handling,
legacy parser rejection, SDK callback variants, queue/pool pressure,
one-attempt probes, unchanged normal retries, status and bounded output.
- Diagnostic CLI: strict grammar, local-only actions, response bounds and
bridge selection across role combinations, including sanitizer builds.
- Existing bridge recovery, transport filter wiring, radio lifecycle,
ESP-NOW runtime and bridge ingress regressions.
- Cooperative ESP32 USB output, USB debug/prefs, hosted documentation links
and strict documentation rendering.
Callback work remains bounded and does not print or allocate. Counter
snapshots and resets use the existing RX/TX locks. Diagnostics are guarded
by ESP-NOW bridge support, including the CLI callbacks, so unrelated firmware
roles do not acquire the new callback interface.
No physical WiFi coexistence, MQTT coexistence, LoRa delivery, probe exchange
or USB debug capture was performed. Actual pair qualification still requires
the new readings and fresh LoRa traffic in both directions. Stop/restart can
discard pending queue work without classifying delivery; lifetime counters
are not a complete end-to-end delivery ledger.
@@ -0,0 +1,73 @@
{
"schema_version": 1,
"date": "2026-10-22",
"source_commit": "40087820781b189e0136b0ce73928a717752a5c8",
"source_clean_at_build": true,
"firmware_version": "v1.18.0.1-halo-keymind-cascade-dev-40087820",
"runtime_profile": "cascade",
"radio_preset": "usa-cascade-fixed",
"scope": "Host tests and clean canonical build/package checks only. No hardware flashed or contacted. Actual bridge pair failure remains unverified.",
"physical_validation_performed": false,
"builds": [
{
"requested_target": "heltec_v4_repeater",
"platformio_environment": "heltec_v4_repeater_observer_mqtt",
"build_profile": "full",
"capability_verification_passed": true,
"feature_reductions": [],
"build_recipe_sha256": "44e773e27532c5e1a3e846a86dd1646631a8f7d03a9cbe9119e6237c765ec516",
"capabilities_sha256": "dfb6df721a6051359ea69de83232930104a5e489cda9cc63c66a1f3e73fddcfe",
"memory": {
"passed": true,
"available_internal_bytes": 202576,
"largest_internal_region_bytes": 169808,
"required_heap_bytes": 192656,
"required_contiguous_bytes": 21184,
"scope": "Linked capacity before runtime allocation; physical boot/load/soak validation remains required."
},
"memory_receipt_sha256": "8ba0fbad37ce56c7b3922dcdc8c76ee6742415bae0b8e7ed540f79224a3b93bf",
"artifacts": [
{
"file": "heltec_v4_repeater_observer_mqtt-full-usb-wifi-ota-v1.18.0.1-halo-keymind-cascade-dev-40087820-merged.bin",
"bytes": 2378472,
"sha256": "2c3b15b2845cd30d796f42138d6ac0a24dbea4cb3d51f9e67c7e35aef51511f5"
},
{
"file": "heltec_v4_repeater_observer_mqtt-full-usb-wifi-ota-v1.18.0.1-halo-keymind-cascade-dev-40087820.bin",
"bytes": 2312936,
"sha256": "31cd7feff5ee4db6c9df6a1ef2c73055cbe42e29739d7dbd9f76d4ad036ea8b5"
}
]
},
{
"requested_target": "heltec_v4_r8_tft_repeater",
"platformio_environment": "heltec_v4_r8_tft_repeater_observer_mqtt",
"build_profile": "full",
"capability_verification_passed": true,
"feature_reductions": [],
"build_recipe_sha256": "aee9d9999eeed7cecb1d76c6914b80a6ff24ddae7c6a4895ceef50185a193780",
"capabilities_sha256": "258f78349f727a9436ae902b99ce4abf5b666ebdd520622e9d6d017a8928c024",
"memory": {
"passed": true,
"available_internal_bytes": 200344,
"largest_internal_region_bytes": 167576,
"required_heap_bytes": 190608,
"required_contiguous_bytes": 21184,
"scope": "Linked capacity before runtime allocation; physical boot/load/soak validation remains required."
},
"memory_receipt_sha256": "820bde1809e719cfbd636373f681368b98fd92f592866bbd88a81f236bc889cd",
"artifacts": [
{
"file": "heltec_v4_r8_tft_repeater_observer_mqtt-full-usb-wifi-ota-v1.18.0.1-halo-keymind-cascade-dev-40087820-merged.bin",
"bytes": 2392424,
"sha256": "dca1c74564b9830e73859d20332a59de3ca0b17456544d4c3102201665577f9c"
},
{
"file": "heltec_v4_r8_tft_repeater_observer_mqtt-full-usb-wifi-ota-v1.18.0.1-halo-keymind-cascade-dev-40087820.bin",
"bytes": 2326888,
"sha256": "23b827c27b46f5a3c6cae5257ca9940f2eb9bc7ccb0bc815c2d123ff18521e43"
}
]
}
]
}
+1
View File
@@ -11,6 +11,7 @@ Completed validation reports, experiments, and test guides are collected here. O
## Radio and RF
- [ESP-NOW bridge diagnostics: V4 and V4 R8 TFT Full build/host validation, 2026-10-22](espnow_bridge_diagnostics_2026-10-22.md)
- [V3/V4/T096 radio2 with two fixed witnesses, matched SF7/BW62.5 at preamble 32, 2026-10-22](radio2_simultaneous_receivers_2026-10-22.md)
- [SolarXiao Room Server power profiles and history build/host validation, 2026-10-21](solarxiao_room_2026-10-21.md)
- [SolarXiao three power profiles build/host validation, 2026-10-21](solarxiao_basic_2026-10-21.md)