Skip to content

Commit

Permalink
Use camera status to get state of camera config (#12787)
Browse files Browse the repository at this point in the history
* Use camera status to get state of camera config

* Fix spelling
  • Loading branch information
NickM-27 authored Aug 6, 2024
1 parent 2e73b13 commit 069c50a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 19 deletions.
15 changes: 14 additions & 1 deletion frigate/comms/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,20 @@ def _receive(self, topic: str, payload: str) -> Optional[Any]:
elif topic == UPDATE_CAMERA_ACTIVITY:
self.camera_activity = payload
elif topic == "onConnect":
self.publish("camera_activity", json.dumps(self.camera_activity))
camera_status = self.camera_activity.copy()

for camera in camera_status.keys():
camera_status[camera]["config"] = {
"detect": self.config.cameras[camera].detect.enabled,
"snapshots": self.config.cameras[camera].snapshots.enabled,
"record": self.config.cameras[camera].record.enabled,
"audio": self.config.cameras[camera].audio.enabled,
"autotracking": self.config.cameras[
camera
].onvif.autotracking.enabled,
}

self.publish("camera_activity", json.dumps(camera_status))
else:
self.publish(topic, payload, retain=False)

Expand Down
44 changes: 26 additions & 18 deletions web/src/api/ws.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { baseUrl } from "./baseUrl";
import { useCallback, useEffect, useState } from "react";
import useWebSocket, { ReadyState } from "react-use-websocket";
import { FrigateConfig } from "@/types/frigateConfig";
import {
FrigateCameraState,
FrigateEvent,
FrigateReview,
ToggleableSetting,
} from "@/types/ws";
import { FrigateStats } from "@/types/stats";
import useSWR from "swr";
import { createContainer } from "react-tracked";
import useDeepMemo from "@/hooks/use-deep-memo";

Expand All @@ -26,40 +24,50 @@ type WsState = {
type useValueReturn = [WsState, (update: Update) => void];

function useValue(): useValueReturn {
// basic config
const { data: config } = useSWR<FrigateConfig>("config", {
revalidateOnFocus: false,
});
const wsUrl = `${baseUrl.replace(/^http/, "ws")}ws`;

// main state

const [hasCameraState, setHasCameraState] = useState(false);
const [wsState, setWsState] = useState<WsState>({});

useEffect(() => {
if (!config) {
if (hasCameraState) {
return;
}

const activityValue: string = wsState["camera_activity"] as string;

if (!activityValue) {
return;
}

const cameraActivity: { [key: string]: object } = JSON.parse(activityValue);

if (!cameraActivity) {
return;
}

const cameraStates: WsState = {};

Object.keys(config.cameras).forEach((camera) => {
const { name, record, detect, snapshots, audio, onvif } =
config.cameras[camera];
cameraStates[`${name}/recordings/state`] = record.enabled ? "ON" : "OFF";
cameraStates[`${name}/detect/state`] = detect.enabled ? "ON" : "OFF";
cameraStates[`${name}/snapshots/state`] = snapshots.enabled
? "ON"
: "OFF";
cameraStates[`${name}/audio/state`] = audio.enabled ? "ON" : "OFF";
cameraStates[`${name}/ptz_autotracker/state`] = onvif.autotracking.enabled
Object.entries(cameraActivity).forEach(([name, state]) => {
const { record, detect, snapshots, audio, autotracking } =
// @ts-expect-error we know this is correct
state["config"];
cameraStates[`${name}/recordings/state`] = record ? "ON" : "OFF";
cameraStates[`${name}/detect/state`] = detect ? "ON" : "OFF";
cameraStates[`${name}/snapshots/state`] = snapshots ? "ON" : "OFF";
cameraStates[`${name}/audio/state`] = audio ? "ON" : "OFF";
cameraStates[`${name}/ptz_autotracker/state`] = autotracking
? "ON"
: "OFF";
});

setWsState({ ...wsState, ...cameraStates });
setHasCameraState(true);
// we only want this to run initially when the config is loaded
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [config]);
}, [wsState]);

// ws handler
const { sendJsonMessage, readyState } = useWebSocket(wsUrl, {
Expand Down

0 comments on commit 069c50a

Please sign in to comment.