GET /api/stats?range=7d|30d computes compressor, CWU, CO and heater hours,
compressor starts and temperatures per Europe/Warsaw day from the raw
heat_pump polls. Hours hold each poll for at most 600 s so gaps add nothing;
starts are 0 -> >0 transitions and are a lower bound at 300 s polling.
Historia gets a Wykresy | Statystyki switch (shared SubView helper, also
used by Energia) with totals tiles, a daily chart and a cycling hint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reserve stepper with the API's bounds, schedule edit mode with a
confirmation summary and Polish results; hidden when not editable.
Stepper and Button move to ui.tsx for reuse.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
POST /api/battery/schedule and /api/battery/reserve with the same
guards as the other writes; /api/battery shows the reserve and whether
changes are possible.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Token-protected /battery/schedule and /battery/reserve: allowlisted Time
of Use changes checked as a whole against a fresh reading and the live
registers, FC16 per range, read-back, audit, rate limit per register.
The reserve is an app setting kept in reserve.json.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Needed for the Deye's program table; works over Solarman V5 unchanged,
as the RTU frame wraps any PDU. The echo of address and count is checked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A segmented switch (Teraz, Bateria, Falowniki) kept in the URL hash so
Back returns to the previous view; tapping the battery in the flow
diagram opens Bateria. The device list moves to Falowniki.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A running pump, pump chip and headline are red instead of green; stopped
stays grey and the alarm is now solid so the two cannot be confused. The
BME280 reading shows in a Salon card, with brak odczytu when stale.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The derived targets and setpoint fields stayed old until the next 300 s poll.
The extra poll runs on the device's own poller thread, so it never overlaps
another read, and requests within the delay coalesce into one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One stepper per preset change under Powrót, lowering only; a setpoint
already at its minimum disables the row and the confirmation. The steppers
of Nastawy and Wyjazd share one component.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
POST /api/presets/{id} accepts optional values per setpoint of the preset,
checked against the gateway's limits before anything is sent, so Wyjazd
can use temperatures other than the defaults.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /commands showed the last poll for up to 5 minutes after a write.
It now shows the value read back after our own write or restore when
that is newer than the poll. POST /commands/restore runs a pending
restore at once through the normal path (conflict check, read-back,
audit with the requester, rate limit).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tapping Wyjazd opens a form with a datetime-local picker (from one hour
to 30 days ahead, default in a week at 18:00) and sends the chosen time
with the local offset. A held restore shows its end date, for example
"do 2 lis, 18:00, potem 43 °C".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A preset with "until": "chosen" needs {"until": ...} in POST
/api/presets/{id} and sends each change to the gateway as a held change
(ADR-012). Wyjazd becomes such a preset. A held preset that would not
lower a setpoint is refused up front, so it never stops half way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A command may carry "until" (ISO-8601 with offset). The change is stored
as a restore with leaseUntil = due = until, so it survives a restart and
runs at its end. Held changes must lower the value below both the current
value and the original, end in the future and within 30 days; otherwise
they are rejected without a write. Renewals now only extend a lease.
ADR-012 amends ADR-011 for held changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>