diff --git a/typescript/frontend-marios2/src/contexts/WebSocketContextProvider.tsx b/typescript/frontend-marios2/src/contexts/WebSocketContextProvider.tsx new file mode 100644 index 000000000..0c3998c96 --- /dev/null +++ b/typescript/frontend-marios2/src/contexts/WebSocketContextProvider.tsx @@ -0,0 +1,137 @@ +import {createContext, ReactNode, useEffect, useState} from 'react'; +import {I_Installation} from '../interfaces/InstallationTypes'; + +// Define the shape of the context +interface WebSocketContextProviderProps { + socket: WebSocket; + openSocket: (installations: I_Installation[]) => void; + closeSocket: () => void; + getStatus: (installationId: number) => number; +} + +// Create the context. +export const WebSocketContext = createContext< + WebSocketContextProviderProps | undefined +>(undefined); + +const WebSocketContextProvider = ({ children }: { children: ReactNode }) => { + const [socket, setSocket] = useState(null); + const [installations, setInstallations] = useState(null); + const [installationStatus, setInstallationStatus] = useState< + Record + >({}); + const BUFFER_LENGTH = 5; + + useEffect(() => { + if (installations) { + const tokenString = localStorage.getItem('token'); + const token = tokenString !== null ? tokenString : ''; + + //const urlWithToken = `ws://localhost:7087/api/CreateWebSocket?authToken=${token}`; + const urlWithToken = `wss://monitor.innov.energy/api/CreateWebSocket?authToken=${token}`; + //const socket = new WebSocket('wss://monitor.innov.energy/websocket'); + + const socket = new WebSocket(urlWithToken); + // Connection opened + socket.addEventListener('open', (event) => { + socket.send( + JSON.stringify(installations.map((installation) => installation.id)) + ); + }); + + // Periodically send ping messages to keep the connection alive + const pingInterval = setInterval(() => { + if (socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify([-1])); + } + }, 10000); // Send a ping every 5 seconds + + // Listen for messages + socket.addEventListener('message', (event) => { + const message = JSON.parse(event.data); // Parse the JSON data + + if (message.id != -1) { + const installation_id = message.id; + const status = message.status; + + //console.log('Message from server ', installation_id, status); + + setInstallationStatus((prevStatus) => { + // Create a new object by spreading the previous state + const newStatus = { ...prevStatus }; + + if (!newStatus.hasOwnProperty(installation_id)) { + newStatus[installation_id] = []; + } + newStatus[installation_id].unshift(status); + newStatus[installation_id] = newStatus[installation_id].slice( + 0, + BUFFER_LENGTH + ); + + return newStatus; + }); + } + }); + setSocket(socket); + } + }, [installations]); + + const openSocket = (installations: I_Installation[]) => { + setInstallations(installations); + }; + + const closeSocket = () => { + socket.close(); + }; + + const getStatus = (installationId: number) => { + let status; + if (!installationStatus.hasOwnProperty(installationId)) { + status = -2; + } else { + let i = 0; + //If at least one status value shows an error, then show error + for (i; i < installationStatus[installationId].length; i++) { + if (installationStatus[installationId][i] === 2) { + status = 2; + return status; + } + if (installationStatus[installationId][i] === 1) { + status = 1; + return status; + } + } + + if (installationStatus[installationId][0] == -1) { + let i = 0; + for (i; i < installationStatus[installationId].length; i++) { + if (installationStatus[installationId][i] != -1) { + break; + } + } + if (i === installationStatus[installationId].length) { + status = -1; + } + } else { + status = installationStatus[installationId][0]; + } + } + return status; + }; + + return ( + + {children} + + ); +}; + +export default WebSocketContextProvider;