2025-08-27 22:36:27 +07:00
|
|
|
import { useEffect, useRef } from "react";
|
|
|
|
|
import { useQueryClient } from "@tanstack/react-query";
|
|
|
|
|
import { API_ENDPOINTS } from "@/config/api";
|
|
|
|
|
|
2025-08-14 12:16:32 +07:00
|
|
|
interface DeviceEventData {
|
|
|
|
|
Message: string;
|
|
|
|
|
DeviceId: string;
|
|
|
|
|
Room: string;
|
|
|
|
|
Timestamp?: string;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-27 22:36:27 +07:00
|
|
|
export function useDeviceEvents(roomName?: string) {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
const reconnectTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
|
2025-08-14 12:16:32 +07:00
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-08-27 22:36:27 +07:00
|
|
|
let onlineES: EventSource | null = null;
|
|
|
|
|
let offlineES: EventSource | null = null;
|
2025-08-14 12:16:32 +07:00
|
|
|
|
2025-08-27 22:36:27 +07:00
|
|
|
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
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-08-14 12:16:32 +07:00
|
|
|
|
2025-08-27 22:36:27 +07:00
|
|
|
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;
|
2025-08-14 12:16:32 +07:00
|
|
|
};
|
|
|
|
|
|
2025-08-27 22:36:27 +07:00
|
|
|
const cleanup = () => {
|
|
|
|
|
if (onlineES) onlineES.close();
|
|
|
|
|
if (offlineES) offlineES.close();
|
|
|
|
|
if (reconnectTimeout.current) {
|
|
|
|
|
clearTimeout(reconnectTimeout.current);
|
|
|
|
|
reconnectTimeout.current = null;
|
|
|
|
|
}
|
2025-08-14 12:16:32 +07:00
|
|
|
};
|
2025-08-27 22:36:27 +07:00
|
|
|
|
|
|
|
|
connect();
|
|
|
|
|
return cleanup;
|
|
|
|
|
}, [roomName, queryClient]);
|
2025-08-14 12:16:32 +07:00
|
|
|
}
|