diff --git a/docs/test-results/companion_ble_refresh_2026-10-19.md b/docs/test-results/companion_ble_refresh_2026-10-19.md new file mode 100644 index 000000000..303832ff6 --- /dev/null +++ b/docs/test-results/companion_ble_refresh_2026-10-19.md @@ -0,0 +1,146 @@ + + + + +# Companion Bluetooth contact refresh, 2026-10-19 + +The production Heltec V3 Full Companion refreshed 92 contacts in a median +**3.347882 seconds at 32.560 kbit/s**, compared with **6.191396 seconds at +17.606 kbit/s** for the earlier 60 ms firmware. All five complete refreshes and +the 46-contact incremental refresh passed exact-record validation in each run. +The new firmware reduced median complete-refresh time by **45.9%** on this +Mercerwood Pi connection. + +Measured production source: +[`4e4f27a25a720c52ca0f5381b5e5834d75532cc6`](https://github.com/mikecarper/MeshCore/commit/4e4f27a25a720c52ca0f5381b5e5834d75532cc6), +version `v1.18.0.1-halo-keymind-cascade-dev-4e4f27a2`, target +`Heltec_v3_companion_radio_full`. This was the normal Full build, with no BLE +benchmark override. These results measure contact synchronization on one V3 +and one Linux central; phone performance and complete application refreshes +remain untested. + +## Production behavior + +The modern NimBLE-Arduino adapter now spaces notification attempts by at least +7 ms. Legacy NimBLE and Bluedroid retain their 60 ms setting. After the first +successful encrypted, authenticated and bonded connection callback for a link, +the modern adapter requests a 15-30 ms connection interval, zero peripheral +latency and a four-second supervision timeout. It makes this request once per +authenticated link. The central chooses the accepted connection parameters. + +Required replies retain the existing bounded queues, notification-subscription +and negotiated-MTU gates, retry behavior and stalled-link recovery. Each +notification carries one complete protocol frame. Failed notification attempts +retain the frame; successful queue acceptance removes it without waiting for a +later callback. Contact-stream production retains its existing 5 ms pacing. +The change preserves the Full feature configuration and contact capacities. + +## Hardware method and results + +The same physical V3, Pi controller and 92 owned synthetic contacts were used +for both firmware revisions. V3 Full has capacity for 100 contacts; eight slots +were reserved. The fixture used zero path bytes and two modification timestamps +so the incremental filter selected exactly 46 records. The complete fixture +record-set hashes agree across both runs. Application-only upgrades preserved +the contact fixture and node identity. + +After the comparison, all 92 owned test contacts were removed. A fresh USB +session verified their absence and that the other contact records were unchanged. + +The earlier firmware was +[`fcc4714e2b1294a0d76c0aab4fa3b95b1609b3d0`](https://github.com/mikecarper/MeshCore/commit/fcc4714e2b1294a0d76c0aab4fa3b95b1609b3d0). +Its comparison run followed a controlled warm boot, recorded separately from +the BLE measurement. That preparatory check verified the same node, all 92 +persisted contacts and a reset uptime without core errors. The result measures the +combined firmware revisions, including the intervening contact-storage fixes; +it does not isolate the contribution of each individual change. + +| Measurement | Earlier 60 ms firmware | Production `4e4f27a2` | +| --- | ---: | ---: | +| Complete refreshes passed | 5/5 | 5/5 | +| Exact contacts per complete refresh | 92 | 92 | +| Median request-to-END time | 6.191396 s | 3.347882 s | +| Complete-refresh time range | 6.137166-6.331489 s | 3.342054-3.435741 s | +| Median protocol throughput | 17.606 kbit/s | 32.560 kbit/s | +| Incremental contacts verified | 46 | 46 | +| Incremental request-to-END time | 3.259745 s | 1.696429 s | +| Incremental protocol throughput | 16.733 kbit/s | 32.152 kbit/s | + +Each stream had to return a valid start header, the declared complete count, +unique complete records, every expected owned record byte-for-byte, and a valid +END watermark. Incremental results had to equal the timestamp-filtered complete +inventory. All streams had zero duplicate contacts or unexpected restarts. +The qualifier also checked the complete firmware version and public identity +against USB, authenticated NUS access, and monotonic device uptime. + +Throughput is application-protocol bytes divided by host-observed time from +the GET_CONTACTS write through the validated END notification. One complete +refresh contains 92 records of 148 bytes plus ten header/END bytes: 13,626 bytes. +The figures include request latency and protocol framing. Unsolicited pushes +are excluded from the byte total. These values are not BLE PHY bit rates. + +## Observed connection and controller limits + +Metadata collected during the normal production run showed the connection +start at 48.75 ms, latency zero and a 420 ms supervision timeout, then accept +**30 ms, latency zero and a 4,000 ms supervision timeout**. The complete-refresh +contact callback gap medians were 30.79-30.87 ms; per-run p95 gaps were +56.97-58.40 ms. Callback gaps include host/controller scheduling and are not +direct radio airtime measurements. + +The Pi controller returned LE feature bytes `[31, 0, 0, 0, 0, 0, 0, 0]` from +HCI opcode `0x2003`: its Data Length Extension and LE 2M PHY feature bits were +both zero. HCI LE Read Maximum Data Length (`0x202f`) returned status `0x01`, +unsupported command. This hardware result establishes the controller's reported +capabilities; no DLE support was inferred from its Bluetooth version. A newer +controller or phone may behave differently and requires separate measurement. + +The monitor collector emitted only numeric connection/update, data-length and +PHY fields. Raw monitor captures, addresses, keys, passkeys and contact records +were not saved in the shareable evidence. + +## Native and build evidence + +All six cases in +[`test_nimble_companion.py`](https://github.com/mikecarper/MeshCore/blob/4e4f27a25a720c52ca0f5381b5e5834d75532cc6/test/test_nimble_companion.py) +passed. Four real-adapter configurations, including the production default and +explicit 7/15/60 ms lab settings, execute a 128-record stream under controller +rejection, queue pressure, notification-subscription changes and small-MTU +pauses. They verify exact ordered delivery, retry retention, bounded queues, +interval boundaries, timer wrap and connection-parameter request gating. The +other two cases verify modern/legacy pacing policy and reject unauthorized or +out-of-range benchmark overrides. These are native tests, separate from the +92-contact hardware measurements. + +All 13 campaign targets compiled and passed their memory admission checks at +the measured production source. The 11 Full Companions were V3, T1000-E, +RAK4631, T096 FEM on, Mesh Pocket, XIAO nRF52, WisMesh Tag, V4.3 FEM off, +T-Deck, XIAO S3 WIO and SenseCAP Indicator. RAK3401 and MeshTower SD repeater +targets also passed, with full/reduced OTA packages. All 15 resulting capability +manifests were verified. Compilation covers this build set; it does not qualify +every board or every Full feature on hardware. + +The retained V3 ELF SHA-256 is +`a05c0cd6d70a8146296d9b6c3edbe3e8602fe05901b4d05759454cf61ba7e902`. +It matches the passed Full memory manifest, whose application, merged image, +capability manifest and license hashes also matched. Disassembly confirms the +7 ms comparisons in `isWriteBusy()` and `checkRecvFrame()`, and the authenticated +`updateConnParams` call with interval units `12/24`, latency `0`, timeout `400` +and connection-event length hints `0/0`. This establishes the linked code; +the monitor evidence above establishes the parameters accepted in this run. + +## Retained safe evidence + +These artifact names and SHA-256 hashes identify the evidence used for this +page. The page contains no private device identifiers or raw contact records. + +| Artifact | SHA-256 | +| --- | --- | +| `v3-equivalent-warmboot.safe.json` | `6d816656a4ff5d2dc22f2175026078bb6b487445acbcc51a70fb3cd51cf87838` | +| `v3-60ms-92-after-warmboot-retry.safe.json` | `41a06fdb63cb63c08d63ca09be78c12e5997bec7fccc2a4a164acda56fd0fabf` | +| `v3-production-fast-92.safe.json` | `d0633f82862322d48194ccdb99a030a600365f1ecd3da729f32614aa80beb510` | +| `v3-production-fast-link.safe.jsonl` | `fdac4c5d0ed73d2c1e3d1e37c2ef02ecc5831d7cb791099da1e3c97493825e64` | +| `pi-hci-capabilities.safe.json` | `7c103253e305b2345dfcbb9170faad4b67c91df5a475536798e1bf48d60b7980` | +| `v3-linked-ble-proof.safe.json` | `cc04c5b0547a9911b9fb3a41fa33140c4647565b27d32c4b51c3d266c6ef7fbb` | +| `v3-owned-cleanup.safe.json` | `c1c7e59c30bf0c2e8bd3097007a2ddb457b5272d6c4b598564d8ac65059ef2c4` | +| `BUILD-RESULTS.json` | `03eb95513c6111804b59e6175892929bd4346be92c9b8942bed925442114cb7f` | diff --git a/docs/test-results/hardware_validation_mercerwood_1_18_0_1_2026-10-19.md b/docs/test-results/hardware_validation_mercerwood_1_18_0_1_2026-10-19.md new file mode 100644 index 000000000..cf2a66dcc --- /dev/null +++ b/docs/test-results/hardware_validation_mercerwood_1_18_0_1_2026-10-19.md @@ -0,0 +1,69 @@ + + + + +# Mercerwood Full firmware testing, 2026-10-19 + +Source: `4e4f27a25a720c52ca0f5381b5e5834d75532cc6` +Version: `v1.18.0.1-halo-keymind-cascade-dev-4e4f27a2` + +Builds: 13/13 targets, 15/15 profiles PASS. The two Reduced OTA profiles are compile-only; repeater hardware status uses Full OTA installation proof. +Expected radios: 13; USB radios observed: 12. USB enumeration does not establish physical presence or absence. Build success does not mean all 13 radios passed hardware testing. + +| Board | Build | Flash | USB | BLE | RF | Bootloader | +| --- | --- | --- | --- | --- | --- | --- | +| Heltec V4.3 | PASS | PASS | PASS | PASS | unknown | n/a | +| RAK 3401 | PASS | PASS | runtime only PASS | n/a | n/a | C2 baseline PASS | +| LilyGo T-Deck | PASS | PASS | PASS | PASS | PASS | n/a | +| RAK WisMesh Tag | PASS | not enumerated | not enumerated | not enumerated | not enumerated | not enumerated | +| Heltec MeshPocket | PASS | PASS | PASS | PASS | PASS | C2 baseline PASS | +| SenseCAP Indicator | PASS | PASS | PASS | PASS | PASS | n/a | +| RAK 4631 | PASS | PASS | PASS | PASS | PASS | C2 baseline PASS | +| Heltec V3 | PASS | HEAD runtime PASS | PASS | PASS | PASS | n/a | +| Seeed XIAO ESP32-S3 | PASS | PASS | PASS | PASS | unknown | n/a | +| Seeed XIAO nRF52 | PASS | transfer PASS; runtime unqualified | unknown | unknown | unknown | C2 baseline PASS | +| Heltec T096 | PASS | PASS | PASS | PASS | PASS | C2 baseline PASS | +| Seeed T1000-E | PASS | PASS | PASS | FAIL | PASS | C2 baseline PASS | +| Heltec MeshTower SD | PASS | PASS | runtime only PASS | n/a | n/a | C2 baseline PASS | + +Repeater rows cover Full OTA application/runtime verification only. Their runtime-only USB entries do not claim Companion 100/10, BLE or RF qualification. +C2 bootloader entries describe earlier source-qualified installation evidence, separately from current application results. + +- Some expected radios were not enumerated in the selected USB inventory; this does not establish physical absence. +- T1000-E BLE remains unresolved until a completed current-source test passes. +- Heltec V4.3 had earlier USB/BLE passes, but later RF setup repeatedly rejected non-ASCII data before channels, leases or datagrams. Current transport behavior remains unresolved; RF qualification is pending. +- Seeed XIAO ESP32-S3 had earlier USB/BLE passes, but later RF setup repeatedly rejected non-ASCII data before channels, leases or datagrams. Current transport behavior remains unresolved; RF qualification is pending. +- XIAO nRF52 application transfer succeeded, but stable normal runtime and its USB/BLE/RF qualification remain unresolved. +- RAK WisMesh Tag is not USB-enumerated; its normal application and C2 bootloader campaign remain pending. + +The V3's first 15-second discovery trial failed. Its separate 25-second scan trial is PASS; the earlier failure remains part of the record. + +T1000-E's initial batch BLE trial failed. The explicit later retry is FAIL. The initial failure remains part of the record. + +Seeed XIAO nRF52 completed the application transfer; recovery failed normal runtime verification. The failed recovery phase and original batch outcomes remain in the JSON trial history. + +Seeed XIAO nRF52: The normal HEAD application transfer succeeded, but normal HEAD runtime was not verified within the required 75-second window. Runtime qualification remains incomplete. Bootloader baseline evidence is reported separately. + +The measured V3 92-contact refresh median was 3.347882 s at 32.560 kbit/s, versus 6.191396 s at 17.606 kbit/s for the earlier firmware. These are protocol throughput measurements on one V3/Linux connection, not BLE PHY rates or phone/full-app refresh claims. [Measured results](https://mikecarper.github.io/MeshCore/test-results/companion_ble_refresh_2026-10-19/). + +The inventory observed 12 distinct USB identities during a 10-second read-only window, including the cycling XIAO nRF52. This does not mean 12 stable ports. + +This is a partial campaign report: 9/11 Companion USB qualifications, 8/11 BLE qualifications and 6 two-way RF links (7 boards including the RAK hub) passed. The full campaign is incomplete. + +USB qualification used 100 persistent query cycles and 10 reopen checks, owned-contact CRUD and warm reboot, plus RX-only radio2 overlap-warning and three-decimal frequency-suggestion trials. BLE passes required three 30-second sessions. RF passes required exact two-way zero-hop DEV datagrams and owned-channel/radio-lease cleanup; they do not qualify text delivery, range, cold boot, phone interoperability or every firmware feature. + +RF setup attempts with no completed delivery are retained separately; they do not count as failed deliveries. + +MeshPocket previously reported error flag 8. Receive silence is a hypothesis, not a confirmed radio fault. A controlled warm reboot with flushed command delivery returned clean core flags, and its later two-way RAK RF test passed. The earlier unconfirmed reboot attempt and incomplete RF setup remain part of the history. + +The T1000-E retry discovered the USB-bound advertisement, but pairing failed with a D-Bus error before any completed sessions. The NUS public key was not verified. Its initial batch discovery failure remains retained; BLE qualification is unresolved. + +The retained pairing reason was Page Timeout. + +V4.3 history retains 4 non-ASCII RF setup aborts and one separate failed USB setup diagnosis. An intervening guarded classification completed a clean normal HEAD handshake and closed its port; it did not qualify RF or run a transition drain. + +The final read-only gateway check verified the active service held the RAK 3401 primary CDC0 interface. + +The unit-test workflow passed for the measured firmware source `4e4f27a2`: [GitHub run](https://github.com/mikecarper/MeshCore/actions/runs/39328768327). + +[Machine-readable results](hardware_validation_mercerwood_1_18_0_1_2026-10-19.safe.json). diff --git a/docs/test-results/hardware_validation_mercerwood_1_18_0_1_2026-10-19.safe.json b/docs/test-results/hardware_validation_mercerwood_1_18_0_1_2026-10-19.safe.json new file mode 100644 index 000000000..10981f81d --- /dev/null +++ b/docs/test-results/hardware_validation_mercerwood_1_18_0_1_2026-10-19.safe.json @@ -0,0 +1,573 @@ +{ + "schema": 1, + "generated_at": "2026-10-19T23:10:06.433624+00:00", + "source_commit": "4e4f27a25a720c52ca0f5381b5e5834d75532cc6", + "expected_version": "v1.18.0.1-halo-keymind-cascade-dev-4e4f27a2", + "campaign_complete": false, + "scope": "Normal Full application installation/runtime plus observed Companion USB/BLE/RF checks; compile results do not imply hardware passes.", + "inventory": { + "expected_radios": 13, + "usb_radios_observed": 12, + "scope": "Distinct USB identities seen during the selected 10-second read-only window; not a stable-port count.", + "counts_consistent": true, + "missing_keys": [ + "tag" + ], + "observation_seconds": 10 + }, + "compile": { + "passed_targets": 13, + "expected_targets": 13, + "passed_profiles": 15, + "expected_profiles": 15, + "reduced_ota_profiles_compile_only": 2 + }, + "companion_checks": { + "expected_boards": 11, + "usb_passed": 9, + "ble_passed": 8 + }, + "batch_state": "failed", + "v3_ble_trials": { + "first_scan_seconds": 15, + "later_scan_seconds": 25, + "first_trial": "failed", + "later_trial": "passed" + }, + "t1000_ble_trials": { + "batch_trial": "failed", + "later_retry": "failed" + }, + "supplemental_state": "failed", + "supplemental_trials": { + "tag": { + "flash": { + "batch_trial": "unknown", + "standalone_trial": "unknown" + }, + "usb": { + "batch_trial": "unknown", + "standalone_trial": "unknown" + }, + "ble": { + "batch_trial": "unknown", + "standalone_trial": "unknown" + } + }, + "xiao_nrf": { + "flash": { + "batch_trial": "unknown", + "standalone_trial": "failed" + }, + "usb": { + "batch_trial": "unknown", + "standalone_trial": "unknown" + }, + "ble": { + "batch_trial": "unknown", + "standalone_trial": "unknown" + } + } + }, + "boards": [ + { + "key": "v43", + "board": "Heltec V4.3", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "passed", + "rf": "unknown", + "runtime": "unknown", + "bootloader": "not_applicable", + "notes": [] + }, + { + "key": "rak3401", + "board": "RAK 3401", + "role": "repeater", + "compile": { + "status": "passed", + "profiles_passed": 2 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "runtime_only_passed", + "ble": "not_applicable", + "rf": "not_applicable", + "runtime": "passed", + "bootloader": "baseline_verified", + "notes": [ + "Full OTA application/runtime scope only; Reduced OTA is compile-only. Companion USB/BLE/RF campaign does not apply." + ], + "gateway_service_bound": true + }, + { + "key": "tdeck", + "board": "LilyGo T-Deck", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "passed", + "rf": "passed", + "runtime": "unknown", + "bootloader": "not_applicable", + "notes": [], + "rf_links_tested": 1 + }, + { + "key": "tag", + "board": "RAK WisMesh Tag", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "not_enumerated", + "flash": "not_enumerated", + "usb": "not_enumerated", + "ble": "not_enumerated", + "rf": "not_enumerated", + "runtime": "unknown", + "bootloader": "not_enumerated", + "notes": [] + }, + { + "key": "pocket", + "board": "Heltec MeshPocket", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "passed", + "rf": "passed", + "runtime": "unknown", + "bootloader": "baseline_verified", + "notes": [ + "MeshPocket previously reported error flag 8. Receive silence is a hypothesis, not a confirmed radio fault. A controlled warm reboot with flushed command delivery returned clean core flags, and its later two-way RAK RF test passed. The earlier unconfirmed reboot attempt and incomplete RF setup remain part of the history." + ], + "rf_links_tested": 1 + }, + { + "key": "indicator", + "board": "SenseCAP Indicator", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "passed", + "rf": "passed", + "runtime": "unknown", + "bootloader": "not_applicable", + "notes": [], + "rf_links_tested": 1 + }, + { + "key": "rak", + "board": "RAK 4631", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "passed", + "rf": "passed", + "runtime": "unknown", + "bootloader": "baseline_verified", + "notes": [], + "rf_links_tested": 6 + }, + { + "key": "v3", + "board": "Heltec V3", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "runtime_verified", + "usb": "passed", + "ble": "passed", + "rf": "passed", + "runtime": "unknown", + "bootloader": "not_applicable", + "notes": [ + "The fresh USB campaign proves normal HEAD runtime; a separate flash-operation report is not an input here.", + "Earlier 15-second BLE discovery trial failed; retained separately from the later 25-second scan trial." + ], + "rf_links_tested": 1 + }, + { + "key": "xiao", + "board": "Seeed XIAO ESP32-S3", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "passed", + "rf": "unknown", + "runtime": "unknown", + "bootloader": "not_applicable", + "notes": [] + }, + { + "key": "xiao_nrf", + "board": "Seeed XIAO nRF52", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "failed", + "usb": "unknown", + "ble": "unknown", + "rf": "unknown", + "runtime": "unqualified", + "bootloader": "baseline_verified", + "notes": [ + "The normal HEAD application transfer succeeded, but normal HEAD runtime was not verified within the required 75-second window. Runtime qualification remains incomplete. Bootloader baseline evidence is reported separately.", + "Explicit later standalone trials are separate from the retained original batch outcomes." + ], + "application_transfer": "passed", + "recovery_note_code": "application_transfer_succeeded_runtime_unqualified" + }, + { + "key": "t096", + "board": "Heltec T096", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "passed", + "rf": "passed", + "runtime": "unknown", + "bootloader": "baseline_verified", + "notes": [], + "rf_links_tested": 1 + }, + { + "key": "t1000", + "board": "Seeed T1000-E", + "role": "companion", + "compile": { + "status": "passed", + "profiles_passed": 1 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "passed", + "ble": "failed", + "rf": "passed", + "runtime": "unknown", + "bootloader": "baseline_verified", + "notes": [ + "Initial batch BLE failure retained separately from any explicit later retry.", + "The T1000-E retry discovered the USB-bound advertisement, but pairing failed with a D-Bus error before any completed sessions. The NUS public key was not verified. Its initial batch discovery failure remains retained; BLE qualification is unresolved." + ], + "rf_links_tested": 1 + }, + { + "key": "tower", + "board": "Heltec MeshTower SD", + "role": "repeater", + "compile": { + "status": "passed", + "profiles_passed": 2 + }, + "presence": "usb_enumerated", + "flash": "passed", + "usb": "runtime_only_passed", + "ble": "not_applicable", + "rf": "not_applicable", + "runtime": "passed", + "bootloader": "baseline_verified", + "notes": [ + "Full OTA application/runtime scope only; Reduced OTA is compile-only. Companion USB/BLE/RF campaign does not apply." + ] + } + ], + "bootloader": { + "baseline_source_commit": "c2f6fa455302167ea547ffe1e065a037762512d5", + "required_profiles": 8, + "baseline_profiles_verified": 7, + "scope": "Earlier source-qualified C2 install proof only; not a fresh bootloader revalidation by this application campaign." + }, + "measured_ble_refresh": { + "contacts": 92, + "candidate_median_seconds": 3.347882, + "candidate_protocol_kbit_s": 32.56, + "baseline_median_seconds": 6.191396, + "baseline_protocol_kbit_s": 17.606, + "measurement_scope": "One V3 and Linux central; five exact complete streams plus 46-contact incremental stream.", + "documentation": "https://mikecarper.github.io/MeshCore/test-results/companion_ble_refresh_2026-10-19/" + }, + "unresolved": [ + "Some expected radios were not enumerated in the selected USB inventory; this does not establish physical absence.", + "T1000-E BLE remains unresolved until a completed current-source test passes.", + "Heltec V4.3 had earlier USB/BLE passes, but later RF setup repeatedly rejected non-ASCII data before channels, leases or datagrams. Current transport behavior remains unresolved; RF qualification is pending.", + "Seeed XIAO ESP32-S3 had earlier USB/BLE passes, but later RF setup repeatedly rejected non-ASCII data before channels, leases or datagrams. Current transport behavior remains unresolved; RF qualification is pending.", + "XIAO nRF52 application transfer succeeded, but stable normal runtime and its USB/BLE/RF qualification remain unresolved.", + "RAK WisMesh Tag is not USB-enumerated; its normal application and C2 bootloader campaign remain pending." + ], + "input_evidence": { + "batch": { + "read_state": "available", + "current_source_version": true + }, + "bootloader": { + "read_state": "available", + "current_source_version": false + }, + "build": { + "read_state": "available", + "current_source_version": true + }, + "inventory": { + "read_state": "available", + "current_source_version": true + }, + "repeaters": { + "read_state": "available", + "current_source_version": true + }, + "rf_batch": { + "read_state": "available", + "current_source_version": true + }, + "rf_v3": { + "read_state": "missing", + "current_source_version": false + }, + "supplemental": { + "read_state": "available", + "current_source_version": true + }, + "t1000_ble_retry": { + "read_state": "available", + "current_source_version": true + }, + "v3_ble_discovery_miss": { + "read_state": "available", + "current_source_version": true + }, + "v3_ble_pass": { + "read_state": "available", + "current_source_version": true + }, + "v3_usb": { + "read_state": "available", + "current_source_version": true + } + }, + "partial": true, + "rf_campaign_trials": { + "pairs": [ + { + "hub": "rak", + "spoke": "indicator", + "status": "passed" + }, + { + "hub": "rak", + "spoke": "pocket", + "status": "passed" + }, + { + "hub": "rak", + "spoke": "t096", + "status": "passed" + }, + { + "hub": "rak", + "spoke": "t1000", + "status": "passed" + }, + { + "hub": "rak", + "spoke": "tdeck", + "status": "passed" + }, + { + "hub": "rak", + "spoke": "v3", + "status": "passed" + } + ], + "attempts": [ + { + "input": "initial", + "hub": "rak", + "spoke": "t1000", + "outcome": "passed", + "two_way_delivery_and_cleanup_verified": true, + "non_ascii_setup_abort": false, + "cleanup_review_required": false + }, + { + "input": "initial", + "hub": "rak", + "spoke": "t096", + "outcome": "passed", + "two_way_delivery_and_cleanup_verified": true, + "non_ascii_setup_abort": false, + "cleanup_review_required": false + }, + { + "input": "initial", + "hub": "rak", + "spoke": "pocket", + "outcome": "setup_incomplete", + "two_way_delivery_and_cleanup_verified": false, + "non_ascii_setup_abort": false, + "cleanup_review_required": false + }, + { + "input": "remaining", + "hub": "rak", + "spoke": "pocket", + "outcome": "passed", + "two_way_delivery_and_cleanup_verified": true, + "non_ascii_setup_abort": false, + "cleanup_review_required": false + }, + { + "input": "remaining", + "hub": "rak", + "spoke": "v3", + "outcome": "passed", + "two_way_delivery_and_cleanup_verified": true, + "non_ascii_setup_abort": false, + "cleanup_review_required": false + }, + { + "input": "remaining", + "hub": "rak", + "spoke": "v43", + "outcome": "setup_incomplete", + "two_way_delivery_and_cleanup_verified": false, + "non_ascii_setup_abort": true, + "cleanup_review_required": false + }, + { + "input": "v43_reopen", + "hub": "rak", + "spoke": "v43", + "outcome": "setup_incomplete", + "two_way_delivery_and_cleanup_verified": false, + "non_ascii_setup_abort": true, + "cleanup_review_required": false + }, + { + "input": "independent", + "hub": "rak", + "spoke": "tdeck", + "outcome": "passed", + "two_way_delivery_and_cleanup_verified": true, + "non_ascii_setup_abort": false, + "cleanup_review_required": false + }, + { + "input": "independent", + "hub": "rak", + "spoke": "xiao", + "outcome": "setup_incomplete", + "two_way_delivery_and_cleanup_verified": false, + "non_ascii_setup_abort": true, + "cleanup_review_required": false + }, + { + "input": "indicator", + "hub": "rak", + "spoke": "indicator", + "outcome": "passed", + "two_way_delivery_and_cleanup_verified": true, + "non_ascii_setup_abort": false, + "cleanup_review_required": false + }, + { + "input": "v43_recheck", + "hub": "rak", + "spoke": "v43", + "outcome": "setup_incomplete", + "two_way_delivery_and_cleanup_verified": false, + "non_ascii_setup_abort": true, + "cleanup_review_required": false + }, + { + "input": "v43_final", + "hub": "v43", + "spoke": "rak", + "outcome": "setup_incomplete", + "two_way_delivery_and_cleanup_verified": false, + "non_ascii_setup_abort": true, + "cleanup_review_required": false + }, + { + "input": "xiao_esp_final", + "hub": "xiao", + "spoke": "rak", + "outcome": "setup_incomplete", + "two_way_delivery_and_cleanup_verified": false, + "non_ascii_setup_abort": true, + "cleanup_review_required": false + } + ], + "passed_links": 6, + "boards_with_rf_pass": 7, + "hardware_cleanup_review_required": false + }, + "method_scope": "USB qualification used 100 persistent query cycles and 10 reopen checks, owned-contact CRUD and warm reboot, plus RX-only radio2 overlap-warning and three-decimal frequency-suggestion trials. BLE passes required three 30-second sessions. RF passes required exact two-way zero-hop DEV datagrams and owned-channel/radio-lease cleanup; they do not qualify text delivery, range, cold boot, phone interoperability or every firmware feature.", + "final_gateway_service_bound_verified": true, + "pocket_observation": { + "controlled_warm_reboot_and_clean_core_verified": true, + "prior_error_flags": 8, + "receive_silence_explanation_is_hypothesis": true, + "prior_unconfirmed_attempt_retained": true + }, + "t1000_retry_observation": { + "usb_bound_discovery_then_pair_dbus_error_before_sessions": true, + "pairing_phase_supported_by_selected_trace_detail": true, + "recognized_pairing_reason": "page_timeout", + "nus_public_key_verified": false, + "original_retry_report_sha256": "622ad084fc5b5f7edb03e02b2db3a86daddee33a082c854e9b20ab2a8997eaa3", + "selected_pairing_detail_sha256": "f4f9b85507145dbe4d6410f4dd455b113866e32f94e3ab45f7ef67e1eb0121b3" + }, + "v43_diagnostic_history": { + "standalone_usb_setup_diagnosis_failed": true, + "diagnosis_has_source_only_not_version_qualification": true, + "guarded_classification_handshake_completed_cleanly": true, + "classification_counts_as_rf_qualification": false, + "rf_non_ascii_setup_aborts": 4 + } +} diff --git a/test/fixtures/nimble_companion/test_nimble_companion.cpp b/test/fixtures/nimble_companion/test_nimble_companion.cpp index a7474a1f8..7a975486f 100644 --- a/test/fixtures/nimble_companion/test_nimble_companion.cpp +++ b/test/fixtures/nimble_companion/test_nimble_companion.cpp @@ -266,7 +266,7 @@ static void test_required_reply_backpressure_services_tx_before_rx() { assert(interface.checkRecvFrame(received) == 0); assert(interface.isReadBusy() && transmitted.empty()); test_millis += 61; - assert(interface.isWriteBusy()); // Capacity, not just the 60 ms TX throttle. + assert(interface.isWriteBusy()); // Capacity also blocks while TX is ready. assert(interface.checkRecvFrame(received) == 0); assert(interface.isReadBusy() && transmitted.empty());