Convert SleepON / Go2Sleep ring data into a Wellue/Viatom O2 Ring CSV that SleepHQ accepts — with one click, fully offline, and now with built-in sleep analysis and charts.
📖 Read the detailed data-format & conversion write-up → — the exact SleepON export layout, the UTC/timezone gotcha, the SleepHQ output spec, the conversion pipeline, and the insights/visualizations, all verified against a real export.
SleepON/Go2Sleep rings record excellent overnight SpO₂ and pulse data, but the export doesn't drop straight into SleepHQ. This is a single, self-contained HTML file that reformats it correctly — no account, no upload, no backend. Your sleep data never leaves your device.
-
Reads real SleepON exports — the cloud
RawDataSecond_….xlsxexport, ViHealth-style flat CSVs, and the "packed"spo2Raw/heartRawarray layout..csv,.xlsx,.xls, comma/semicolon/tab-delimited. Fuzzy column matching; metadata rows above the header are skipped. -
Converts correctly — the parts the old version got wrong:
- Localises time. SleepON stores
Timein UTC with a separateTime_Zonecolumn (e.g.-05:00). The converter applies the offset so timestamps are the real local time SleepHQ aligns against — deterministically, regardless of your computer's own timezone. - Keeps the whole night, across midnight (the old version silently dropped everything after 00:00).
- Robust dates (ISO/
DD-MM/MM-DD/AM-PM/Excel-serial/epoch, auto day-vs-month), range validation,Validityfiltering, de-duplication to one reading per second. - Emits the exact Wellue/Viatom columns SleepHQ expects, named
YYYYMMDDHHMMSS.csv.
- Localises time. SleepON stores
-
Analyses your night — computed and charted locally (inline SVG, no dependencies):
- Avg / lowest SpO₂, % of night below 90% / 88%, desaturation events and approximate ODI
- Pulse average and range
- Hypnogram and sleep-stage breakdown (from the
Stagecolumn) - SpO₂-over-night (with 90% threshold + shaded dips), pulse trend, and time-in-band charts
-
Mobile-first UX
- Large, non-overlapping tap targets that stack cleanly on phones
- Native picker via a real
<label>+<input type="file">so uploads work reliably on iOS and Android (Files, iCloud Drive, Google Drive, Photos); drag-and-drop on desktop - Microinteractions and animations throughout, with full
prefers-reduced-motionsupport - Try it with sample data button, and a Conversion details log for troubleshooting
- Open
SleepConverter.htmlin any modern browser (or host it anywhere static). - Add your file — choose it, drag it in, or tap Try it with sample data.
- Convert — cleaned and reformatted client-side; review the stats and charts.
- Download the
YYYYMMDDHHMMSS.csvand import it into SleepHQ's O2 Ring uploader.
Input — SleepON cloud RawDataSecond export (.xlsx):
| Time (UTC) | Time_Zone | Heart_Rate(BPM) | Oxygen(%) | Active | Stage | Validity |
|---|---|---|---|---|---|---|
2025-10-04T00:59:04.000Z |
-05:00 |
64 |
96 |
0 |
Wake |
1 |
Output — SleepHQ / Wellue O2 Ring CSV:
Time,Oxygen Level,Pulse Rate,Motion,O2 Reminder,PR Reminder
03/10/2025 19:59:04,96,64,0,0,0
04/10/2025 03:39:59,95,66,0,0,0Full details, the timezone worked-example, supported variants, and the pipeline diagram are in docs/DATA_FORMAT.md.
- Vanilla HTML / CSS / JavaScript — no build step, no framework
- SheetJS (xlsx) for Excel parsing (the only external dependency, via CDN)
- Charts are hand-rendered inline SVG — runs 100% client-side and offline
If you track sleep because you have to rather than out of curiosity, WakeState is the other half of this: a local, narcolepsy-first tracker for wake state, events, medications, and last night's sleep.
I'm Taylor O'Neal. I work in product and analytics, teach at Miami University, and put the tools I actually use into the open.
- tayloroneal.com for what I'm working on and how to reach me
- @businesstaylor on X, where I post build notes
- @grizzpm on YouTube
If this saved you time, a star helps other people find it. Issues and PRs are welcome.
MIT, see LICENSE.