Add device telemetry history + per-device graph view
activity_log only ever recorded state transitions/overrides/sync/errors — useful for "what did the app decide" but not "what was the room actually doing" when a guest/staff complaint comes in after the fact. Backend: - New device_readings time-series table (room_temp, target_temp, mode, power_state, fan_speed, valve_position, heating_active), throttled to ~1 row/device/minute via recordReading() in db.js regardless of how often a caller fires — MQTT pushes can be far chattier than that. - Wired into every place zone_devices' live-status cache already gets updated: ac-poller.js, daikin-poller.js, and mqtt.js's TRV (handleStatusBlob/handleInfo) and native-MQTT MHI (writeMhiState) handlers. - 4-day retention by default (config key history_retention_days), pruned every 6h by the new history-pruner.js. - GET /api/devices/:id/history?hours=96 to read it back. Frontend: - DeviceHistoryModal: room temp vs setpoint line chart, plus a valve-position chart (TRVs) or fan-speed step chart (AC), plus a diffed mode/power/fan change log — 24h/4d/7d range picker. Uses recharts, matching the convention already established in utilities/wages/reports. - Graph icon on each device in both ZoneDetailModal and the Devices page opens it. Side effect: frontend/package-lock.json was missing vite-plugin-pwa's whole dependency tree even though package.json already declared it — pre-existing drift, reconciled by this npm install (unrelated to the recharts addition, just came along with it).
This commit is contained in:
parent
59a3e091d8
commit
f0b4ac3c41
15 changed files with 5172 additions and 38 deletions
|
|
@ -307,6 +307,22 @@ html, body, #root { height: 100%; margin: 0; font-size: 14px; }
|
|||
display: flex;
|
||||
}
|
||||
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; flex-wrap: wrap; }
|
||||
.modal-lg { max-width: 820px; }
|
||||
|
||||
/* ── Device history chart ─────────────────────────────────── */
|
||||
.history-range-row { display: flex; gap: 6px; margin-bottom: 12px; }
|
||||
.history-chart-title { font-size: 12.5px; font-weight: 600; color: var(--text-mid); margin: 14px 0 4px; }
|
||||
.history-tooltip {
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--card-border);
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
padding: 8px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.history-tooltip .ht-time { font-weight: 600; color: var(--text-dark); margin-bottom: 4px; }
|
||||
.history-tooltip .ht-row { display: flex; align-items: center; gap: 6px; color: var(--text-mid); }
|
||||
.history-tooltip .ht-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
|
||||
|
||||
/* ── Timeline / activity log ──────────────────────────────── */
|
||||
.timeline { margin: 8px 0; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue