# mqtt_washingMachine ## Overview A small Go service that shows whether the laundry is done using the Tasmota plug's MQTT `ENERGY.Power` readings. The phone-first page has a white background, a large status message, and the last three power readings, such as `47.70W`. Missing readings appear as `--`. The backend runs continuously, even with no page open. Every 60 seconds it records the latest valid message received since the previous tick, or a missing sample if none arrived. It keeps only the last three samples in memory, oldest first. The page fetches the current status on load and every 60 seconds. ### Status rules Rules apply in this order: | Condition | Message | Color | |-----------|---------|-------| | Fewer than three samples recorded since startup | Waiting for data... | Grey | | Any of the last three samples is missing | Incomplete data | Grey | | Any sample is at least 3.00 W | Laundry not yet done | Red | | All three samples are below 3.00 W | Laundry done | Default text color | Exactly **3.00 W is active**; `2.99 W` and `0 W` are idle. Malformed JSON and payloads without numeric `ENERGY.Power` are logged and ignored; they do not replace the last valid message or make a missing interval valid. If the HTTP request fails, the page shows a grey "Status unavailable" message and retries at the next refresh. ## Getting Started ### Docker Compose Install Docker with the Compose plugin on a server that can reach your MQTT broker. From this repository, run: ```bash docker compose up --build -d docker compose logs -f laundry-status ``` Open `http://:8080/` on a phone connected to your home Wi-Fi. By default the service connects to `192.168.1.12:1883` and subscribes to `tele/tasmota_washingmashine_C21183/SENSOR`. No broker is included in the Compose file; it connects to your existing one. To override settings, export the environment variables below or place them in a local `.env` file before running Compose. For example: ```bash MQTT_BROKER=tcp://192.168.1.12:1883 docker compose up --build -d ``` Keep credential files local. The Docker build context excludes `.env` files. The container runs as an unprivileged user, with a static Go binary and embedded page; no volume or database is required. Stop it with `docker compose down`. ### Configuration | Variable | Default | Description | |----------|---------|-------------| | `MQTT_BROKER` | `tcp://192.168.1.12:1883` | Broker URL, including scheme and port | | `MQTT_TOPIC` | `tele/tasmota_washingmashine_C21183/SENSOR` | Tasmota sensor topic | | `MQTT_USERNAME` | Empty | Optional MQTT username | | `MQTT_PASSWORD` | Empty | Optional MQTT password | | `HTTP_ADDR` | `:8080` | HTTP listen address | | `SAMPLE_INTERVAL` | `60s` | Positive Go duration between samples, for example `60s` or `1m` | Empty variables use the defaults. In Docker, keep the HTTP listen address on all interfaces (for example `:8080`). If you change its port, also update the target port in the Compose `ports` mapping. To change only the published host port, edit the left side of `8080:8080` and leave `HTTP_ADDR` unchanged. Changing `SAMPLE_INTERVAL` affects backend sampling and the three-sample window; the browser still refreshes every 60 seconds. Invalid or nonpositive intervals stop startup with an error. The service retries an unavailable broker in the background and subscribes again after reconnecting. HTTP remains available during broker outages; intervals without valid messages become missing data. ### Tasmota setup Configure the plug to publish sensor telemetry to the topic above, with a payload containing a numeric power measurement, for example: ```json {"ENERGY":{"Power":139.60}} ``` The plug currently uses `TelePeriod 10` (about six messages per minute). Sampling does not depend on that exact setting: any telemetry interval works, but an interval longer than `SAMPLE_INTERVAL` can leave gaps and show "Incomplete data". Only the latest message within each sampling interval is used; this is not an average of all measurements. ### Run and validate locally Install Go 1.26 or later, then run: ```bash go run . ``` Validation commands: ```bash go fmt ./... go vet ./... go test ./... go test -race ./... docker build -t laundry-status . ``` No automated E2E command is configured. For a manual MQTT smoke check, run the service against a test broker and topic with `SAMPLE_INTERVAL=1s`. Use `mosquitto_pub` to send a message repeatedly, at least once per second: ```bash mosquitto_pub -h -t -m '{"ENERGY":{"Power":2.99}}' ``` After three valid samples, `/api/status` should report `done`. Publish `3.00` to get `running`, then stop publishing for a sample interval to get `incomplete`. Reload the page to inspect each result immediately. Check the page at 360 px width for readable text and no horizontal scrolling. ### Status API `GET /api/status` returns JSON with a state, display message, and zero to three readings ordered oldest first. Responses are not cached. For example: ```json {"state":"incomplete","message":"Incomplete data","readings":[{"power":47.7,"valid":true},{"power":0,"valid":false},{"power":2.99,"valid":true}]} ``` Use `valid` to distinguish a missing sample from a real zero-watt reading. Startup returns `{"state":"waiting","message":"Waiting for data...","readings":[]}`. ### Limitations - In-memory state only: a restart clears the window. With the default interval, the service shows "Waiting for data..." for approximately three minutes. - A single device and three samples only; no persistent history or notifications. - This is an idle-power heuristic. An unused machine or a sufficiently long pause below 3 W also results in "Laundry done"; it does not track wash-cycle phases. - Use on a trusted home LAN only. HTTP has no TLS or authentication; keep the published port off the public internet. ## AI Workflow This project includes the persistent planner/implementer/reviewer workflow with file-based coordination, plus the PO orchestration layer. Manual and auto are two runtime modes for the same scaffold: they use the same generated files, task board, and review gate. Fewer role sessions means less coordination overhead and lower token cost. ## Modes This scaffold supports two workflow profiles that share the same generated files, task board, plan, review log, and handoff log. - `full` keeps the planner, implementer, reviewer, and optional PO split. - `lite` keeps the planner but replaces separate implementer/reviewer sessions with one `aide dev` session. | Profile | Sessions and launchers | Who drives work | Commit cadence | PO support | Recommended fit | |---------|------------------------|-----------------|----------------|------------|-----------------| | `full` | `aide plan`, `aide implement`, `aide review`, optional `aide po` | Separate role sessions with explicit implement/review handoffs | One final task commit after reviewer approval | yes | Larger, riskier, or more review-heavy changes | | `lite` | `aide plan`, `aide dev` | Planner plus one dev session that implements and reviews, then halts for human approval at `ready_for_review` | One real commit per task, including `all_task` | no | Smaller changes or lower-coordination work | ### How to switch ```bash aide profile full aide profile lite ``` Use `aide profile full` to return to the split workflow, or `aide profile lite` to switch to the dev-session flow. `full` is the default for new scaffolds. When you switch to `lite`, `aide implement`, `aide review`, and `aide po` refuse and point you at `aide dev`. When you switch back to `full`, `aide dev` refuses and points you at `aide implement` and `aide review`. ### Runtime modes - Manual mode: start the planner, implementer, and reviewer in separate terminals, then drive each session yourself with the documented text commands. - Auto mode: run `aide po` to start the PO session, which uses MCP tools to coordinate the post-planning implementer/reviewer workflow for you. ### Concepts **Cycle** — a unit of work on a feature branch. One cycle = one branch = one PR. **Roles and file ownership:** | Role | Reads | Writes | |------|-------|--------| | PO | `.ai/TASKS.md`, `.ai/PLAN.md`, `.ai/REVIEW.md`, `.ai/prompts/po.md` | MCP session commands via `aide po` | | Planner | `ROADMAP.md` | `.ai/PLAN.md`, `.ai/TASKS.md` | | Implementer | `.ai/PLAN.md`, `.ai/REVIEW.md` | source code, `.ai/TASKS.md` | | Reviewer | `.ai/PLAN.md`, commits | `.ai/REVIEW.md`, `.ai/TASKS.md` | **Status flow:** ```text in_planning → ready_for_implement → in_implementation → ready_for_review → in_review → ready_to_commit → done ↑ | └──── changes_requested ◄─────────────┘ ``` ### Start a new development cycle ```bash # Edit ROADMAP.md with your goals first, then: aide cycle start feature/ ``` ### Full profile quick start ```bash aide plan # terminal 1 aide implement # terminal 2 aide review # terminal 3 ``` Launch each role once, then keep those sessions open for the rest of the cycle. Role launchers read default agent/model settings from `.ai/config.json`. To override, pass the agent first, then any CLI flags. Example: `aide review claude --model sonnet` Claude starts interactively by default, and the Codex launcher uses interactive `codex` mode so the session stays open for role commands. ### Lite profile quick start ```bash aide profile lite aide plan # terminal 1 aide dev # terminal 2 ``` The dev session handles implementation and review, then halts for human approval at `ready_for_review`. In lite mode, `aide implement`, `aide review`, and `aide po` refuse and point you at `aide dev`. ### Start the PO orchestrator (auto mode) ```bash aide po ``` The PO session drives the post-planning task board flow through the `aide` MCP server. PO orchestration is available only in the `full` profile. By default, `aide po` launches Claude with `--model haiku`, and `aide po codex` launches Codex with `-m gpt-5.4-mini`. `.ai/config.json` can override those defaults, and an explicit CLI `--model` or `-m` flag takes precedence. If no tasks are in `ready_for_implement` or later, run the planner first. The normal MCP completion path is `session_run` followed by `session_wait`, then a re-read of `.ai/TASKS.md`; `session_get_output` is for debugging only. The MCP server appends structured debug logs to `.ai/mcp-server.log`, and the scaffold gitignore excludes that file. ### Drive work inside the existing sessions ```text planner> start_plan implementer> next_task T-001 reviewer> next_task T-001 implementer> commit_task T-001 dev> next_task T-001 dev> commit_task T-001 implementer> rework_task T-001 aide cycle end 0.7.0 ``` Cross-platform CLI equivalents: `aide cycle end [VERSION]` closes the cycle outside the persistent role session, and `aide pr [--dry-run]` creates or updates the branch PR. **Planner commands:** Before `start_plan`, freeform conversation with the planner is the roadmap-refinement phase. Use it to sharpen scope, acceptance criteria, constraints, and trade-offs directly in `ROADMAP.md`. `start_plan` is the explicit handoff into formal planning. | Command | Description | |---------|-------------| | `start_plan` | Read `ROADMAP.md`, write `.ai/PLAN.md` and `.ai/TASKS.md` | | `rework_plan [TASK_ID]` | Revisit the plan when scope or approach changes | **Implementer commands:** | Command | Description | |---------|-------------| | `next_task [TASK_ID]` | Pick up the next `ready_for_implement` task | | `commit_task [TASK_ID]` | Turn a `ready_to_commit` task into one clean final commit, including task-specific `.ai/` artifacts | | `rework_task [TASK_ID]` | Address `changes_requested` findings from `.ai/REVIEW.md` | | `aide cycle end [VERSION]` | Close the cycle after all tasks reach `done`, committing remaining `.ai/` artifacts with a `Release-As:` footer | | `status_cycle [TASK_ID]` | Show task status and recommended next action | **Reviewer commands:** | Command | Description | |---------|-------------| | `next_task [TASK_ID]` | Pick up the next `ready_for_review` task and run review plus verification | | `status_cycle [TASK_ID]` | Show task status and recommended next action | ### File map | File | Purpose | Tracked | |------|---------|---------| | `.ai/PLAN.md` | Current plan | yes | | `.ai/TASKS.md` | Task board with status | yes | | `.ai/prompts/po.md` | PO orchestration prompt for auto mode | yes | | `.ai/REVIEW.md` | Review findings | yes (tracked cycle log) | | `.ai/HANDOFF.md` | Runtime handoff log | yes (tracked cycle log) | | `.ai/config.json` | Per-role launch defaults | yes | | `ROADMAP.md` | Cycle goals (edit before planning) | yes | | `AGENTS.md` | Project-specific and workflow-managed agent rules | yes | | `CLAUDE.md` | Agent instruction entry point (`@AGENTS.md`) | yes | | `aide po` | Launch the PO orchestration session | yes | ### Create a PR ```bash aide pr ``` Full workflow details and session recovery rules are in `AGENTS.md`.