/**
* DsmrPanel — shows the latest parsed DSMR telegram (the source of our metering data).
*
* This is the "ground truth" view: it fetches GET /api/energy/dsmr/latest and
* renders the full parsed frame as a key/value table, so you can confirm at a
* glance whether DSMR ingest is actually landing data (without reading the DB).
*
* - Auto-refresh toggle (default on) so new telegrams appear without a manual reload.
* - Loading / error / empty states; "empty" explains the likely cause.
* - Null phase values are shown as "—" (kept verbatim in the payload).
*/
import { useState } from 'react'
import {
Stack,
Group,
Text,
Loader,
Center,
Alert,
Paper,
Table,
ScrollArea,
Switch,
Divider,
Badge,
} from '@mantine/core'
import { useDsmrLatest } from './hooks'
import { formatLocalDateTime } from '../utils/datetime'
/** Default auto-refresh interval (ms) — DSMR ingest stores ~one row per 10 s. */
const AUTO_REFRESH_INTERVAL_MS = 10_000
function formatValue(value: unknown): string {
if (value === null || value === undefined) return '—'
if (typeof value === 'object') return JSON.stringify(value)
return String(value)
}
export function DsmrPanel() {
const [autoRefresh, setAutoRefresh] = useState(true)
const latestQuery = useDsmrLatest(
autoRefresh ? { refetchIntervalMs: AUTO_REFRESH_INTERVAL_MS } : undefined,
)
return (
Latest DSMR reading
The most recent parsed telegram persisted to dsmr_reading.
)
}
if (isError || !data) {
return (
Failed to load the latest DSMR reading.
)
}
if (!data.found || !data.payload) {
return (
No DSMR data yet. Enable DSMR ingest in Config, make sure MQTT
is connected, and confirm the DSMR Reader is publishing to the configured topic
(default dsmr/json). Rows are stored about once every 10 seconds.
)
}
const payload = data.payload
const keys = Object.keys(payload).sort()
return (
{keys.length} fields
{data.recorded_at && (
recorded at {formatLocalDateTime(data.recorded_at)}
)}