EnvOS — Custom Environmental Monitoring OS

EnvOS — Custom Environmental Monitoring OS

Production-grade IoT environmental monitor on a custom Raspberry Pi OS image

A production-grade IoT system built from bare metal up — a Go service, a custom-branded Raspberry Pi OS image, and a real-time web dashboard — running unattended on a Raspberry Pi Zero 2 W.

EnvOS is a fully self-hosted environmental monitoring system — live dashboard, historical trends, Home Assistant integration, MQTT alerts — running on hardware I fully controlled, from the OS image up.

The Problem

Off-the-shelf home sensor kits are either cloud-locked, closed-source, or too limited to extend. I wanted something I could own end-to-end instead.

What I Built

  • A Go service that reads 5 I2C sensors (temperature, humidity, pressure, VOC air quality, ambient light, UV index, 9-axis IMU) through a single contention-safe I2C goroutine, fanning out readings via an internal event bus to independent consumers: a REST/SSE API, an MQTT publisher, a CSV logger, and an e-paper display renderer.
  • A live web dashboard — server-sent events for real-time sensor cards, Chart.js historical graphs reading straight from rotating CSV logs, mobile-responsive layout.
  • A custom Raspberry Pi OS image — my own build pipeline (macOS-hosted, APFS copy-on-write base cloning, cross-compilation, boot partition config, rootfs verification, xz compression) that produces a branded, pre-configured image: boot splash, MOTD, systemd services, WiFi-from-SD-card provisioning, USB-OTG fallback networking, and auto-installing MQTT broker — all baked in, ready to flash and boot headless.
  • MQTT + Home Assistant integration — auto-discovery on startup, threshold-based alerting (VOC, over-temp).
  • A physical status display — an SSD1680 e-paper panel rendering a live summary, driven by a custom driver (partial-refresh, custom bitmap font, flicker-free redraws).

EnvOS live dashboard on mobile

Highlights / Engineering Decisions

  • Single I2C goroutine + event bus fan-out — avoids bus contention while keeping API, MQTT, logging, and display fully decoupled from the sensor read loop.
  • Dual network paths — WiFi (auto-reconnect + watchdog) with a USB-OTG gadget fallback, so the device is always reachable even with no WiFi configured, useful for a headless single-board computer.
  • Built and debugged the image pipeline myself — including chasing down a Bookworm/NetworkManager quirk that left the USB gadget interface “unmanaged” after boot, and a watchdog bug that was intermittently forcing the network into sleep state.
  • Design for reflash safety — sensor logs are backed up to the boot partition and restored automatically on first boot, so re-imaging the SD card doesn’t lose historical data.

Stack

Go · periph.io (I2C) · paho MQTT · Home Assistant · Chart.js · Server-Sent Events · systemd · NetworkManager · Raspberry Pi OS / Bookworm · e-paper (SSD1680) · bash (image build tooling)

Status

Running continuously in production on a Raspberry Pi Zero 2 W: live sensor readings, dashboard, MQTT/Home Assistant integration, CSV history, and e-paper display are all complete and stable. Next: OTA update delivery.