-
released this
2026-08-28 14:46:56 +02:00 | 3 commits to main since this releaseAllocate thermal standing charges between Heating and Hot Water totals so they sum to All-in, and run Mantine tests in test mode with bounded workers to prevent act-warning log floods.
Downloads
-
released this
2026-08-28 01:26:58 +02:00 | 6 commits to main since this releaseSplit meter discovery devices, repair legacy thermal topics and registry bindings, and add combined hot-water cost entities.
Downloads
-
released this
2026-08-27 22:06:42 +02:00 | 7 commits to main since this releaseFixes the v1.6.0 Sources API failure on migrated installations where DSMR_SAMPLE_INTERVAL_S=0. Zero retains its legacy persist-every-telegram meaning; other numeric validation remains strict. No database migration or data repair is required.
Downloads
-
released this
2026-08-27 21:02:20 +02:00 | 8 commits to main since this releaseAdds protocol-agnostic meter sources and bindings, read-only WarmteLink P1 ingestion, scoped thermal contracts and billing, Home Assistant entities, lifecycle recovery workflows, deployment hardening, and Energy UI polish.
Downloads
-
released this
2026-08-06 22:22:20 +02:00 | 58 commits to main since this releaseFix: the Energy Costs Summary labelled its Import/Export cards "(kWh)" while
displaying monetary totals, so today's page read "Import 1.339 kWh" when the
meter had imported 4.188 kWh.GET /api/energy/costs/summary now additionally returns metered_import_kwh and
metered_export_kwh (Σ d1+d2 / Σ r1+r2 over non-degraded periods). The cards
show kWh as the headline figure with the monetary equivalent as a sub-line.Additive API change; the Home Assistant outbound sensors read only the existing
money fields and are unaffected.Downloads
-
released this
2026-07-27 20:31:13 +02:00 | 59 commits to main since this releaseFixes
- prices: the chart keyed its X axis on "HH:mm" labels, which repeat across a
today+tomorrow range. Recharts resolves axis tooltips by value, so hovering a
slot after midnight matched today's identically labelled point — the tooltip
showed today's prices and the marker jumped back to today's position. The axis
is now keyed on the ISO instant; ticks still read HH:mm and the tooltip label
carries the date.
Features
- prices: the price slot currently in effect is marked by default with a dot on
the buy and sell lines, plus a caption with its prices; re-evaluated every 30s.
Chores
- frontend: regenerate src/api/schema.d.ts, which had drifted from
openapi/openapi.json sinced07a083and was failing CI's codegen check. - docs: the validation gates now spell out that a route/schema/docstring change
needs bothscripts/export_openapi.pyandnpm run codegencommitted.
Downloads
- prices: the chart keyed its X axis on "HH:mm" labels, which repeat across a
-
released this
2026-07-17 18:53:20 +02:00 | 64 commits to main since this releaseBug fix release.
- fix(tibber): priceInfoRange now uses last:192 instead of first:96, so the
hourly refresh fetches the newest quarter-hourly slots (today + tomorrow)
instead of being stuck on the oldest slots anchored at the subscription start
date. Fixes the empty "No Tibber price points available" state on the energy
prices page for contracts added mid-period. - test(energy-cost): pin local_now in the future-window summarize test so it is
deterministic regardless of the wall-clock date.
Downloads
- fix(tibber): priceInfoRange now uses last:192 instead of first:96, so the
-
released this
2026-06-30 17:20:55 +02:00 | 66 commits to main since this releasev1.4.0 — DDSU666 Modbus meter support
Adds support for the CHINT DDSU666 single-phase smart meter alongside the
existing Eastron SDM120, and generalizes the Modbus read driver so the read
function code is chosen per device profile instead of being hardcoded.
Validated end-to-end against real DDSU666 hardware.Highlights
- 🆕 DDSU666 support — a second supported energy meter model.
- 🔧 Per-profile read function code — the driver now selects FC03 (holding) vs FC04 (input) registers based on the device profile.
- ✅ Hardware-validated — confirmed on a live DDSU666 (big-endian word order, FC03 reads, energy accumulation).
Added
- DDSU666 device profile (
ddsu666.yaml): reads via FC03 holding registers — voltage, current, active power (kW), reactive power (kvar), power factor, frequency, import/export active energy. Big-endian word and byte order. - DDSU666 Modbus protocol reference (
docs/references/DDSU666-Modbus-Protocol.md), extracted from the official CHINT manual: register map, frame format, function codes, CRC/exception handling, an SDM120 comparison table, and field notes from real-hardware validation.
Changed
driver.read_blocksnow selects the read function code per profile (function_code: 4 = FC04 input registers — default, SDM120; 3 = FC03 holding registers — DDSU666), validated before connecting. Previously the read path was hardcoded to FC04 and the profile'sfunction_codefield was declared but never honored.function_codeis now threaded through every read path: themodbus_cli readcommand, the background poller, and the device/testendpoint. The CLIreadoutput additionally prints the active function code.
Compatibility
- SDM120 behavior is unchanged (still FC04).
- No API or OpenAPI schema changes.
- Read-only — no meter configuration registers are ever written.
Verification
- Full test suite green (1037 passed), ruff clean, OpenAPI unchanged; multi-stage Docker image builds, migrates, and boots cleanly.
- Confirmed on a live DDSU666: big-endian word order correct, FC03 reads decode to sensible values, cumulative energy (kWh) accumulates correctly.
- Note: at load currents below the meter's measuring range (Imin ≈ 0.25 A), the instantaneous active power and power factor read 0 while energy still accumulates — expected meter behavior at very low current, not a decoding issue.
Docs
- Roadmap updated to queue Authentication next-steps (sliding session renewal + long-lived token targets).
Downloads
-
released this
2026-06-27 11:18:24 +02:00 | 68 commits to main since this releasev1.3.0
A large release covering everything since v1.2.0 — it takes the backend from
single-user auth hardening through a full IoT + energy-metering stack with deep
Home Assistant integration.Highlights
- Home Assistant integration via MQTT Discovery — Modbus devices and energy-cost sensors auto-appear in HA.
- Energy metering & cost engine — DSMR smart-meter ingest, manual/dynamic pricing (incl. Tibber), per-15-minute cost billing with standing charges and tax credits.
- Meter epochs (meter-swap archival) — swapping a physical meter spins up a brand-new HA sensor and never mixes readings across meters.
- Login hardening — TOTP two-factor auth plus exponential login back-off.
Authentication & security (M4)
- Two-factor authentication (TOTP): QR setup, recovery codes, and a two-step login flow.
- Exponential back-off throttling on failed logins.
admin_cliescape hatches: reset password, unlock account, disable/reissue TOTP, list admins.
IoT devices & Home Assistant (M5)
- Generic Modbus TCP polling: device CRUD, JSON readings, YAML device profiles (e.g. SDM120), opt-in scheduled polling, cascade delete.
- MQTT client with lifespan connect / auto-reconnect and a config "test" button.
- Home Assistant MQTT Discovery: an entity-exposure framework with per-entity enable/disable toggles; publishes discovery configs, state, and availability under the
home_automationtopic prefix. - UI: sidebar navigation, Energy/device management views, latest-reading cards + trend charts, accordion config, and a Home Assistant expose panel.
- DB-level foreign-key enforcement (SQLite
foreign_keyspragma).
Energy pricing, DSMR & cost engine (M6)
- Pluggable pricing layer with manual and Tibber strategies plus profile validation.
- Energy contracts with versioned tariffs.
- DSMR P1 telegram ingest over MQTT.
- Billing engine: per-15-minute period cost computation, dual-tariff buy/sell prices, standing fees folded into import cost and the energy-tax credit into export revenue; summary + retroactive recompute.
- Tibber GraphQL client with hourly price refresh (today + tomorrow).
- Energy API (prices / costs / summary / latest DSMR / recompute / Tibber test) plus frontend contract management, price/cost views, and a DSMR data panel.
Meter epochs / meter-swap archival (M7)
- New
metertable modelling each physical meter's install window[started_at, ended_at); cost periods now carry ameter_id. - Meter-aware billing: never computes a register delta across two meters; periods straddling a swap boundary are marked degraded; added a delta sanity guard.
- Cumulative cost sensors are anchored to the active meter's start, so a swap cleanly resets the running totals for the new meter.
- Meter CRUD API with retroactive recompute, plus a meter-management UI (timeline, declare swap, edit).
- Each meter has a stable UUID used as its Home Assistant identity, and the energy-cost HA device is named after the meter label — so swapping a meter produces a brand-new HA device/sensor and never contaminates old data. Discovery is re-published automatically on meter changes.
Energy time & Home Assistant midnight handling (follow-ups)
- All energy time math localized to the server timezone; the UI shows energy/DSMR/meter times in local time (24h).
- Fixed fees and the energy-tax credit accrue per local calendar day; any day with recording counts its full-day credit (symmetric start/end-day handling).
- Daily-resetting "today" cost/revenue sensors in addition to lifetime totals.
- Midnight handling tuned for Home Assistant statistics: the daily "today" reset is shifted to just past local midnight (robust to a few seconds of clock skew between hosts), and each day's fixed fee + tax credit are settled at ~01:05 local — off the midnight hour-boundary — so HA attributes them to the correct day and the energy dashboard's daily costs stay accurate.
- Billing robustness: ignore stale / out-of-range DSMR readings; energy-cost sensors marked always-available.
Upgrade notes
- Database migrations run automatically. The new
metertable is created and backfilled — existing electricity history is attributed to an initial meter with a generated UUID. No data is deleted. - After upgrading, declare your meter (set its label) so the Home Assistant energy-cost device is named correctly. The old generic "energy-cost" HA device is superseded by a per-meter device; you may delete the stale one in HA.
- (Optional) To include standing charges and the tax credit in the Home Assistant Energy dashboard, set the grid cost source to "Use an entity tracking the total costs" pointing at
import_cost_total(andexport_revenue_totalfor return-to-grid).
Downloads
-
v1.2.0
Stablereleased this
2026-06-13 17:21:26 +02:00 | 147 commits to main since this releaseReplaces the server-side Jinja pages with a same-origin React single-page app,
backed by a new JSON API. Same container, same origin (no CORS); auth still
rides the existing Argon2 + server-side session cookie.Added
- React SPA (Vite + TypeScript + Mantine + TanStack Query + React Router),
served same-origin from FastAPI as static build output. - JSON API for the SPA:
GET/PUT /api/config— config read/writePOST /api/config/smtp/test— SMTP test action- read-only data query endpoints (location / poo)
- single-record CRUD (
PATCH/DELETE) - session/auth endpoints (
/api/session, login, logout, forced password change)
- Data visualization: Leaflet heatmap home page (viewport-normalized
intensity, dark basemap) + records-management UI (paginated lists, edit/delete
modals) — takes over what Grafana used to do. - Typed OpenAPI client generated from
scripts/export_openapi.pyoutput. - Multi-stage Dockerfile (node build → python runtime) + frontend CI workflow.
- Explicit
docker-compose.dev.ymldev stack (port 8001,-devcontainer
names, prod-copy./dataDB). - Dark-mode toggle, Feather-icon nav, Grafana-style quick time-range presets.
Changed
- Browser endpoints reuse the existing session-cookie auth with presence-only
CSRF (X-CSRF-Token). - README + architecture-overview updated for the SPA reality; retire the
"no frontend/backend split" and "Grafana as visualization" constraints.
Removed
- Jinja templates (
base/config/home/login.html) and the oldauth.py/
pages.pypage routers. docker-compose.override.yml(renamed to the explicitdocker-compose.dev.yml).
Fixed
- Logout no longer floods
GET /api/sessionwith 401s — the session probe and
the login endpoint own their 401s, breaking the redirect→refetch loop. - Heat-layer white-screen crash on first load after login.
Notes
- The device ingestion endpoint stays on bare API until M3 (token auth).
- TOTP 2FA for the now public-facing dashboard is recorded under
Future Ideas — not scheduled.
Downloads
- React SPA (Vite + TypeScript + Mantine + TanStack Query + React Router),