Changes since v0.4.0
_ZLE-based EDF start alignment
- EDF start time now aligned to the rising edge of AS11's _ZLE (Zero Leak
Estimate) signal instead of MaskOn, better matching AS11's own export
behaviour. - Added find_zle_time() to scan events.snt for the first _ZLE event with
value=1 (rising edge only). Falls back to MaskOn when no _ZLE event found. - _ZLE subscription and ValueChange handling added with injected NTP
timestamp and diagnostic rising/falling-edge logging.
Missing-packet compensation via startTime gap detection
- StreamData notifications now parsed for startTime (ISO8601) in the
fast-path single-pass scanner — no cJSON overhead, one extra string
comparison per key. - Gap detection: compares consecutive startTime values; normal gap is
~200ms, threshold 280ms. Handles multi-notification loss (2, 3, 5+). - Compensation per signal type:
- BRP (25Hz waveform): inserts -1 sentinels (preserves waveform
integrity — fabricated data could mimic apnea). - SA2 (1Hz vitals): holds previous HR/SpO2 value (changes over
minutes; gap is clinically negligible). - PLD (0.5Hz metrics): holds previous 12-channel row (2-second
summaries change slowly).
- BRP (25Hz waveform): inserts -1 sentinels (preserves waveform
- Decimation counters advanced correctly during gap compensation to
maintain timeline sync. Midnight rollover handled. Gap capped at 50
notifications to prevent runaway on BLE reconnection.
Session data quality logging
- Per-gap warning at ESP_LOGW level:
StreamData gap: <gap>ms (<N> missing notifications), inserting compensation - Session-end summary at ESP_LOGI level:
stream quality: <N> notifications received, <N> gap events, <N> missing compensated, loss rate <X.XX>% - Loss rate shown as percentage with 2 decimal places. 0.00% = no drops;
0.13% is typical for problematic BLE links.