tliu93
8d4f496ff4
DSMR hardening: restart-free config + decouple from telegram id
...
Config hot-reload (no restart):
- MqttManager.unsubscribe(); apply_dsmr_subscription(settings) re-applies the
DSMR subscription (subscribe/unsubscribe/topic-change, fresh snapshot so the
sample interval also takes effect).
- Called from lifespan AND PUT /api/config, so toggling DSMR ingest in the UI
takes effect immediately without restarting the app.
Decouple ingest from the DSMR telegram id (overflows / resets to zero):
- Migration 20260624_12: drop UNIQUE(source_id), make recorded_at UNIQUE.
- Idempotency now keys on recorded_at (telegram timestamp); the table's own
autoincrement PK is the stable identity. source_id kept only as a reference.
- Regression test: colliding telegram ids no longer drop new data.
2026-06-24 11:02:32 +02:00
tliu93
df54f5518b
M6-T02: add DSMR + Tibber flat config fields
...
- Settings: dsmr_ingest_enabled, dsmr_mqtt_topic, dsmr_sample_interval_s,
tibber_api_token (secret), tibber_home_id (all opt-in / off by default).
- CONFIG_FIELDS DSMR + Tibber sections; _settings_payload extended.
- .env.example examples; test_api_config coverage (sections, secret, 422).
2026-06-23 20:43:46 +02:00
tliu93
35cdc7f22a
M5: use DB-merged runtime settings for MQTT/discovery; add MQTT test button; move Expose panel into config accordion
2026-06-22 20:11:54 +02:00
tliu93
75d685f04d
M5: roll Energy chart window for live auto-refresh (English label); render boolean config fields as switches
2026-06-22 19:40:18 +02:00
tliu93
14b846549e
M5-T08: add MQTT, HA Discovery, and Modbus polling config fields
2026-06-22 14:27:21 +02:00
tliu93
a9830c42d8
M2-T11: serve React SPA from FastAPI and remove Jinja pages
...
- app/main.py serves the SPA build (SPA_DIST_DIR, default frontend/dist):
mounts /assets and a GET catch-all returning index.html for client routes;
catch-all 404s on /api/*, never swallows /docs, /openapi.json, /static, assets,
ingestion/ticktick/status; skips SPA serving when dist absent (backend-only CI)
- delete app/api/routes/pages.py, app/api/routes/auth.py, app/templates/
(all replaced by /api/* + SPA; auth service layer kept)
- remove/replace Jinja page tests (JSON coverage already in test_api_*);
add tests/test_spa_hosting.py for the fallback contract
- regenerate openapi/ (Jinja paths gone) and frontend schema.d.ts
2026-06-13 15:20:50 +02:00
tliu93
2bc5d6ea9a
M2-T05: add SMTP test action API (POST /api/config/smtp/test)
...
- reuses send_smtp_test_email; tri-state result success(200)/config-error(400)/failed(502)
- session + CSRF protected; never echoes SMTP secrets
- SmtpTestResponse schema; regenerate openapi/
- extend tests/test_api_config.py (3 states + 401 + missing-CSRF 403)
2026-06-13 15:20:50 +02:00
tliu93
c2b1b7b751
M2-T01: add config JSON API (GET/PUT /api/config)
...
- new app/api/routes/api/ package with shared require_session (401) and
require_csrf (presence-only X-CSRF-Token, 403) dependencies
- GET /api/config returns masked config sections; PUT /api/config reuses
save_config_updates (blank secret keeps old; invalid -> 422, no write)
- session-protected; PUT also CSRF-protected
- register router in app/main.py; regenerate openapi/
- tests/test_api_config.py
2026-06-12 23:08:14 +02:00