Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intrusion detection #18

Merged
merged 5 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Backend/.env-openvidu
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
OPENVIDU_SECRET=MY_SECRET
OPENVIDU_WEBHOOK=true
OPENVIDU_WEBHOOK_ENDPOINT=https://localhost:8080/media-server
1 change: 0 additions & 1 deletion Backend/src/app/mediaServer/mediaServer.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class MediaServerController {
@Header('Content-Type', 'application/json')
@Post('/media-server')
async getMediaServerEvents(@Body() event: any) {
console.log(event);
this.cameraStreamGateway.broadcastEvent(event);
return { message: 'OK' };
}
Expand Down
8 changes: 4 additions & 4 deletions Backend/src/cameraStream/cameraStream.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,16 @@ export class CameraStreamGateway implements OnGatewayConnection {

async afterInit() {
try {
const session = await this.openvidu.instance.createSession({});
const session = await this.openvidu.instance.createSession();
this.sessionId = session.sessionId;

const nvr = await this.database.getNVRData();

nvr.channels.forEach((id: number) => {
const connectionProperties: ConnectionProperties = {
type: ConnectionType.IPCAM,
rtspUri: `${nvr.ip}/ch${id}_0.264`,
adaptativeBitrate: true,
onlyPlayWithSubscribers: false,
onlyPlayWithSubscribers: true,
networkCache: 1000,
data: id.toString(),
};
Expand All @@ -77,7 +77,7 @@ export class CameraStreamGateway implements OnGatewayConnection {
.catch((error) => console.error(error));
});
} catch (error) {
console.error(`OpenVidu initialization Failed...`);
console.error(error);
}
}

Expand Down
4 changes: 2 additions & 2 deletions Backend/src/database/database.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,10 @@ export class DatabaseService {
const array = await this.getRawDataArray('General', {
name: 'NVR',
});

return {
ip: process.env.NVR_IP_ADDRESS,
channels: array[0].channels,
channels: cameraIds,
};
}
}
13 changes: 6 additions & 7 deletions Frontend/src/api/recent-activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@ import { Activity } from "@/types";
import { axiosClient } from "./axios-client";
import { endpoints } from "./endpoints";

type RecentActivitiesResponseDTO = {
data: Activity[];
};
type RecentActivitiesResponseDTO = Activity[];

type RecentActivitiesCountResponseDTO = {
_id: string;
count: number;
}[];

type RecentActivityImageResponseDTO = {
data: any;
};
type RecentActivityImageResponseDTO = any;

export const getRecentActivities = (top: number, skip: number) => {
return () =>
Expand Down Expand Up @@ -50,5 +46,8 @@ export const getActivityImage = (id: string, timestamp: string) => {
`${id}/${timestamp}`,
{}
)
.then((result) => result.data);
.then((result) => {
const blob = new Blob([result.data], { type: 'image/jpeg' });
return {imageUrl:URL.createObjectURL(blob)}
});
};
6 changes: 3 additions & 3 deletions Frontend/src/components/button/view-screenshot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const ViewScreenshotButton: React.FC<PropsType> = ({
data: imageData,
refetch: fetchImage,
} = useQuery(
["recentActivitiesCount", cameraId],
["recentActivitiesImage", cameraId, timestamp],
getActivityImage(cameraId, timestamp),
{ enabled: false }
);
Expand All @@ -39,8 +39,8 @@ export const ViewScreenshotButton: React.FC<PropsType> = ({
if (imageData) {
openModal({
title: timestamp,
modalContent: imageData.data,
isLoading: true,
modalContent: imageData,
isLoading: false,
});
}
}, [imageData]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ const VideoPlayer = ({
}) => {
const [fullScreen, setFullScreen] = useState(false);
const [videoControlHidden, setvideoControlHidden] = useState(false);
const [loading, setLoading] = useState(true);
const intervalRef: any = useRef(null);

/* event handlers */
const onScreenSizeToggle = () => {
const elem = document.documentElement;
Expand Down Expand Up @@ -60,7 +59,6 @@ const VideoPlayer = ({

return (
<div className="w-full min-h-[250px] video-container relative">
{/* <Spin className="absolute top-1/2 left-1/2" /> */}
<video
ref={(el) => {
videoRef.current = { ...videoRef.current, [camera.id]: el };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const VideoRecordingScreen: FC<PropsType> = ({ camera, videoRef }) => {
{camera.isActive && (
<VideoPlayer camera={camera} videoRef={videoRef} />
)}

{!camera.isActive && (
<div className="bg-black min-h-[250px] relative">
<span className="absolute animate-pulse top-1/2 left-1/2 bg-red-500 -translate-x-1/2 -translate-y-1/2 rounded-full w-8 h-8"></span>
Expand Down
4 changes: 3 additions & 1 deletion Frontend/src/containers/layout-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ export const LayoutContainer = ({

useEffect(() => {
if (camerasFetchedData && session) {
setCameras(camerasFetchedData);
setCameras(
camerasFetchedData.map((item) => ({ ...item, isActive: true }))
);
}
}, [camerasFetchedData, session]);

Expand Down
5 changes: 2 additions & 3 deletions Frontend/src/containers/modal-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ export const ModalContainer = () => {
const onCancel = () => {
closeModal();
}

console
return (
<>
<Modal title={title} open={isModalOpen} onOk={onCancel} onCancel={onCancel} afterClose={onCancel}>
{modalContent}
{isLoading &&
<Spin/>
}
{!isLoading &&
<img src={modalContent} alt="Ima"/>
<img src={modalContent} alt="Image detection"/>
}
</Modal>
</>
Expand Down
13 changes: 4 additions & 9 deletions Frontend/src/containers/recent-activities-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,10 @@ export const RecentActivitiesContainer: FC<PropsType> = () => {
<>
<Table
columns={recentActivitiesColumns}
data={
/* recentActivitiesFetchedData */ recentActivitiesData?.map(
(event) => ({
...event,
cameraName: cameras.find((item) => item.id == event.cameraId)
?.name,
})
)
}
data={recentActivitiesFetchedData?.map((event) => ({
...event,
cameraName: cameras.find((item) => item.id == event.cameraId)?.name,
}))}
pagination={{
total: recentActivitiesCountFetchedData,
onChange: setPageNumber,
Expand Down
53 changes: 34 additions & 19 deletions Frontend/src/containers/video-stream-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import type { FC } from "react";
import { Tooltip } from "antd";
import { VideoRecordingScreen } from "@/components";
import { useCameraSlice, useSessionSlice } from "@/hooks";
import { cameras as camerasData } from "@/data";
import { useCameraSlice } from "@/hooks";
import { FullscreenOutlined, FullscreenExitOutlined } from "@ant-design/icons";
import React, { useEffect, useRef, useState } from "react";
import { io } from "socket.io-client";
Expand All @@ -21,8 +20,12 @@ const webSocketURL = process.env.NEXT_PUBLIC_BACKEND_URL
export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
const [subscribers, setSubscribers] = useState<any[]>([]);
/* hooks */
const { cameras, isFullScreenGrid, toggleIsFullScreenGrid, setCameras } =
useCameraSlice();
const {
cameras,
isFullScreenGrid,
toggleIsFullScreenGrid,
updateCameraStatus,
} = useCameraSlice();
const videoRef: any = useRef(null);

/* event handlers */
Expand All @@ -31,13 +34,11 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
if (elem.requestFullscreen && !isFullScreenGrid) {
elem.requestFullscreen();
toggleIsFullScreenGrid(true);
console.log("Setting true");
}

if (document.exitFullscreen && isFullScreenGrid) {
document.exitFullscreen();
toggleIsFullScreenGrid(false);
console.log("Setting false");
}
};

Expand Down Expand Up @@ -94,11 +95,6 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
);
});

// On every Stream destroyed...
session.on("streamPropertyChanged", (event) => {
console.log(event);
});

// On every asynchronous exception...
session.on("exception", (exception) => {
console.error(exception);
Expand Down Expand Up @@ -141,8 +137,6 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
let publisher = await openVidu.initPublisherAsync(undefined, {
audioSource: false, // The source of audio. If undefined default microphone
videoSource: false, // The source of video. If undefined default webcam
publishAudio: false, // Whether you want to start publishing with your audio unmuted or not
publishVideo: false, // Whether you want to start publishing with your video enabled or not
});

// -Publish your stream ---
Expand Down Expand Up @@ -172,12 +166,33 @@ export const VideoStreamContainer: FC<PropsType> = ({ sizePerScreen = 9 }) => {
}, []);

useEffect(() => {
subscribers.forEach((subscriber) =>
subscriber.addVideoElement(
videoRef.current?.[subscriber?.stream?.connection?.data]
)
);
}, [subscribers]);
if (cameras.length === 8) {
let toBeInActive = [...cameras];
subscribers.forEach((subscriber, index) => {
try {
subscriber.addVideoElement(
videoRef.current?.[subscriber?.stream?.connection?.data]
);
console.log(toBeInActive);

toBeInActive = toBeInActive.filter(
(item) => item.id != subscriber?.stream?.connection?.data
);
} catch (err) {
console.log(err);
}
console.log(toBeInActive);
if (index === subscribers.length - 1) {
toBeInActive.forEach((item) =>
updateCameraStatus({
id: item.id,
status: false,
})
);
}
});
}
}, [subscribers, cameras.length > 0]);

return (
<>
Expand Down
7 changes: 7 additions & 0 deletions Frontend/src/hooks/use-camera-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
updateCamera,
toggleIsFullScreenGrid,
setCameras,
updateCameraStatus,
} from "@/store";

export const useCameraSlice = () => {
Expand All @@ -31,6 +32,11 @@ export const useCameraSlice = () => {
const toggleIsFullScreenGridState = (value: boolean) => {
dispatch(toggleIsFullScreenGrid(value));
};
updateCameraStatus;

const updateCameraStatusState = (update: { id: string; status: boolean }) => {
dispatch(updateCameraStatus(update));
};

return {
cameras: cameras,
Expand All @@ -40,5 +46,6 @@ export const useCameraSlice = () => {
setCameras: setCamerasState,
updateCamera: updateCameraState,
toggleIsFullScreenGrid: toggleIsFullScreenGridState,
updateCameraStatus: updateCameraStatusState,
};
};
1 change: 1 addition & 0 deletions Frontend/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {
setCameras,
updateCamera,
toggleIsFullScreenGrid,
updateCameraStatus
} from "./slices/camera-slice";
export {
selectNotification,
Expand Down
19 changes: 17 additions & 2 deletions Frontend/src/store/slices/camera-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ export const cameraSlice = createSlice({
return item;
});
},
updateCameraStatus: (
state: CameraStateType,
action: PayloadAction<{ id: string; status: boolean }>
) => {
state.cameras = state.cameras.map((item) => {
if (item.id === action.payload.id) {
return { ...item, isActive: action.payload.status };
}
return item;
});
},
toggleIsFullScreenGrid: (
state: CameraStateType,
action: PayloadAction<boolean>
Expand All @@ -46,8 +57,12 @@ export const cameraSlice = createSlice({
},
});

export const { updateCamera, toggleIsFullScreenGrid, setCameras } =
cameraSlice.actions;
export const {
updateCamera,
toggleIsFullScreenGrid,
setCameras,
updateCameraStatus,
} = cameraSlice.actions;

// Other code such as selectors can use the imported `RootState` type
export const selectCameras = (state: RootState) => state.camera.cameras;
Expand Down
4 changes: 2 additions & 2 deletions Frontend/src/store/slices/modal-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ type ModalStateType = {
title: string;
isModalOpen: boolean;
isLoading: boolean;
modalContent: string;
modalContent: any;
};
};

type OpenModalPayloadType = {
title: string;
modalContent: string;
modalContent: any;
isLoading: boolean;
};

Expand Down
Loading