switched to status websocket instead of the dead full device websocket

This commit is contained in:
Carter 2026-03-23 12:18:51 -06:00
parent d6e3fe7a16
commit a288c9503a

View file

@ -3,7 +3,8 @@ import Grid from '@mui/material/Grid2';
import { Component, Device, Interaction, User } from "models";
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
import { useDeviceAPI, useGlobalState, useSnackbar } from "providers";
import { useEffect, useMemo, useState } from "react";
import { useDeviceStatusStreams } from "hooks/useDeviceStatusStreams";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useLocation, useParams } from "react-router-dom";
import PageContainer from "./PageContainer";
import { useHTTP, useMobile } from "hooks";
@ -23,6 +24,25 @@ import DeviceWizard from "device/DeviceWizard";
import DeviceScannedComponents from "device/autoDetect/DeviceScannedComponents";
import { useWebSocket } from "hooks/useWebSocket";
type TimestampedReading = { timestamp?: string };
function getTimestampMillis(timestamp?: string): number | undefined {
if (!timestamp) return undefined;
const parsed = Date.parse(timestamp);
return Number.isNaN(parsed) ? undefined : parsed;
}
function pickNewestReading<T extends TimestampedReading>(
current: T | null | undefined,
incoming: T | null | undefined
): T | null | undefined {
const currentTs = getTimestampMillis(current?.timestamp);
const incomingTs = getTimestampMillis(incoming?.timestamp);
if (incomingTs === undefined) return current ?? incoming;
if (currentTs === undefined) return incoming ?? current;
return incomingTs >= currentTs ? incoming : current;
}
export interface DevicePageData {
device: Device;
components: Component[];
@ -76,6 +96,55 @@ export default function DevicePage() {
? as
: undefined;
const liveStatusDeviceIds = useMemo(
() => (deviceID ? [deviceID] : []),
[deviceID]
);
const handleLiveDeviceStatus = useCallback(
(streamDeviceId: string, status: pond.DeviceStatus) => {
setDevice((prev) => {
if (prev.id().toString() !== streamDeviceId) return prev;
const updated = Device.clone(prev);
const incomingStatus = pond.DeviceStatus.fromObject(status);
const currentStatus = prev.status ?? pond.DeviceStatus.create();
incomingStatus.plenum = pickNewestReading(currentStatus.plenum, incomingStatus.plenum);
incomingStatus.sen5x = pickNewestReading(currentStatus.sen5x, incomingStatus.sen5x);
incomingStatus.co = pickNewestReading(currentStatus.co, incomingStatus.co);
incomingStatus.co2 = pickNewestReading(currentStatus.co2, incomingStatus.co2);
incomingStatus.no2 = pickNewestReading(currentStatus.no2, incomingStatus.no2);
incomingStatus.o2 = pickNewestReading(currentStatus.o2, incomingStatus.o2);
incomingStatus.lel = pickNewestReading(currentStatus.lel, incomingStatus.lel);
incomingStatus.h2s = pickNewestReading(currentStatus.h2s, incomingStatus.h2s);
const currentLastActive = getTimestampMillis(currentStatus.lastActive);
const incomingLastActive = getTimestampMillis(incomingStatus.lastActive);
if (
currentLastActive !== undefined &&
incomingLastActive !== undefined &&
incomingLastActive < currentLastActive
) {
incomingStatus.lastActive = currentStatus.lastActive;
}
updated.status = incomingStatus;
return updated;
});
},
[]
);
useDeviceStatusStreams({
deviceIds: liveStatusDeviceIds,
onStatusUpdate: handleLiveDeviceStatus,
token,
keys: liveContextKeys,
types: liveContextTypes,
as: liveAs,
enabled: Boolean(deviceID && token),
});
const loadDevice = () => {
if (loading) return
if (state?.devicePageData) {
@ -212,35 +281,6 @@ export default function DevicePage() {
enabled: !!deviceID,
});
// --- Real-time device updates (optional) ---
// Updates device-level info (name, status, lastActive, etc.)
useWebSocket<Device | null>({
path: `/v1/live/devices/${deviceID}`,
parse: (e) => {
try {
const raw = JSON.parse(e.data);
const dev = Device.any(raw);
if (!dev?.settings) {
console.warn("[ws] received device without settings:", raw);
return null;
}
return dev;
} catch (err) {
console.warn("[ws] failed to parse device:", err);
return null;
}
},
onMessage: (updatedDevice) => {
if (!updatedDevice) return;
setDevice(updatedDevice);
},
keys: liveContextKeys,
types: liveContextTypes,
as: liveAs,
token,
enabled: !!deviceID,
});
const loadPortScan = () => {
deviceAPI.listFoundComponents(parseInt(deviceID))
.then(resp => {