diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index a126237..db9914e 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -172,15 +172,25 @@ export default function DevicePage() { // Streams all component changes for this device. // When the backend receives a new reading and updates a component, // this fires and updates the component in state without a page refresh. - useWebSocket<{ key: string; component: Component }>({ + useWebSocket<{ key: string; component: Component } | null>({ path: `/live/devices/${deviceID}/components`, parse: (e) => { - const raw = JSON.parse(e.data); - const comp = Component.any(raw); - return { key: comp.key(), component: comp }; + try { + const raw = JSON.parse(e.data); + const comp = Component.any(raw); + if (!comp?.settings) { + console.warn("[ws] received component without settings:", raw); + return null; + } + return { key: comp.key(), component: comp }; + } catch (err) { + console.warn("[ws] failed to parse component:", err); + return null; + } }, - onMessage: ({ key, component }) => { - // Functional update so we always work with the latest state + onMessage: (data) => { + if (!data) return; + const { key, component } = data; setComponents((prev) => { const updated = new Map(prev); updated.set(key, component); @@ -193,10 +203,24 @@ export default function DevicePage() { // --- Real-time device updates (optional) --- // Updates device-level info (name, status, lastActive, etc.) - useWebSocket({ + useWebSocket({ path: `/live/devices/${deviceID}`, - parse: (e) => Device.any(JSON.parse(e.data)), + 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); }, token,