From 52da393d0c32fb1699a3422e067508aaab1e07de Mon Sep 17 00:00:00 2001 From: sosokker Date: Mon, 13 May 2024 13:23:35 +0700 Subject: [PATCH] Add camera viewer page --- frontend/src/components/LoadingAnimation.tsx | 15 ++ frontend/src/pages/Camera.tsx | 136 ++++++++++++++++++- 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/LoadingAnimation.tsx diff --git a/frontend/src/components/LoadingAnimation.tsx b/frontend/src/components/LoadingAnimation.tsx new file mode 100644 index 0000000..a1402ae --- /dev/null +++ b/frontend/src/components/LoadingAnimation.tsx @@ -0,0 +1,15 @@ +const LoadingAnimation = () => { + return ( +
+
+ Loading... +
+
+ ); +}; + +export default LoadingAnimation; diff --git a/frontend/src/pages/Camera.tsx b/frontend/src/pages/Camera.tsx index b1e4715..093a795 100644 --- a/frontend/src/pages/Camera.tsx +++ b/frontend/src/pages/Camera.tsx @@ -1,13 +1,147 @@ +import React, { useEffect, useRef, useState } from 'react'; import Breadcrumb from '../components/Breadcrumbs/Breadcrumb'; import DefaultLayout from '../layout/DefaultLayout'; +import LoadingAnimation from '../components/LoadingAnimation'; const Camera = () => { + const webSocketRef = useRef(null); + const canvasRef = useRef(null); + const [connectionError, setConnectionError] = useState(false); + const [loading, setLoading] = useState(false); + const [cameras, setCameras] = useState< + { camera_id: number; link: string; status: boolean }[] + >([]); + const [selectedCamera, setSelectedCamera] = useState(null); + + useEffect(() => { + // Fetch cameras data from the API + const fetchCameras = async () => { + try { + const response = await fetch( + 'http://127.0.0.1:8000/api/v1/camera/list', + ); + const data = await response.json(); + setCameras(data); + } catch (error) { + console.error('Error fetching cameras:', error); + } + }; + + fetchCameras(); + }, []); + + const connectWebSocket = () => { + if (selectedCamera !== null) { + const selectedCameraData = cameras.find( + (camera) => camera.camera_id === selectedCamera, + ); + if (selectedCameraData && selectedCameraData.status) { + setLoading(true); + const websocketUrl = `ws://127.0.0.1:8000/api/v1/camera/ws/${selectedCamera}`; + webSocketRef.current = new WebSocket(websocketUrl); + + webSocketRef.current.onmessage = (event) => { + setLoading(false); + const blob = new Blob([event.data], { type: 'image/png' }); + const imageUrl = URL.createObjectURL(blob); + + const image = new Image(); + image.onload = () => { + if (canvasRef.current) { + const context = canvasRef.current.getContext('2d'); + if (context) { + context.drawImage( + image, + 0, + 0, + canvasRef.current.width, + canvasRef.current.height, + ); + } + } + }; + image.src = imageUrl; + }; + + webSocketRef.current.onopen = () => { + console.log('WebSocket connected'); + setConnectionError(false); + }; + + webSocketRef.current.onerror = (error) => { + console.error('WebSocket error:', error); + setConnectionError(true); + setLoading(false); + }; + + webSocketRef.current.onclose = () => { + console.log('WebSocket closed'); + setLoading(false); + }; + } + } + }; + + const handleCameraChange = (event: React.ChangeEvent) => { + const selectedValue = parseInt(event.target.value, 10); + setSelectedCamera(selectedValue); + }; + + const handleClearConnection = () => { + if (webSocketRef.current?.readyState === WebSocket.OPEN) { + webSocketRef.current.close(); + } + setSelectedCamera(null); + }; + return (
- Camera here +
+ +
+ + +
+
+ {selectedCamera !== null && !loading && ( + + )} + {loading && }
);