Skip to content

v2.0.0

Latest

Choose a tag to compare

@ilyakruchinin ilyakruchinin released this 04 Sep 09:10

πŸš€ SomnoTrace v2.0.0 Release Notes

✨ Highlights & What's New Since v1.4.2

SomnoTrace v2.0.0 marks a major milestone for the firmware, transitioning the project into the v2.0 architecture. This release brings a completely modularized EDF export engine, bulletproof storage coordination between uploads and session recording, zero-leak BLE sync, full civil calendar/DST accuracy, verified transactional consistency on SD card exports, and an advanced physics-based battery monitoring subsystem with dynamic CC/CV fuel gauging and persistent RTC state.


1. 🧩 Modular EDF Subsystem (v2.0 Architectural Foundation)

  • Decoupled Engine: Decomposed the monolithic export generator into clean, single-responsibility modules:
    • edf_header: Fixed 256-byte EDF headers, patient/recording IDs, and metadata sidecars.
    • edf_waveform: High-rate breath waveforms (BRP.edf), per-breath stats (PLD.edf), and oximetry (SA2.edf).
    • edf_annotations: Event annotations (EVE.edf) and Cheyne-Stokes logging (CSL.edf).
    • edf_summary: Multi-record daily summary (STR.edf) from ResMed protobuf spools and settings snapshots.
    • edf_data_dict: Master signal dictionary defining physical and digital boundaries for 134 channels.
  • Native ResMed SD Parity: Generated exports match native AirSense 11 SD card layouts and binary formats 1:1, ensuring out-of-the-box compatibility with OSCAR, SleepHQ, and clinical analysis software.

2. πŸ›‘οΈ Resilient Storage & Export Coordination (No More Dropped Exports)

  • Deferred Export Recovery: When therapy stops while a background cloud or SMB upload holds the storage lock, SomnoTrace no longer drops the export. It queues a deferred export marker and automatically exports the day as soon as the storage lock becomes available.
  • Granular Storage Leases: The upload scheduler now acquires storage locks on a per-day basis rather than locking the SD card for the entire upload session, preventing export starvation during long cloud syncs or SleepHQ polling.
  • Smart Upload Reconciliation: Upload passes now reconcile newly added or rebuilt sessions instead of forgetting the whole day, eliminating duplicate session uploads to SleepHQ.

3. πŸ”’ BLE Protocol Hardening & Memory Leak Elimination

  • Spool Fragment Leak Fix: Fixed an issue where transient timeouts during BLE summary spool downloads over weak radio links leaked accumulated memory buffers (~90 KB per failed attempt).
  • Race-Free Teardown: The spool fragment collector is now detached before releasing memory, preventing late-arriving BLE notifications from corrupting freed state during disconnects.

4. ⏰ Full Daylight Saving (DST) & Calendar Accuracy

  • Civil Calendar Math Across DST Transitions: Replaced naive 24-hour UTC arithmetic with proper civil calendar transitions. Morning sessions during 23-hour spring-forward transitions now reliably map to the correct therapy day instead of landing in yesterday's folder.
  • Standardized Noon-Day Derivation: Unified noon-day cutoffs across session logging, oximetry correlation, upload indexing, and portal management via a centralized as11_time module.

5. 🫁 Cheyne-Stokes Respiration (CSR) Event Support

  • Dedicated CSL.edf Layer: Added full support for ResMed CSL.edf annotation exports. CsrStart and CsrEnd events are captured, timestamped with backdate offsets, and deduplicated, allowing OSCAR and SleepHQ to accurately display Cheyne-Stokes breathing episodes.

6. πŸ’Ύ SD Card Data Integrity & Checksum Reliability

  • Transactional Sidecar Checksums: Identification.crc and CurrentSettings.crc generation is now strictly gated on the successful write of their respective .json files. If a JSON write fails, any existing stale .crc is actively unlinked, guaranteeing that downstream tools never encounter corrupt or mismatched checksums.

7. πŸ§ͺ Automated Property-Based Test Suite

  • Host-Executable Test Harness: Added an automated property test suite with 37 property tests and 8 state-machine scenarios covering fixed-point scaling, rounding, clamping, sentinels, and boundary dates without requiring physical hardware.

