SLOG is open source software for logging saunas. The reference logger is a power-loss-resilient Seeed Studio XIAO ESP32-C3 with eight powered DS18B20 temperature sensors. Radio stays off unless saved pairing enables the optional ESP-NOW display link; no Wi-Fi network is needed. Measurements are available over USB, while detected sauna sessions are stored in internal flash.
The 28 September field/readiness audit records a hardware-ready local setup and the remaining browser work. At that audit, the hosted flasher still offered older firmware, and browser recording health/standby messages did not yet reflect all current firmware states. Use the verified local recovery package for the accepted field setup.
Open the hosted portal at akkauppi.github.io/slog. For normal use, this is the SLOG application. Installing Python, PlatformIO, or the source repository is not required for firmware installation, probe setup, record download, charts, or CSV/Excel export.
| Task | Normal interface | Python required? |
|---|---|---|
| Install or update firmware | Portal · Prepare | No |
| Verify the logger and map eight probes | Portal · Prepare | No |
| Download, preserve, or remove records | Portal · Records | No |
| View charts and export CSV or Excel | Portal · Analyze | No |
| Optional receiver for live temperatures; pairing and power controls | Portal · Radio (optional) | No |
| Develop firmware, retrieve crash dumps, or make batch reports | Command-line tools | Yes |
Blank session storage is initialized automatically when it is provably erased. If a board carries factory-test data and its session partition cannot mount, the portal offers a guarded new or intentionally erased board recovery path. Existing loggers are never formatted automatically.
Radio is optional and is needed only for a separate receiver showing real-time temperatures. Recording, USB downloads and analysis work without pairing. The Radio (optional) tab shares the portal connection: disconnect before choosing the other board. Save one private recovery kit and use it for both.
- Wire the logger as shown below and connect it over USB.
- Open the portal in a current desktop Chrome or Edge.
- In Prepare, install SLOG firmware, verify the running logger, and map the eight probes. The portal downloads a backup of the completed probe map.
- In Records, confirm that storage is ready and the 12-hour reserve is available. If a genuinely new board needs recovery, use the explicitly guarded new-board storage action; do not use it for an existing logger.
- Disconnect USB and power the logger for the sauna run.
- Reconnect later and use Records to CRC-check and preserve the raw
.slogfiles. - Use Analyze to open those files locally, inspect charts and the selected probe's heating/cooling rate, and export CSV or Excel.
Firmware installation normally needs no button sequence, even on a new board: choose the normally connected logger and SLOG enters ROM download mode automatically. Manual BOOT access is retained only as a connection-recovery fallback.
Logger access requires Web Serial, so use a current desktop Chrome or Edge on
Windows, macOS, or Linux. File-only analysis works in other modern browsers.
All processing is local, nothing is uploaded, and the portal remains available
offline after its application files and firmware package have been cached.
GitHub Pages rebuilds the portal and its commit-identified firmware package
from main; local development must use tools/serve_portal.py as described in
docs/web-commissioning-portal.md.
The portal also includes a preheated electric-sauna example under Analyze → Try a real sauna recording. The sauna was already fully heated; useful observations start around 15 minutes. All raw readings and unknown-duration power gaps are preserved.
The repository contains the embedded logger, browser portal, optional USB and
analysis tools, CRC-safe log parser, and self-contained interactive analysis
reports. Development invariants and verification commands for coding agents
are summarized in AGENTS.md.
The agreed roadmap for turning this into a reproducible DIY build and curated
community dataset is documented in
docs/community-project-plan.md.
The first full sauna run is retained as a de-identified reproducible example.
Like every raw .slog, it still contains stable probe ROM identifiers. See
docs/runs/2026-08-16-session-1.md for the
observations and commands used to regenerate its CSV and interactive report.
The firmware uses XIAO pin D2 for the 1-Wire data line. Connect every sensor
in powered (three-wire) mode:
- sensor GND to XIAO GND
- sensor VDD to XIAO 3V3
- sensor DATA to XIAO D2
- 4.7 kOhm pull-up from DATA to 3V3 as an initial value
Prefer a linear trunk with short sensor branches. Do not use parasite power. The final pull-up value may need adjustment for the installed cable length and topology.
The firmware is generic: it contains no installation-specific probe addresses. On the first boot of this version, on a new device, or after NVS has been erased, probe discovery and fresh temperature scans remain available over USB but session logging is disabled until all eight probes have been mapped. Probe identity always comes from the DS18B20 ROM address, never from discovery order.
Use Prepare in the browser portal for the normal setup. It commissions a
fully assembled eight-probe column by asking you to warm one metal probe tip at
a time, verifies the committed map after restart, and downloads a
sensor-map.json backup. The secondary browser method supports connecting
probes individually.
The portal uses a fixed, SHA-256-checked firmware package and has no arbitrary
firmware picker or whole-flash erase option. See
docs/web-commissioning-portal.md for
browser requirements and recovery behavior.
The repository also includes a Python commissioning tool for development, bench work, and scripted recovery. Its default method connects probes one at a time, starting with probe 1 at the top/farthest end and finishing with probe 8 at the bottom/nearest end:
.venv/bin/python tools/identify_sensors.py --method connectFor an assembled harness, use its warm-one-at-a-time method:
.venv/bin/python tools/identify_sensors.py --method warmBoth the portal and tool validate every ROM's family and Maxim CRC, require
eight unique addresses, and confirm that the final discovered set exactly
matches the proposed map. The configuration is staged in RAM, written as a
CRC-protected record to the inactive NVS slot, read back, and then activated by
reboot.
After reconnecting, the workflow verifies that boot activated that exact
generation and that the same eight ROMs are still present. The previous valid
slot is never erased during a normal commit. Partial identification progress
is saved to sensor-map.pending.json, so an interrupted replacement cannot
overwrite the last verified sensor-map.json. The final map replaces sensor-map.json
atomically only after all post-reboot checks pass.
Commissioning does not format LittleFS or alter existing .slog files. The
challenged storage-format flow likewise leaves the probe mapping in NVS intact.
A full-chip erase does remove the mapping, so keep sensor-map.json as a backup. The
line-oriented protocol intended for both this tool and the browser portal is
documented in
docs/probe-commissioning.md.
- Active sampling runs every 10 seconds. Cold standby checks probes every 150 seconds and sends fresh temperatures every 15 minutes (5 minutes in the testing profile). See power management.
- No session can start without one complete, valid eight-probe configuration.
- Up to 10 minutes of active pretrigger samples are retained in RAM. Entering cold standby clears that ring; cold checks do not populate it. Recording after waking can therefore begin with a shorter pretrigger history.
- A session starts after any valid probe remains above 40 C for 30 seconds.
- The pre-trigger readings are committed immediately; later blocks are flushed every 10 minutes, limiting sudden-power-loss exposure to the current block.
- A normal session ends after the hottest probe remains below 45 C and at least 15 C below the session peak for 30 minutes. Probe 1 and at least six probes must be healthy for automatic ending.
- Logs use CRC-protected binary blocks. An absent footer marks a power-cut session; valid committed blocks remain downloadable.
- Every 10-minute block is opened, appended, flushed, and closed independently. An unexpected power cut can therefore lose or corrupt only the block being assembled or written; the offline parser stops at the first incomplete or invalid block and preserves all earlier blocks.
- New sessions are staged until their header and pretrigger block are durable, then published atomically. Appends check write, sync, and close errors before acknowledging committed records. Interrupted staging files are preserved outside the published-session catalog; see storage reliability for recovery boundaries.
- If power returns while the sauna is still hot, the new session records the interrupted session ID as a probable continuation. A cold reading from at least six probes cancels that link.
- Device flash is a bounded rolling store, not the permanent archive. Immediately before opening a new session, the logger requires enough free space for a full 12-hour recording. If necessary, it may retire the oldest eligible completed logical run to make that reserve. Segments linked by continuation metadata are treated as one run, and an interrupted session that may be continued is protected.
- Linked segments are retired newest first. If power fails between removals, the remaining files are still a valid prefix and the same run is completed immediately before the next session starts.
- Retention never runs during an active session. If the full-session reserve cannot be made from eligible completed runs, the new session is refused and every existing raw log is left in place.
- The firmware records boot/reset metadata, RTC source and fallback state, sensor-health flags, and the ESP32-C3's internal temperature alongside probe readings. Wi-Fi remains disabled.
At boot SLOG mounts the session partition without formatting it. If the entire partition is still erased, SLOG initializes it automatically before session logging can begin. A nonblank partition that cannot mount is left untouched; this protects records from vendor residue, interrupted writes, and hardware faults.
If a newly purchased board contains factory-test data that prevents mounting,
the portal can offer Initialize or erase session storage. This action is
only for a new or intentionally erased board: it displays the current storage
state, requires typing ERASE SLOG STORAGE, obtains a one-use device challenge,
and asks for a final confirmation. It permanently deletes .slog files but
does not erase the probe map in NVS or the core-dump partition.
The development helper uses the same challenge protocol and still requires an explicit flag:
.venv/bin/python tools/logs.py format --yesDownloading neither removes the device copy nor marks it as archived. Because
the logger cannot know whether a completed run has been copied elsewhere,
download and CRC-validate raw .slog files regularly, ideally after every
measurement. Automatic retention may eventually retire an old completed run.
Manual deletion remains available when you have already preserved every linked
segment of that logical run.
The portal's Records section shows the rolling-store reserve and logical chains, supports CRC-validated raw downloads, and prefers whole-run removal only after every segment has been saved and read back through the file-system picker. Browsers without that API can use an explicit, strongly warned override after Quick downloading every segment; the portal CRC-checks the transfer and compares fresh device bytes again immediately before deletion, but cannot prove the browser saved a copy.
Analyze opens one or more .slog files entirely offline and groups only
unambiguous continuations by default. The user can instead view each segment
alone without changing its raw linkage metadata. It shows an eight-probe SVG
timeline with explicit unknown-duration gaps and a selected-probe derivative
chart on the same time axis. The selected view can be exported as CSV or an
Excel .xlsx workbook; both keep segment-relative time and mark unknown power
gaps instead of inventing elapsed time. See
docs/web-data-workspace.md for the preservation
and deletion gates and the export schema.
Nothing in this section is required for the normal browser workflow. These commands are for firmware development, automation, deeper reports, and device diagnostics.
PlatformIO is installed in the repository-local Python virtual environment:
.venv/bin/pio run
.venv/bin/pio run --target upload
.venv/bin/pio device monitorExit the serial monitor with Ctrl-C. Install the optional offline-report
dependency once:
.venv/bin/pip install -r requirements-analysis.txtThe command-line record tools are:
.venv/bin/python tools/logs.py status
.venv/bin/python tools/logs.py list
.venv/bin/python tools/logs.py download 1 session-1.slog
.venv/bin/python tools/logs.py export session-1.slog session-1.csv
.venv/bin/python tools/logs.py plot session-1.slog session-1.html
.venv/bin/python tools/logs.py report session-1.slog
.venv/bin/python tools/logs.py delete 1The plot result is a self-contained interactive HTML report with raw and
optional 50-second-median traces, a time/height thermal map, linked vertical
profiles, stratification analysis, threshold timing, rapid-warming candidates,
and logger-health information. Related continuation segments retain explicit
unknown power-off gaps. Use --no-chain to inspect one physical file alone.
Compare complete runs, aligned at their 40 C triggers, with:
.venv/bin/python tools/logs.py compare session-1.slog session-8.slog \
--output comparison.htmlstatus provides additional firmware diagnostics, including RTC source,
reset cause, probe state, retention activity, and crash-dump presence. If a
watchdog crash occurred, preserve its raw dump before erasing it:
.venv/bin/python tools/logs.py crash-download crash.bin
.venv/bin/python tools/logs.py crash-eraseThe task watchdog, brownout detector, and flash core dumps are enabled in the build. ESP-IDF falls back if XTAL32K cannot start; the logger records the active RTC source and any fallback for later review.
Probe 1, at the end opposite the ESP32, is the highest probe near the ceiling. Probes increase in number downward toward the ESP32 at 20 cm intervals. Probe 8 is therefore 140 cm below probe 1. These are relative heights; an absolute ceiling or floor height can be added later without changing sensor identity.
- In the portal's Prepare section, install or verify the firmware and complete probe setup. Blank storage initializes automatically; use the guarded new-board action only when a genuinely new or intentionally erased board still cannot mount its session partition.
- In Records, confirm that the 12-hour storage reserve is ready and preserve any sessions not already backed up. Keep the XIAO and wiring in the coolest practical location; keep the USB power bank outside the sauna.
- Disconnect serial, power from the power bank, and let the firmware start the session automatically after a probe stays above 40 C for 30 seconds.
- Unannounced power removal is supported. On the next USB connection, use
Records to download every relevant
.slog. - Open the saved files in Analyze, review the charts, and export CSV or
Excel before deleting anything from the device. Retain the original
.slogfiles for later analysis.
Focused code, documentation, hardware-design, and test contributions are welcome. Read CONTRIBUTING.md before opening a pull request. Use the issue forms for bugs and proposals, and report vulnerabilities through the private process in SECURITY.md. Community measurement intake remains closed until its consent and privacy-review workflow is implemented; do not attach raw records to an issue.
Project decisions and maintainer review rules are documented in GOVERNANCE.md. Participation is governed by the Code of Conduct.
SLOG deliberately separates licenses by material:
- software is licensed under Apache-2.0;
- documentation is licensed under CC BY 4.0;
- hardware design files are licensed under CERN-OHL-P-2.0; and
- measurements and catalog metadata are dedicated under CC0 1.0.
The exact path rules and full license texts are in
LICENSES/README.md. Vendored dependencies retain their
upstream licenses.
New recordings preserve acquisition identity in SLOG V3; V1/V2 remain readable. Encrypted ESP-NOW is available through explicitly provisioned pairing, with radio off by default. See the identity and radio contract for offline pairing, compatibility, and hardware release gates. The logger owns the shared protocol packages; the private receiver consumes a pinned snapshot.
