Each image gets the release tag as the VERSION build arg. The gateway
reports it in /health, the backend adds its own and the gateway's to
/api/health, and the Stan screen lists all three.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The gateway now reads the Deye lifetime counters, inverter power and
temperatures, and the meter's per-phase energy into house_meter_phases.
A group can take its fields from another measurement of the same device.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new fields added seven requests per poll over the Solarman logger.
Neighbouring registers now share one request, so each poll again makes
ten round trips.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without renewals the gateway restores every change after 15 minutes, so a
lost backend or tunnel never leaves the house on boost or away settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A "Urządzenia" card lists the Deye, Fronius and house meter as rows with
a "Szczegóły ›" chevron, 56 px high. Tapping one opens a bottom sheet on
a phone (a dialog on wide screens) with the grouped values; it closes by
button, backdrop or Escape and returns focus to the row.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Groups of labelled values for the Deye, Fronius and house meter, so the
energy screen can show more without crowding it. A stale device has no
groups; a field the device did not report is left out.
The catalog of labels, units and groups lives in the backend
(EnergyDetailsService): the frontend renders whatever groups arrive, so
a new field is one line in one file and needs no UI release. It also
keeps field names out of TypeScript and lets the backend round values
(Wh to kWh) once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Verified live on 2026-10-24 (read only, two dumps a minute apart): totals
are 32-bit low word first and stay above the today counters, PV V x A
matches PV W within the 0.1 A resolution, per-phase inverter power sums
to 636, battery current agrees with battery power, frequency is 49.95 Hz.
Rejected as unclear: alarm words 552-558, inverter and load currents
(scale does not fit), registers 592 and 604-607.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A change now keeps a restore that runs at the earlier of its end time and a
15 minute lease; POST /commands/renew extends live leases. A lost backend or
tunnel can no longer leave boost or away settings on the controller.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One extra FC4 request per poll; PRAD2 is unchanged and still written when
the extra request fails.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The RS485 converter at 192.168.0.10 forwards raw RTU frames (unit, PDU,
CRC-16), as sdm_modbus does with ModbusRtuFramer. The gateway sent Modbus
TCP with an MBAP header, which the converter never answers, so every poll
timed out. TcpTransport now takes a framing: MBAP for MK01, RTU for the
meter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Pi every other heat pump poll failed with 'Connection reset by
peer': MK01 drops a connection left idle for minutes, and the gateway
kept one open between polls (300 s). The socket now closes after 5 idle
seconds and the next poll connects anew, which also frees the single
MK01 connection for the vendor's app between polls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each part gets a Dockerfile and a compose.yaml. The Dockerfiles build on
the runner's own platform and only copy into the final stage, so CI
makes the Pi's arm64 gateway image without emulation. A pushed tag
(scripts/release.sh) publishes them in the Gitea registry; on the Pi
update.sh pulls a release with its compose.yaml and goes back to the
previous one when /health fails or the container restarts. nginx in the
frontend image serves the UI and passes /api/ to the backend.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The gateway moves from the root to gateway/, the web UI from backend/web
to frontend/ with its own build into dist/. The backend drops static
files and the frontend-maven-plugin and answers 404 outside /api/, still
with the security headers. check.sh builds and tests all three; CI sets
up Node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The user chose to defer the login: Traefik admits only Krosno and clears
a client's Remote-User. A later ADR picks the login before access from
outside.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With http.bind on the WireGuard address the gateway no longer answers on
localhost, so every deploy would have rolled back. The script now reads
http.bind and http.port from gateway.json on the Pi.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hand-drawn scene showed an outdoor unit and no photovoltaics; ours is
a ground-source pump in the boiler room. The overview now shows a
generated cutaway of the house (research/ui/house-cutaway.webp) with an
SVG layer on top: each pipe circuit, found by colour into a mask by
scripts/house-assets.py, flows while its pump runs and is grey while it
stands; the heat pump and tanks glow while they work, warmth rises from
the floor, light sweeps over the PV panels, and callouts carry the live
values. The backend serves .webp.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plain-JS UI was too weak to grow into the reference dashboard. The new
UI (React, TypeScript, Vite, Tailwind, Recharts) follows research/ui/: a
side bar on large screens, tabs on a phone, and an SVG picture of the
installation whose pipes flow, compressor turns and tanks glow while the
matching pump runs. Energy flows are animated the same way.
Maven builds and tests the UI (frontend-maven-plugin, Node per project),
so check.sh and CI need only Java. The fixes of the web review (stale and
missing readings, silent inverters, outages, Warsaw time, timeouts,
out-of-order answers, restore values) carry over; tests read the API
contract examples. The CSP now allows the self-hosted font.
Supersedes fix/web-review. ADR-008 records the new UI stack.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PV series sums three measurements; asking one after another tripled
the wait on the energy screen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GATEWAY_URL and INFLUX_URL with a path now fail at start instead of
having the path silently dropped.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>