TTMT.ManageWebGUI/src/hooks/useDeviceEvents.ts

110 lines
3.2 KiB
TypeScript

import { useEffect, useRef } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { API_ENDPOINTS } from "@/config/api";
interface DeviceEventData {
Message: string;
DeviceId: string;
Room: string;
Timestamp?: string;
}
export function useDeviceEvents(roomName?: string) {
const queryClient = useQueryClient();
const reconnectTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
let onlineES: EventSource | null = null;
let offlineES: EventSource | null = null;
const connect = () => {
onlineES = new EventSource(API_ENDPOINTS.SSE_EVENTS.DEVICE_ONLINE);
offlineES = new EventSource(API_ENDPOINTS.SSE_EVENTS.DEVICE_OFFLINE);
onlineES.addEventListener("online", (event) => {
try {
const data: DeviceEventData = JSON.parse(event.data);
if (roomName && data.Room === roomName) {
queryClient.setQueryData(
["devices", roomName],
(oldDevices: any[] = []) =>
oldDevices.map((d) =>
d.macAddress === data.DeviceId
? { ...d, isOffline: false }
: d
)
);
}
queryClient.setQueryData(["rooms"], (oldRooms: any[] = []) =>
oldRooms.map((room) =>
room.name === data.Room
? {
...room,
numberOfOfflineDevices:
Math.max(0, room.numberOfOfflineDevices - 1),
}
: room
)
);
} catch (err) {
console.error("Error parsing online event:", err);
}
});
offlineES.addEventListener("offline", (event) => {
try {
const data: DeviceEventData = JSON.parse(event.data);
if (roomName && data.Room === roomName) {
queryClient.setQueryData(
["devices", roomName],
(oldDevices: any[] = []) =>
oldDevices.map((d) =>
d.macAddress === data.DeviceId
? { ...d, isOffline: true }
: d
)
);
}
queryClient.setQueryData(["rooms"], (oldRooms: any[] = []) =>
oldRooms.map((room) =>
room.name === data.Room
? {
...room,
numberOfOfflineDevices: room.numberOfOfflineDevices + 1,
}
: room
)
);
} catch (err) {
console.error("Error parsing offline event:", err);
}
});
const onError = (err: any) => {
console.error("SSE connection error:", err);
cleanup();
reconnectTimeout.current = setTimeout(connect, 5000);
};
onlineES.onerror = onError;
offlineES.onerror = onError;
};
const cleanup = () => {
if (onlineES) onlineES.close();
if (offlineES) offlineES.close();
if (reconnectTimeout.current) {
clearTimeout(reconnectTimeout.current);
reconnectTimeout.current = null;
}
};
connect();
return cleanup;
}, [roomName, queryClient]);
}