# Roadmap Bottom-up: each milestone builds on a verified one below it, and master stays deployable. Closed milestones shrink to one line here; details stay in git history and in decisions/. ## Done - M0 Foundation · `v1.0.0`: `scripts/check.sh` gate in CI and pre-push, deploy with health check and rollback, `/ship` and `/close-milestone`. Baseline (`e345063`) still does the work: read-only, 8 heat pump values to InfluxDB every 300 s. ## Current: M1 Gateway: all readings Done when: a week on the Pi without manual action, Grafana unchanged. Existing measurements keep their names and fields; new data goes into new measurements (ADR-005). The heat pump stays at 300 s polls while the Frisko app is still in use (MK01 takes one client). - [x] Skeleton: `Reading`, ports `Device`, `ReadingSink`, `ModbusClient`, `ModbusTransport` - [x] Modbus core (ADR-007): FC3/FC4 codec, TCP transport, Solarman V5 transport - [x] Heat pump: legacy `Dom_Pompa.POMPA` fields unchanged; 4112–4119, 4201–4203, 4221–4228 and the setpoints into `heat_pump` - [x] House meter SDM630 (`electricity.PRAD2`) and BME280 via IIO (`measurement.MEASUREMENT`) - [x] Deye and Fronius into `electricity.deye`, `electricity.fronius` - [x] Influx writer: line protocol over JDK `HttpClient`, file buffer (fixes D2, D8) - [x] Poller: one virtual thread per device, snapshot, watchdog without `/health` polling (D1) - [x] HTTP: `/health` per device, `/snapshot` - [x] Config file outside the jar (D3), wire `Main`, drop modbus4j, influxdb-java and the baseline classes (D4, D5) - [x] Three parts with their images and compose (ADR-010); releases by tag, `update.sh` on the Pi - [x] On the Pi (2026-10-24): D7, Docker (no iptables, no forwarding), `gateway.json`, ufw 8080 on `wg0` only, `v1.1.1` running with the heat pump, Deye and Fronius; old service stopped - [x] On the Pi (2026-10-24): IIO overlay, BME280 and the meter in the gateway (`v1.2.1`: the meter's converter speaks RTU over TCP); `rpi-measurements` stopped and disabled - [ ] After the week: remove `rpi-measurements` and the old `home-pump.service` files ## Next | Milestone | Scope | Done when | |---|---|---| | M2 Understand the controller | Timing (safe poll rate, response times), which pumps run in which state, open questions in `docs/frisko/` | `docs/frisko/` reviewed; F3 limits agreed | | M3 Backend and web UI, read-only | Backend in Docker in Kraków: history from Influx, snapshot from the gateway; F1, F2, F5, F7 with the schematic and charts after `research/ui/`; Traefik route, sign-in (ADR-014), on the internet since v2.0.0 (ADR-016). Backend, frontend and their images are on master (ADR-008 proposed, ADR-010); open: `REGISTRY_TOKEN`, first release, the stack in homelab-compose (Arcane) | My father sees the heat pump and the energy on his phone | | M4 Setpoints | F3 through gateway commands with timed restore (ADR-006) and 15 min leases the backend renews (ADR-011), away held until a chosen date (ADR-012); CWU first, then CO; S1–S6. On master and wired, off until `commands.enabled` (gateway/README.md: Enabling commands): command service with restores, FC6, token-protected `/commands`, backend `/api/setpoints` and presets, UI tab Ustawienia | Father boosts hot water from his phone, value restored on time | | M4b Battery settings | F8 (ADR-013): Time of Use table and backup reserve from the Bateria view, FC16 with read-back, refused on stale or changed state; on branch/master and off until `deyeCommands.enabled` (gateway/README.md: Enabling battery commands) | Father changes the battery program from the app; first live write watched | | M5 Alarms | F4; decide the channel first (e.g. ntfy, Telegram) | Simulated alarm reaches the phone | | M6 Native app? | Decide: keep the web UI, WebView wrapper or React Native | Decision recorded | ## Known defects in the baseline - D1 Self-restart works only while something polls `/health` (`HealthMonitor`). - D2 Influx client logs every request (`LogLevel.FULL`), ~420 journal lines/hour. - D3 Config is packaged inside the jar. - D4 Dead code and config: `pollIntervalMs`, `windowSeconds`, `ModbusCachedWrapper`, write path. - D5 Single and batch reads use different addresses for registers ≥ 4100 (`ModbusRtuTcpRepository`). - D6 Development runs wrote test fields into the production `Dom_Pompa` database. - D8 Each field is written as its own point with its own timestamp, so one poll can split into points 1 ms apart (`InfluxMetricModbusSender`); write one point per poll. - D7 fixed 2026-10-24: Pi `AllowedIPs` only `10.0.0.0/24, 10.2.0.0/24`, and OPNsense NATs `192.168.0.0/24 → 10.0.0.2` to its tunnel address, as both sites use `192.168.0.0/24`. ## Knowledge - Controller: [docs/frisko/rx910-se21.md](frisko/rx910-se21.md) - Energy devices: [research/energy/](../research/energy/README.md) - UI reference: [research/ui/](../research/ui/README.md)