Skip to content
Projects

airmon 2026

An end-to-end air quality monitor for my apartment, running 24/7 on a Raspberry Pi 4. It samples particulate matter, CO2, temperature, and humidity every 5 seconds, stores the readings in SQLite behind a FastAPI service, and serves a live React dashboard. The same data drives the fans of a DIY air purifier.

I built it to know what I'm breathing, and to practice building a system that keeps working when nobody is watching it: unattended for months, tolerant of network and power outages, and close to free to run.

airmon dashboard showing live PM2.5, CO2, temperature, and humidity readings

Engineering highlights

  • Hand-rolled Python drivers for all three sensors over UART and I2C, including the SPS30's byte-stuffed, checksummed SHDLC protocol, so OS upgrades can't break a dependency tree.
  • Outage-proof ingestion: every reading lands in a local SQLite queue first and replays with a UUID idempotency key when the network returns, so nothing is lost and nothing is inserted twice.
  • Tiered downsampling (5-second, per-minute, per-hour) keeps full resolution for recent data while the database settles near 100 MB for good. Before pruning, a daily job recomputes sampled aggregates from raw rows and refuses to delete anything if they disagree.
  • Closed-loop purifier control: an ESP32 polls the API for a fan duty computed from the last 5 minutes of PM2.5. The curve lives on the server, so the policy changes without a firmware update, and Home Assistant boosts the fans when the cats use the litter box.
  • Self-hosted on the Pi behind Cloudflare and Caddy, with DDNS, nightly backups to Cloudflare R2, a UPS, and a dead-man's-switch health check.
© 2026 Umut Toker.