Changes since v1.3.1
Calendar SpO₂ Indicator (PR #172 by @moldbuster)
- Added an orange SpO₂ dot to the calendar. Days with oximetry
data now show an orange dot alongside the existing blue CPAP dot.
Days with both data types show two dots side-by-side. Hovering
shows "CPAP data" or "SpO₂ data" tooltips. Selected-day contrast
was adjusted (theme-aware) so the dots remain visible.
SD Card Formatting (PR #173 by @cwm12345)
- Fixed "Format SD" on 32–64 GB cards. The formatter was using a 0
allocation-unit-size, causing FAT32 cluster counts too large for the
work buffer — f_mkfs would silently abort or trip the watchdog. Now
uses an explicit 32 KB allocation unit. - Fixed false success reporting. The web UI showed "formatted,
rebooting" the moment the task was spawned, regardless of the actual
result. Added a/api/format-progressendpoint that the UI polls for
real-time status (active/done/ok/error). - Fixed a crash when formatting during an upload scan. The upload
scan was walking the SD card directory tree at the same moment the
formatter was unmounting and reformatting it, corrupting the SDMMC
driver. The format task now holds an exclusive SD lease for the
entire operation, and the upload scan takes the lease around every
card walk. - Fixed post-format data loss. The hard
esp_restart()could beat
the card's internal flush. Addedsd_storage_deinit()(proper
f_unmount+ CTRL_SYNC) before the reboot. - Follow-up fix: restored the
s_mountedflag if the card is still
accessible after a format failure, and added a mutex around the
format-progress state to prevent races between the format task and
the progress HTTP handler.
Oximeter Auto-Detection Pairing
- Added automatic ring generation detection. When pairing, the
firmware now tries the OxyII (Gen2) protocol first. If the ring
responds with MTU=23 or "service not found" (indicating it's a Gen1
ring that doesn't speak OxyII), it automatically retries with the
Legacy (Gen1) protocol. The detected protocol is persisted to NVS,
so subsequent boots use the correct driver without re-detection. - Simplified the pairing UI. The scan dropdown now shows each ring
once (by name and signal strength) — no more Gen1/Gen2 protocol
selection. The user picks a ring, not a driver. - Fixed the root cause of the v1.3.1 "MTU=23" pairing failure.
Both Gen1 and Gen2 rings advertise the same BLE manufacturer ID and
service UUID, so both drivers matched both generations. The old scan
dedup kept only the OxyII entry, forcing Gen1 rings into the wrong
protocol. The dedup now keeps the first entry per address (legacy
driver wins, which has the device name). - Improved the MTU=23 error message to mention Gen1 as a possible
cause (for users who explicitly select a protocol via the API). - Race-condition hardening: the auto-pair task distinguishes
pair-task success from pull-task state changes by checking
is_paired()(only set by the pair task, never by the background
pull task). Concurrent pair attempts are rejected. Stale error
strings are ignored unless the driver state is actually ERROR.