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. Wi-Fi is disabled. Measurements are available over USB, while detected sauna sessions are stored in internal flash.
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 |
| Initialize blank session storage once | Serial command or supplied Python helper | Only when using the helper |
| Develop firmware, retrieve crash dumps, or make batch reports | Command-line tools | Yes |
The one current exception is explicit storage initialization. The portal never
formats flash, so a factory-new or erased logger needs the one-time
LOG FORMAT YES serial command before it can record sessions. This is
explained under First-use storage initialization.
Python is one convenient way to send that command; it is not part of installing
firmware, mapping probes, or processing downloaded data.
- 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.
- If Records reports that storage is unavailable, perform the one-time storage initialization described below.
- 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 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.
LOG FORMAT YES 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.
- Samples are taken every 10 seconds.
- No session can start without one complete, valid eight-probe configuration.
- The latest 10 minutes are retained in RAM while idle.
- 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.
- 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.
SLOG never formats its flash filesystem automatically, and the portal does not offer a format button. A factory-new board—or a board whose session partition has been deliberately erased—must therefore be initialized once before it can record sessions.
This is the only normal setup operation that is not yet available in the portal. Python is not inherently required: with the running logger connected, any 115200-baud serial terminal can send this exact line:
LOG FORMAT YES
Wait for LOG_FORMAT ok=1. Formatting destroys any session records already in
that partition, so use it only for new or intentionally cleared storage. It
does not erase the probe map stored in NVS.
From a SLOG development checkout, the supplied Python helper sends the same command:
.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. Initialize blank storage once if Records reports that the filesystem is unavailable.
- 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.
