Show live values in a dashboard
This guide shows parameter readings in a dashboard you develop locally. The hooks and components it uses are described in Live data in dashboards. For writes, see Write parameter values from a dashboard.
Show one reading
Section titled “Show one reading”These two files form a complete dashboard that shows one live reading.
-
Declare the binding in
config.ts.parameterIdis the UUID of an existing parameter, andunitsits engineering unit, such as°C:import Type from "typebox";export const dashboardConfigType = Type.Object({parameterId: Type.Optional(Type.String({ format: "uuid" })),units: Type.Optional(Type.String()),},{ additionalProperties: false },); -
Read the value in
index.tsx:import { formatAppDateTime } from "@overvis/hmi-shared";import {parseDashboardConfiguration,type DashboardRootProps,} from "@overvis/hmi-shared/dashboard";import {DashboardConfigurationRequired,ParameterDiagnostics,ParameterValueDisplay,useParameterValue,useParameterValues,} from "@overvis/hmi-workspace-ui";import { useTranslation } from "@overvis/hmi-workspace-ui/i18n";import type { ReactElement } from "react";import { dashboardConfigType } from "./config.ts";export { dashboardConfigType } from "./config.ts";export const supportedLocales = ["en", "pl", "de", "uk", "ru"] as const;export default function ReadingDashboard(props: DashboardRootProps): ReactElement {const config = parseDashboardConfiguration(dashboardConfigType, props.configuration);const id = config.parameterId;const demand = useParameterValues({parameterIds: id == null ? [] : [id],intervalMs: 5_000,});const state = useParameterValue(id ?? "");const t = useTranslation();if (id == null) {return (<DashboardConfigurationRequiredworkspaceId={props.workspaceId}dashboardId={props.dashboardId}title="Reading"description="Choose the parameter this dashboard shows."missing={[{ path: "configuration", fields: ["parameterId"] }]}exampleConfiguration={{ parameterId: "<parameter-uuid>", units: "°C" }}/>);}const receivedAt =state.status === "value" ? formatAppDateTime(state.snapshot.receivedAt) : null;return (<main className="grid gap-3 p-4"><div className="flex items-baseline gap-2 text-2xl"><ParameterValueDisplay state={state} locale={props.locale} />{state.status === "value" ? <span>{config.units}</span> : null}</div>{state.status === "value" && receivedAt != null ? (<p className="text-sm text-muted-foreground">{state.freshness === "stale"? t("parameter_value_stale_since", { when: receivedAt }): receivedAt}</p>) : null}<ParameterDiagnosticsdiagnostics={demand.diagnostics}onRetry={demand.retry}workspaceId={props.workspaceId}dashboardId={props.dashboardId}/></main>);} -
Push the dashboard and set
parameterIdin its settings.
Until parameterId is set, the dashboard registers no demand, and DashboardConfigurationRequired
lists the missing key with an example configuration. It offers Open dashboard settings only to
members who can open Setup. ParameterDiagnostics shows permission failures and owns Retry, so the
dashboard needs no Retry button of its own. The example passes a defined callback to onRetry,
which is compatible with exactOptionalPropertyTypes.
Bind parameters in the configuration
Section titled “Bind parameters in the configuration”- Bind parameters through a strict TypeBox
dashboardConfigType, not through UUIDs in the source. The same source then works in another workspace after the configuration is changed. - Use named keys grouped by topic, such as
parameters.readings,parameters.thresholds, andparameters.commands. Use a generic list of UUIDs only when the UI itself is generic. - While a required binding is missing, render a setup state, such as
DashboardConfigurationRequired, and register no demand. - Take units from parameter metadata or from an explicit configuration key. Never infer a unit from a parameter name.
- Take
workspaceIdanddashboardIdfrom the props. Do not copy them into the configuration.
Read values in cohorts
Section titled “Read values in cohorts”- Call
useParameterValuesonce per cohort, not once per tile. Do not write your own polling effect or a second tRPC client. - Put quickly changing visible values in a fast cohort, and settings or identity values in a slow cohort. Pick each cadence by how fast the process changes; typical plant views use 1 to 5 seconds.
- Read each value with
useParameterValue(id)where it is shown. It adds no network demand. AdduseParameterValueHistoryoruseParameterValueActionsonly where a view needs samples or writes. - To combine the cohorts for
ParameterLiveControlsandParameterDiagnostics, pass their results tocombineParameterValuesDemands. - To pause reading, pass
enabled: false. Values already read stay on screen.
A static dashboard, or a one-time report-like page, calls no useParameterValues; the host’s
provider then stays inert.
Show loading, stale, and failed values
Section titled “Show loading, stale, and failed values”- Until a value or a structured failure arrives for a parameter, show a skeleton.
ParameterValueDisplaydoes this; in custom markup, testisParameterValuePending(state). While device availability is not confirmed, keep showing it as loading, not as missing or offline. - After a successful value, keep it visible during refreshes.
- When a later read fails, mark the value stale at once, with its unchanged received-at time.
parameterStatesStaleSince(states)gives the time for one “stale since” note. - Render the current diagnosis once, in
ParameterDiagnostics. Do not repeat a grouped failure beside every stale value. - Build your own error text from
code,reason, and the structuredparams. Never display or parse Englisherror.messageorparams.detail. - When a reading times out, tell the operator to check the device’s power, wiring, unit ID, serial settings, and response. Do not say that the device is offline.
Act only on current values
Section titled “Act only on current values”A value kept from an earlier read may no longer be on the device.
- Decide whether to offer a write, color a tile, or count an alarm only on a current value:
isCurrentParameterValue(state), or a reader with{ current: true }such asparameterValueNumber(state, { current: true }).
Read typed values for custom controls
Section titled “Read typed values for custom controls”For custom controls and SVG bindings, read typed values with parameterValueNumber,
parameterValueBoolean, parameterValueFlag, or parameterValueTime. Do not parse the displayed
text.
Show a trend from stored readings
Section titled “Show a trend from stored readings”- Load the closed buckets with
useStoredParameterHistory, using a window fromstoredHistoryWindowsor your own. Passenabled: falsewhile the trend is hidden. - To reach the current time, collect live values with
useParameterValueHistory, sized withliveTailPoints, and append them withwithLiveTail(points, live, cadenceMs). - Draw the points with
ParameterTrendChartorSparkline. Set the gap threshold to about twice the bucket length. - When
recordedis false, say that the parameter’s readings are not stored, instead of showing an empty chart.
Show the last stored reading
Section titled “Show the last stored reading”When a parameter has no live value yet, for example while its device answers intermittently, show the last reading the server stored.
- Query
readings.segmentsthroughtrpcwithsegmentCount: 1and a window that ends now. Take the point with the greatesttime, and keep that time with the value. Trend points fromuseStoredParameterHistoryare bucket averages, so they do not serve here. - Skip a reading older than the dashboard allows; the result can hold one from before
from. Show nothing when no reading is left. - Mark the value as last stored and show its time. It is not current: offer writes, color tiles, and count alarms only from live values.
Show the endpoint connection state
Section titled “Show the endpoint connection state”Subscribe to endpoint.watchStatus for connection indicators. Do not infer connectivity from
parameter failures.
Read other workspace data
Section titled “Read other workspace data”- Call other procedures through
trpcfrom@overvis/hmi-workspace-ui, such asparameter.listInventoryfor a wiring picker. - Do not poll catalog queries or subscribe to
workspace.watchChanges: the host refreshes setup queries, including the dashboard’s ownconfiguration, when the setup changes. - Do not call
dashboard.getto read the configuration. It is already in the props, and the workspace is available throughuseWorkspace().
Isolate a subsystem with its own provider
Section titled “Isolate a subsystem with its own provider”The host’s provider serves ordinary plant dashboards. When a subsystem needs its own demand or
lifecycle, mount a nested ParameterValuesProvider around it.
Call tRPC directly only when the coordinator cannot express the workflow. Keep the coordinator’s behavior then: progressive results, no overlapping reads, cancellation, a pause while the page is hidden, structured diagnoses, stale values kept, and batched writes.