From 5b1ec1445044c8a21300fa4cbdc03fccba43e9f1 Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Mon, 23 Mar 2026 12:14:17 +0100 Subject: [PATCH] init project with README and PLAN --- PLAN.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 10 ++++++++ 2 files changed, 78 insertions(+) create mode 100644 PLAN.md create mode 100644 README.md diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..fed5964 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,68 @@ +# Plan: Balcony Weather Station Dashboard + +## 1. Project Overview +A real-time, neighborhood-facing weather dashboard that streams sensory data from an MQTT broker (Home Assistant) to a web interface. + +### Tech Stack +- **Backend:** Gleam (Target: Erlang/OTP) +- **Web Server:** Mist (HTTP & WebSockets) +- **Database:** SQLite (via `sqlight`) for persistent uptime tracking +- **Frontend:** SolidJS (Signals-based reactivity) + Tailwind CSS +- **Infrastructure:** Nomad (Docker-based deployment) + +--- + +## 2. Core Architecture & Actors +- **MQTT Actor:** Subscribes to weather topics (e.g., `tele/sensor/SENSOR`), parses JSON, and broadcasts updates. +- **Monitor Actor:** Tracks sensor "heartbeats." Maintains a state of "Last Seen." +- **WebSocket Manager:** Handles browser connections; pushes HTML-ready JSON to SolidJS. +- **Storage:** Single `weather.db` file using "Schema-on-Boot" (no manual migrations). + +--- + +## 3. Implementation Phases + +### Phase 1: Backend Infrastructure (Gleam) +- [ ] Initialize Gleam project with `gleam_otp`, `mist`, `wisp`, and `sqlight`. +- [ ] Implement `database.gleam`: + - Function `init_db` to run `CREATE TABLE IF NOT EXISTS sensor_stats`. + - Schema: `sensor_id (PK)`, `last_seen (DATETIME)`, `uptime_start (DATETIME)`. +- [ ] Implement `mqtt_handler.gleam`: + - Use `gemqtt` (wrapper for `emqtt`) to connect to the broker. + - Map incoming payloads to a `WeatherUpdate` custom type. + +### Phase 2: Uptime Logic +- [ ] Implement the `Monitor` Actor logic: + - On MQTT message: Update `last_seen` in SQLite. + - If `(CurrentTime - last_seen) > 10 minutes`, consider the sensor "disrupted." + - On recovery: Reset `uptime_start` to `now`. +- [ ] Calculate "Days since disruption" using: $$(CurrentTime - UptimeStart) / 86400$$ + +### Phase 3: Real-time Streaming +- [ ] Set up a Mist WebSocket handler. +- [ ] Use a simple process registry (or `gleam_otp` subject) to broadcast JSON to all connected clients. +- [ ] Ensure the JSON payload includes: `temp`, `humidity`, `wind`, and `uptime_days`. + +### Phase 4: Frontend (SolidJS) +- [ ] Scaffold SolidJS via Vite. +- [ ] Create a `WeatherCard` component. +- [ ] Implement `createEffect` for WebSocket management: + - On `ws.onmessage`: Update Solid signals. + - On `ws.onclose`: Implement simple exponential backoff for reconnection. +- [ ] Style with Tailwind CSS (Card-based layout, dark mode). + +### Phase 5: Deployment (Nomad) +- [ ] Create a multi-stage `Dockerfile`: + - Build SolidJS assets. + - Compile Gleam to a production Erlang release. +- [ ] Create `weather.nomad` job file: + - Mount `host_volume` for the `.db` file. + - Configure networking for the WebSocket port (default 8080). + +--- + +## 4. Claude Code Implementation Instructions +1. **Start with the Backend:** Focus on the `WeatherUpdate` type and the MQTT subscriber first. +2. **Database:** Use `sqlight.exec` to ensure the table exists on every app start. +3. **Frontend:** Keep the SolidJS app in a `./frontend` subdirectory. +4. **Mocking:** If the MQTT broker isn't reachable during coding, create a "Simulator" actor that sends random weather data every 5 seconds. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b7db5a --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Balcony Weather Station Dashboard + +This is a real-time, neighborhood-facing weather dashboard that streams sensory data from an MQTT broker (Home Assistant) to a web interface. + +## Tech Stack Overview +- **Backend:** Gleam (Target: Erlang/OTP) +- **Web Server:** Mist (HTTP & WebSockets) +- **Database:** SQLite (via `sqlight`) for persistent uptime tracking +- **Frontend:** SolidJS (Signals-based reactivity) + Tailwind CSS +- **Infrastructure:** Nomad (Docker-based deployment)