BusyBoard: Edge IoT System
A physical control panel becomes the starting point for a full hardware-to-software system. Switch interactions are captured, recorded, grouped into sessions, and surfaced through connected components like a dashboard and buzzer. The result is a local-first system that makes physical activity visible, traceable, and useful.
Overview
The system is built around an ESP32 control panel with 11 toggle switches and motion-based session detection. Switch activity is published over MQTT to a local Python ingestion service, which validates each payload, applies session lifecycle logic, and writes the data to SQLite as the primary record. From there, events are replicated asynchronously to Supabase for cloud-backed visibility. A Next.js dashboard reads from Supabase Realtime to show live switch states, session history, event timing, and activity gaps. Core functionality runs entirely on the local network, so the board, broker, ingestion service, and local database continue working without internet access. Cloud sync supports remote visibility, but it is not required for the system to capture or store events.
View ProjectTHE INTERFACE
Physical Input at the Edge
The interface is a custom-wired electronic busyboard built around an ESP32. It combines 11 physical toggle switches, motion detection, and a connectivity status LED into a single input panel that turns physical interactions into structured MQTT events.
A MPU6050 accelerometer detects motion and automatically starts a session. From there, all activity is grouped until the session ends, either through a clean signal or a short period of inactivity.
- 11 toggle switches on dedicated GPIO pins
- Active-HIGH with pull-down resistors
- State-change publishing only
- Motion detection used to trigger sessions
- MPU6050 over I2C (SDA=GPIO21, SCL=GPIO22)
- Online connectivity indicator LED on GPIO5

ARCHITECTURE
Event-Driven Communication
The ESP32 publishes to a local Mosquitto broker with no knowledge of consumers. The ingestion service subscribes to all topics, persists events to a local database, and replicates them to Supabase. The buzzer subscribes independently and reacts to session activity. New consumers can be added without firmware changes.
Topics are scoped by device ID so the broker can serve multiple boards cleanly. Authentication is enforced while anonymous connections are rejected.
- Pub/sub decoupling between producers and consumers
- Device-scoped topic structure (`busyboard/{deviceId}/x`)
- Multiple active participants: control panel and buzzer (alarm)
- MQTT authentication enabled (no anonymous access)

SYSTEM DESIGN
Sessions and Event Modeling
Interactions are grouped into sessions to give structure to the data. Each session represents a period of activity, making it easier to understand behavior beyond individual events.
Sessions have clear start and end states. A session ends either through a clean signal or a timeout, ensuring every session has a defined and queryable outcome.
Each session includes relative timing and gaps between events, making it easier to follow sequence, pacing, and interaction patterns.
- Sessions track start, end, duration, and interaction count
- Events are linked to sessions for context
- Relative timing (+REL) and gap tracking between events
- Watchdog closes inactive sessions after a period of silence
- Disconnects handled through MQTT LWT and timeout logic
- End reason stored and surfaced in the UI

DASHBOARD
Real-Time Visibility
A Next.js dashboard provides a live view of device activity alongside session history. It combines real-time updates with structured logs, making system behavior easy to observe and review.
Live data flows into the interface as events are processed, while historical sessions remain available for inspection.
- Live switch states for all inputs
- Session list with duration and activity summary
- Event log with timestamps and relative timing
- Gap and sequence tracking between events
- Backed by Supabase (Postgres) with real-time updates