8. πŸ”‹ Physics-Based Battery Monitoring & Dynamic CC/CV Fuel Gauge

  • ⚑ Dynamic CC/CV Slew Rate Limiting: Accurately models the physical charging curve of the ETA6098 switching charger. When plugged in, the gauge rate-limits percentage increases based on the active charge regime:
    • 0% – 69% (Constant Current Phase): 35 seconds per 1% step for rapid, linear accumulation under the full ~500 mA charge rate.
    • 70% – 84% (Early CV Transition): 60 seconds per 1% step as cell voltage reaches 4.15 V and current begins tapering.
    • 85% – 94% (Deep CV Absorption): 120 seconds (2 minutes) per 1% step as current decays to ~150–200 mA.
    • 95% – 99% (Trickle Saturation): 180 seconds (3 minutes) per 1% step during final saturation (<100 mA).
    • 100% (Charge Termination): Snaps instantly to 100% when the hardware charger IC turns off above 4140 mV.
    • Direction Lock: Prevents artificial percentage decreases while actively connected to a charger.
  • πŸ“‰ Two-Tier Discharge Guardrail:
    • 20% – 100%: Gated to at most 1% drop per 30 seconds, dampening transient voltage dips caused by Wi-Fi and BLE transmission bursts while tracking real drain (~120–180s per 1%).
    • 0% – 19%: Accelerates to 15 seconds per 1% step to reliably track the steep discharge knee before the PMU low-voltage cutoff (~3.3 V).
    • Direction Lock: Strictly non-increasing while discharging.
  • βš–οΈ Honest Uncalibrated State Machine (--%):
    • Eliminates misleading false-100% readings on boot: cold booting while plugged into USB in the constant-voltage float zone ($\ge 4100\text{ mV}$) displays --% ⚑ on the LCD and --% (X.XXV) ⚑ (Calibrating) in the Web Portal until the true state of charge is established.
    • Electrochemical Surface Relaxation: Unplugging from an uncalibrated state enters a 10-second relaxation window (BAT_UNPLUG_SETTLE_S = 10) to allow surface charge to dissipate, then snaps directly to the true relaxed Open Circuit Voltage (OCV) percentage and engages normal discharge guardrails.
    • Snaps directly to 100% if left plugged in until the hardware charger IC completes full saturation.
  • 🧠 Persistent State Across Warm Reboots & USB Flashing (RTC_NOINIT_ATTR):
    • Displayed percentage and filtered millivolts are preserved in ESP32-S3 RTC Fast SRAM across warm reboots, software restarts, watchdog triggers, and USB firmware flashing using the .rtc_noinit memory section, protected by a 32-bit magic header (0x534E5442) and CRC validation.
    • Cold power-ons (battery reconnection) naturally fail CRC due to uninitialized RAM, safely re-entering the calibration state machine.
  • ⏱️ Decoupled 10-Second Burst Sampling & Debouncing:
    • Unified 10-second sampling cycle using a 256-sample ADC burst over 1s, trimmed-mean averaging (discarding highest and lowest 1/8th to reject noise spikes), and an IIR low-pass filter.
    • Fast 2-second edge debounce (BAT_DEBOUNCE_SEC = 2) for rapid 2–3s detection of physical charger plug and unplug events.

9. 🎨 Top Bar UI Polish & Slender Bluetooth Indicator

  • α›’ Slender Pixel-Perfect Bluetooth Rune: Replaced the ambiguous CPAP mask graphic with a sleek, Nordic Bluetooth rune (α›’) rendered in light blue (#50B4FF) at x=199, y=11 with uniform 1-pixel stroke geometry, perfectly matching the adjacent Wi-Fi signal icon.
  • ⚑ Rescaled Battery Gauge & Bold Charging Bolt:
    • Rescaled the battery indicator frame to 22Γ—14px with a 3Γ—6px terminal nub and 20Γ—12px inner cavity, aligning flush with the 14px line height of digits and header icons.
    • Prominent 11Γ—8px bold lightning bolt in vivid yellow (#FFCC00) centered inside the cavity during active charging, and proportional multi-level fill when running on battery.
    • Color-coded percentage readout: Green (>30%), Orange (16–30%), Red (≀15%), and Muted Slate-Blue for --% calibrating state.
  • πŸ“ Header Alignment & Visual Breathing Room:
    • Repositioned the "CUR" label to the left margin (x=12) and "AVG" to the right margin (x=193), providing 22px of symmetrical breathing room around the central "Leak (L/min)" title and eliminating visual crowding.
  • ⚑ Low-Latency Status Bar Refresh:
    • Decoupled battery UI updates from the 3-second display loop to run every 1 second upon state changes, providing instant visual feedback on plug/unplug events without redrawing unchanged frames.

10. 🌐 Web Portal Telemetry & User Configuration

  • βš™οΈ Battery Indicator Toggle: Added a configurable battery_enabled toggle in the Web Portal under Display & Sound and via the REST API (POST /api/device/settings). Users operating solely on USB power without a Li-ion battery can cleanly hide the battery indicator from the LCD status screen.
  • πŸ“Š Live Battery Telemetry in Web Portal: The portal Status tab displays live battery percentage, cell voltage (X.XXV), charging bolt status, uncalibrated state (Calibrating), or USB Power (No battery) when disabled.

11. πŸ“œ Comprehensive Formal Specifications

  • Spec 0012 (Battery Monitoring & Power Management): Full technical specification documenting ADC burst sampling, OCV curves, electrochemical surface relaxation, dynamic CC/CV slew rate limiting, uncalibrated state machine, RTC Fast RAM persistence, and power latch pin controls.
  • Spec 0011 (Web API Endpoints): Updated REST and SSE API contracts for battery telemetry under GET /api/status and configuration schema in POST /api/device/settings.
  • Spec Documentation Index: Updated spec/README.md to catalog Specifications 0009 through 0012.

🀝 Credits & Acknowledgements

A huge thank you to everyone involved in making this milestone release possible through code contributions, rigorous protocol analysis, and real-world testing:

πŸ’» Code Contributions

  • @Plantucha:
    • Pull Request #187: Implemented the deferred export queue on storage lease contention (SD_LEASE_EXPORT), non-blocking lease probing, and smart day reconciliation to prevent duplicate uploads to SleepHQ.
    • Pull Request #196: Fixed the BLE spool fragment memory leak on collection timeouts (~90 KB accumulation under weak signal) and implemented race-free collector detachment during teardown.

πŸ” Technical Analysis, Bug Reports & Architectural Review

  • @Plantucha:
    • Issue #200: Discovered and proved the 23-hour spring-forward DST boundary defect in noon-day derivation across multiple timezones.
    • Issue #190: Identified Cheyne-Stokes Respiration (CSR) event labeling requirements in CSL.edf, driving the backdate timing and deduplication implementation.
    • Issue #198: Uncovered the sidecar .crc failure path where checksums could be written despite .json write failures.
    • Issue #199: Conducted comprehensive dimensional analysis on STR.edf summary metric scaling across all 53 signals.
    • Issue #186 & Discussion #191: Detailed review and verification of the EDF modularization and STR data dictionary parity.

🩺 Testing & Community Feedback