SomnoTrace v4.0.0-beta5
The SomnoBridge release. π SomnoTrace now pairs, provisions, time-syncs
and pulls therapy data through the Wi-FiβBLE bridge β the AirSense's SD
card never has to leave the machine.
beta5 fixes release-image builds: a clean build (which regenerates its
configuration from sdkconfig.defaults) had NimBLE security compiled
out entirely, so SomnoBridge pairing failed instantly on every attempt β
with the bridge never even contacted.
β¨ New since v4.0.0-beta4
π Clean-built release images could not pair at all
- The root cause of beta4's pairing failures β
build-dist.sh --clean
deletessdkconfigand regenerates it fromsdkconfig.defaults, which
had NimBLE SMP disabled (# CONFIG_BT_NIMBLE_SECURITY_ENABLE is not set). With SMP compiled out,ble_gap_security_initiate()is a stub
that returnsBLE_HS_ENOTSUP (8)unconditionally β before the bond
store is consulted and before any SMP packet is sent. Every clean-built
release image could therefore never pair a SomnoBridge; only developer
builds with a hand-tunedsdkconfigworked. - SMP enabled in the defaults β
CONFIG_BT_NIMBLE_SECURITY_ENABLE,
SM_LEGACY,SM_SC(LE Secure Connections) andNVS_PERSIST(bond
persistence across reboots) are now set insdkconfig.defaults, so a
clean release build pairs exactly like a developer build. - Diagnostics name both causes β an
ENOTSUP (8)from the SM layer
now logs "SMP disabled or bond store full; the bridge was never
contacted", so this class of failure is one line to diagnose instead of
a bridge-reset goose chase. - Verified on hardware β a build made from defaults only (the exact
--cleanpath, confirmed by the 21 KB smaller image and the SMP code
present insdkconfig.h) completes
link encrypted, authenticated and bondedβpairedβsubscribed.
β¨ New since v4.0.0-beta3
π SomnoBridge pairing β local bond-store failures fixed
- Pairing no longer fails before the bridge is contacted β NimBLE's
SM layer refuses to start pairing when its capacity check
(ble_sm_chk_store_overflow) trips, returningBLE_HS_ENOTSUP (8)
synchronously. That check counts stored bonds plus any active SMP
procedure againstCONFIG_BT_NIMBLE_MAX_BONDSβ which was 2 (and 1
in the shipped defaults). One stored bridge bond plus a single live
pairing procedure was enough to block every attempt. The failure was
then reported as "bridge refused pairing β FORGET_PEER is required",
which sent users to reset the bridge for no reason. - Bond store now self-heals β registered a store-status callback
that evicts the oldest peer bond (ble_store_util_delete_oldest_peer)
when the store reports FULL, instead of refusing to pair. - Capacity raised β
CONFIG_BT_NIMBLE_MAX_BONDS2 β 4, and
sdkconfig.defaults1 β 4 (a clean build from defaults could not
pair anything at all). - Honest diagnostics β rc=8 now says the refusal is local and the
bridge was never contacted, and the portal reports "pairing blocked
locally" instead of blaming the bridge. - No more spurious "Pair failed" β a connect still winding down
answersEBUSY (15); the pair op now retries once after 400 ms
instead of surfacing an error on a quick second press. - Verified on hardware β NVS bond-store dump (IDF
nvs_partition_tool) confirmed a single valid bridge bond (LTK
present, LESC, authenticated); live pairing completes
encrypted, authenticated and bondedβpairedβsubscribed.
β¨ New since v4.0.0-beta1
πΎ SomnoBridge "Configure" dialog β smarter Save & Test
- Join is now verified, not assumed β after saving a custom card
password, the dialog polls the bridge's real link state
(GET_STATUS.sta_connected, 1 s Γ 12) instead of running a redundant
probe-join. Success shows "Bridge joined the card"; a typo'd password
gets a clear red error instead of a false "good". - Security probe only when it matters β the factory-password check
now runs only when the saved password is88888888or the card is
open. Custom passwords skip it entirely. - Dialog closes itself on success β the button flips to OK and the
window auto-dismisses; nothing left to configure means nothing left
on screen. It stays open on any failure. GET_STATUSadded to the/api/sb/opproxy whitelist;
EZSHARE_CHECKtimeout raised 25 s β 32 s.
βοΈ Portal wording β data-source direction made explicit (#345)
- Pairing card renamed "ResMed Series 11 / SomnoBridge" β covers
AirSense 11 and AirCurve 11 plus the bridge path (was "ResMed
AirSense 11 CPAP" even though it pairs a SomnoBridge too). - Scan button renamed "Scan for ResMed / SomnoBridge".
- Upload Window now states the direction: "days recorded on this
device are uploaded from SomnoTrace to the destinations above" β
plus a note that SomnoTrace records live over Bluetooth and cannot
import history stored on the SD card inside your CPAP machine. - Reset Upload State description and confirm dialog say the same,
and now correctly state the upload-window cap instead of "all days". - Maintenance section says "the SomnoTrace SD card" β no more
ambiguity about which card an action touches.
π Fixes
- π Dashboard could shimmer forever β with no sessions recorded,
the "Connecting & loading sessionsβ¦" progress bar was never
dismissed; "No sessions recorded yet" appeared only as a small muted
line. This is what looked like an 18-hour hang in #345. The dashboard
now stops loading and explains the empty state in one line.
Everything in v4.0.0-beta1
β¨ Highlights
- π SomnoBridge integration β a complete BLE client (
sb_ble,
~1.5k LoC): discovery, passkey pairing, bonded GATT ops over the
framed protocol, streaming file pulls, and a/api/sb/opHTTP proxy
that drives every bridge op from the portal. - π Authoritative UTC & drift correction β SomnoTrace anchors its
NTP time on the bridge's monotonic clock with periodic exchanges,
reads back the fitted drift on every sync pass, and applies the
estimate when importing sessions β AS11 clock wander is corrected
instead of silently skewing therapy data. - βοΈ "Configure SomnoBridge" dialog β card network picker (scrollable
AP list, OPEN/SECURED badges, saved network), AS10/AS11 machine cards
with the AS11 GMT-offset picker, an X close button, and an
insecure-card flow: factory88888888and open cards are detected by
a real probe-join, flagged with a warning, and can be re-secured
in-place viaEZSHARE_ADMINβ the bridge changes the card's own Wi-Fi
password through its admin form and rejoins automatically. - π Bridge status in the portal β pairing state, card Wi-Fi,
therapy-active and transfer-allowed indicators, last sync, and sync
progress straight from the bridge. - π₯ Session augmentation β late-recovered stream files now merge
into already-committed sessions instead of being discarded as
duplicates; coverage is verified against the manifest and annotations
are regenerated byte-identically.
π Fixes
- ποΈ Duplicate recording folders β oximetry day labels are now a pure
function of the recording's civil digits (ESP-local noon rule) and an
existingrecording_idunder any day folder wins β DST/offset changes
can no longer file one recording under two days. - π Uploader fingerprint ping-pong β duplicate
recording_ids across
day folders are deduplicated in reconcile (newest day wins) so two
files can never take turns invalidating each other's uploads. - π Retry storms β any unit that fails 5 uploads is parked and
retried at most once a day, reviving automatically when its content
changes. A local anomaly can never again become hours of HTTP 429s. - π± Logs tab scroll β narrow screens no longer open the log view at
the oldest line of a page-long scrollback.
ποΈ Under the hood
sb_protorequest/response framing with reassembly; BLE ops run off
the NimBLE host task so provisioning never starves indications.- Transfer ledger coordination keeps already-downloaded card files from
re-pulling β zero redundant transfers across reconnects. edf_importevents rendering extracted behind a byte-identical
emit-to-file / emit-to-set abstraction for coverage checks.- AS11 BLE: connection handling improvements alongside the bridge path.
β Testing
- New
sb_ble_testhost suite: 153 checks covering pairing state
machine, framing, reassembly and op dispatch. somno_ml_workersurvivor tests: guards, deadlines, SST checks,
fragment grouping.- Full host suite: 31 targets, 0 failures, sanitizer-clean.
π Docs
- Windows 10/11 SMB share setup guide with screenshots (contributed).