M5-T07: add latest-reading cards and Recharts trend charts; readings return most-recent rows
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
* ['modbus-devices'] — device list
|
||||
* ['modbus-device', uuid] — single device
|
||||
* ['modbus-profiles'] — profile list (rarely changes)
|
||||
* ['modbus-latest', uuid] — latest reading per device
|
||||
* ['modbus-metrics', uuid] — profile metric metadata per device
|
||||
* ['modbus-readings', uuid, params] — time-range readings per device
|
||||
*
|
||||
* On success, mutations invalidate the device list so the UI refreshes.
|
||||
*/
|
||||
@@ -25,6 +28,22 @@ export type ModbusDeviceCreate = components['schemas']['ModbusDeviceCreate']
|
||||
export type ModbusDeviceUpdate = components['schemas']['ModbusDeviceUpdate']
|
||||
export type ProfileSummary = components['schemas']['ProfileSummary']
|
||||
export type ModbusTestReadResponse = components['schemas']['ModbusTestReadResponse']
|
||||
export type ModbusLatestResponse = components['schemas']['ModbusLatestResponse']
|
||||
export type ModbusMetricsResponse = components['schemas']['ModbusMetricsResponse']
|
||||
export type MetricInfo = components['schemas']['MetricInfo']
|
||||
export type ModbusReadingResponse = components['schemas']['ModbusReadingResponse']
|
||||
export type ModbusReadingsResponse = components['schemas']['ModbusReadingsResponse']
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Reading query params
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ReadingsQueryParams {
|
||||
start?: string | null
|
||||
end?: string | null
|
||||
/** Capped server-side; default max is 1000 to avoid pulling full history. */
|
||||
limit?: number
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Query: list all devices
|
||||
@@ -112,3 +131,70 @@ export function useTestReadDevice() {
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Query: latest reading for a device
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function useLatestReading(uuid: string) {
|
||||
return useQuery({
|
||||
queryKey: ['modbus-latest', uuid],
|
||||
queryFn: async () => {
|
||||
const res = await apiClient.GET('/api/modbus/devices/{uuid}/latest', {
|
||||
params: { path: { uuid } },
|
||||
})
|
||||
return res.data
|
||||
},
|
||||
// Refresh every 10 s to show up-to-date readings.
|
||||
refetchInterval: 10_000,
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Query: profile metric metadata for a device (label/unit per key)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function useMetrics(uuid: string) {
|
||||
return useQuery({
|
||||
queryKey: ['modbus-metrics', uuid],
|
||||
queryFn: async () => {
|
||||
const res = await apiClient.GET('/api/modbus/devices/{uuid}/metrics', {
|
||||
params: { path: { uuid } },
|
||||
})
|
||||
return res.data
|
||||
},
|
||||
// Metrics are static (tied to profile version); 5 min stale time.
|
||||
staleTime: 5 * 60 * 1000,
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Query: time-range readings for a device (window + limit — never full-table)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Hard upper-bound on readings fetched; prevents accidental full-table pulls. */
|
||||
const READINGS_MAX_LIMIT = 1000
|
||||
|
||||
export function useReadings(uuid: string, params: ReadingsQueryParams) {
|
||||
const { start, end, limit } = params
|
||||
const effectiveLimit = Math.min(limit ?? READINGS_MAX_LIMIT, READINGS_MAX_LIMIT)
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['modbus-readings', uuid, { start, end, limit: effectiveLimit }],
|
||||
queryFn: async () => {
|
||||
const res = await apiClient.GET('/api/modbus/devices/{uuid}/readings', {
|
||||
params: {
|
||||
path: { uuid },
|
||||
query: {
|
||||
...(start ? { start } : {}),
|
||||
...(end ? { end } : {}),
|
||||
limit: effectiveLimit,
|
||||
},
|
||||
},
|
||||
})
|
||||
return res.data
|
||||
},
|
||||
// Enabled only when we have valid uuid; start/end may be null (full window).
|
||||
enabled: !!uuid,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user