SomnoTrace v3.0.1
SomnoTrace v3.0.1 is a follow-up stability and refinement release bringing a major visual overhaul to the SomnoStage hypnogram, robust handling of split-night uploads, critical fixes for legacy oximeter ring synchronization, automatic mDNS recovery after network link flaps, and improved cross-core IPC headroom.
📈 Hypnogram & Dashboard Refinements
- Connected Sleep Stage Ribbons: Adjacent sleep stages on the dashboard hypnogram are now joined by crisp 1.5px vertical transition hairlines featuring 2-point color gradients. Stage bars occupy 80% of their lane height, creating clean breathing room between rows while forming an unbroken, readable hypnogram across the night.
- Robust Thin-Block Geometry: Transient 30-second sleep stage dips (e.g. brief awakenings or single-epoch deep sleep dips) render cleanly as anchored vertical notches without geometry clipping or subpixel distortion.
- Moiré Pattern Elimination: Merged contiguous same-stage epochs into solid, continuous blocks, eliminating visual striping and subpixel aliasing across browser zoom levels.
- Stage & Confidence Tooltips: Hovering or tapping anywhere on the hypnogram displays a rich tooltip showing the sleep stage name and SomnoStage confidence percentage.
- Y-Axis Label Margin Fix: Adjusted tick dimensions and text gap on the hypnogram Y-axis, completely eliminating the first-letter clipping on "Wake", "REM", "Light", and "Deep" without shifting the horizontal alignment of stacked charts.
☁️ Uploader & Session Management
- Universal Incremental Uploads: Removed the backend
atomic_dayrestriction in favor of consistent incremental session uploads across both SleepHQ and SMB backends. - Capture-Hold Grace Window: Added a 1-hour post-therapy grace window (
UPLOAD_THERAPY_GRACE_MS) tracking session end timestamps insd_storageto ensure split-session fragments and STR summaries upload cleanly without premature dispatch. - Daily Group Revival: Added
UPLOAD_PARK_REVIVE_S(24h) to re-evaluate and revive parked upload groups daily, ensuring no capture group remains permanently stranded.
💍 Oximetry & Legacy Ring Sync
- Gen1 Ring FileList Truncation Safety: Resolved an issue where older Gen1 oximeter rings holding more than 34 files would silently truncate the 512-byte
FileListbuffer mid-filename, causing failed pulls and sync timeouts. The parser now safely drops truncated trailing fragments and reports incomplete lists. (PR #292 by @Plantucha) - Unified Session Gap Policy: Extracted the StreamData gap decision into a single pure function (
sw_gap_actioninmain/session_gap.h), strictly separating the padding ceiling from the session split threshold so radio dropouts (>10s) are never padded as continuous breathing waveforms. (PR #293 by @Plantucha)
🛡️ Network & System Stability
- mDNS Link-Flap Watchdog: Added a periodic health checker (every 60s) verifying UDP port 5353 binding and IGMP multicast membership (
224.0.0.251) inside the lwIP TCPIP thread. Automatically restarts dead responders after two consecutive failures with a 10-minute cooldown. - Updated mDNS Component: Upgraded
espressif/mdnsto1.11.3and exported mDNS restart counters and health status to Home Assistant MQTT attributes and/api/status. - IPC Task Stack Headroom: Increased
CONFIG_ESP_IPC_TASK_STACK_SIZEfrom 1280 to 1536 bytes insdkconfig.defaults, ensuring safe stack margin during cross-core flash and PHY operations.
👥 Contributors & Acknowledgements
A heartfelt thank you to everyone who contributed to this release:
- Michal Planicka (@Plantucha) for tracking down and fixing the Gen1 ring file list truncation bug (#292) and unifying the session gap policy and mutation tests (#293).
- Ilya Kruchinin (@ilyakruchinin) for the upload scheduler overhaul, hypnogram UI enhancements, mDNS link watchdog, and FreeRTOS stack tuning.