Disabled cameras fixing (#17273)

* Fix case where objects are returned as null

* Fix enabled status not being persisted

* Use config as source of truth when refreshed

* Ensure camera always have config object updated

* Cleanup typing
This commit is contained in:
Nicolas Mowen 2025-03-20 10:20:44 -06:00 committed by GitHub
parent d84fd324b2
commit d4d5c4aac8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 36 additions and 19 deletions

View File

@ -306,7 +306,6 @@ class CameraState:
# TODO: can i switch to looking this up and only changing when an event ends?
# maintain best objects
camera_activity: dict[str, list[any]] = {
"enabled": True,
"motion": len(motion_boxes) > 0,
"objects": [],
}

View File

@ -164,8 +164,12 @@ class Dispatcher:
def handle_on_connect():
camera_status = self.camera_activity.last_camera_activity.copy()
cameras_with_status = camera_status.keys()
for camera in self.config.cameras.keys():
if camera not in cameras_with_status:
camera_status[camera] = {}
for camera in camera_status.keys():
camera_status[camera]["config"] = {
"detect": self.config.cameras[camera].detect.enabled,
"enabled": self.config.cameras[camera].enabled,

View File

@ -113,8 +113,10 @@ def capture_frames(
def get_enabled_state():
"""Fetch the latest enabled state from ZMQ."""
_, config_data = config_subscriber.check_for_update()
if config_data:
return config_data.enabled
config.enabled = config_data.enabled
return config.enabled
while not stop_event.is_set():

View File

@ -44,7 +44,8 @@ function useValue(): useValueReturn {
return;
}
const cameraActivity: { [key: string]: object } = JSON.parse(activityValue);
const cameraActivity: { [key: string]: FrigateCameraState } =
JSON.parse(activityValue);
if (Object.keys(cameraActivity).length === 0) {
return;
@ -64,9 +65,7 @@ function useValue(): useValueReturn {
autotracking,
alerts,
detections,
} =
// @ts-expect-error we know this is correct
state["config"];
} = state["config"];
cameraStates[`${name}/recordings/state`] = record ? "ON" : "OFF";
cameraStates[`${name}/enabled/state`] = enabled ? "ON" : "OFF";
cameraStates[`${name}/detect/state`] = detect ? "ON" : "OFF";
@ -174,7 +173,7 @@ export function useEnabledState(camera: string): {
value: { payload },
send,
} = useWs(`${camera}/enabled/state`, `${camera}/enabled/set`);
return { payload: (payload ?? "ON") as ToggleableSetting, send };
return { payload: payload as ToggleableSetting, send };
}
export function useDetectState(camera: string): {

View File

@ -385,7 +385,10 @@ export default function LivePlayer({
<div
className={cn(
"absolute inset-0 w-full",
showStillWithoutActivity && !liveReady && !isReEnabling
showStillWithoutActivity &&
!liveReady &&
!isReEnabling &&
cameraEnabled
? "visible"
: "invisible",
)}

View File

@ -37,7 +37,7 @@ export function useCameraActivity(
return getAttributeLabels(config);
}, [config]);
const [objects, setObjects] = useState<ObjectType[]>([]);
const [objects, setObjects] = useState<ObjectType[] | undefined>([]);
// init camera activity
@ -54,7 +54,7 @@ export function useCameraActivity(
// handle camera activity
const hasActiveObjects = useMemo(
() => objects?.filter((obj) => !obj?.stationary)?.length > 0,
() => (objects || []).filter((obj) => !obj?.stationary)?.length > 0,
[objects],
);
@ -81,11 +81,10 @@ export function useCameraActivity(
return;
}
const updatedEventIndex = objects.findIndex(
(obj) => obj.id === updatedEvent.after.id,
);
const updatedEventIndex =
objects?.findIndex((obj) => obj.id === updatedEvent.after.id) ?? -1;
let newObjects: ObjectType[] = [...objects];
let newObjects: ObjectType[] = [...(objects ?? [])];
if (updatedEvent.type === "end") {
if (updatedEventIndex !== -1) {
@ -104,10 +103,10 @@ export function useCameraActivity(
score: updatedEvent.after.score,
sub_label: updatedEvent.after.sub_label?.[0] ?? "",
};
newObjects = [...objects, newActiveObject];
newObjects = [...(objects ?? []), newActiveObject];
}
} else {
const newObjects = [...objects];
const newObjects = [...(objects ?? [])];
let label = updatedEvent.after.label;
@ -158,7 +157,7 @@ export function useCameraActivity(
? detectingMotion === "ON"
: updatedCameraState?.motion === true
: false,
objects: isCameraEnabled ? objects : [],
objects: isCameraEnabled ? (objects ?? []) : [],
offline,
};
}

View File

@ -52,7 +52,18 @@ export type ObjectType = {
};
export interface FrigateCameraState {
enabled: boolean;
config: {
enabled: boolean;
detect: boolean;
snapshots: boolean;
record: boolean;
audio: boolean;
notifications: boolean;
notifications_suspended: number;
autotracking: boolean;
alerts: boolean;
detections: boolean;
};
motion: boolean;
objects: ObjectType[];
}