add enabled switch

This commit is contained in:
Josh Hawkins 2025-07-02 13:08:02 -05:00
parent 38a5797681
commit aca9e15790
9 changed files with 61 additions and 4 deletions

View File

@ -107,6 +107,8 @@ class CameraConfigUpdateSubscriber:
config.record = updated_config
elif update_type == CameraConfigUpdateEnum.review:
config.review = updated_config
elif update_type == CameraConfigUpdateEnum.semantic_search:
config.semantic_search = updated_config
elif update_type == CameraConfigUpdateEnum.snapshots:
config.snapshots = updated_config
elif update_type == CameraConfigUpdateEnum.zones:

View File

@ -125,10 +125,11 @@ class SemanticSearchConfig(FrigateBaseModel):
class TriggerConfig(FrigateBaseModel):
enabled: bool = Field(default=True, title="Enable this trigger")
type: TriggerType = Field(default=TriggerType.DESCRIPTION, title="Type of trigger")
data: str = Field(title="Trigger content (text phrase or image ID)")
threshold: float = Field(
title="Confidence score required to run the trigger.",
title="Confidence score required to run the trigger",
default=0.8,
gt=0.0,
le=1.0,

View File

@ -80,6 +80,16 @@ class SemanticTriggerProcessor(PostProcessorApi):
)
for trigger in triggers:
if (
not self.config.cameras[camera]
.semantic_search.triggers[trigger["name"]]
.enabled
):
logger.debug(
f"Trigger {trigger['name']} is disabled for camera {camera}"
)
continue
logger.debug(
f"Processing {trigger['type']} trigger for {event_id} on {trigger['camera']}: {trigger['name']}"
)
@ -171,6 +181,7 @@ class SemanticTriggerProcessor(PostProcessorApi):
.actions
):
# TODO: handle actions for the trigger
# notifications already handled by webpush
pass
if WRITE_DEBUG_IMAGES:

View File

@ -97,7 +97,11 @@ class EmbeddingMaintainer(threading.Thread):
self.config_updater = CameraConfigUpdateSubscriber(
self.config,
self.config.cameras,
[CameraConfigUpdateEnum.add, CameraConfigUpdateEnum.remove],
[
CameraConfigUpdateEnum.add,
CameraConfigUpdateEnum.remove,
CameraConfigUpdateEnum.semantic_search,
],
)
# Configure Frigate DB

View File

@ -693,6 +693,9 @@
"alreadyExists": "A trigger with this name already exists for this camera."
}
},
"enabled": {
"description": "Enable or disable this trigger"
},
"type": {
"title": "Trigger Type",
"placeholder": "Select trigger type"

View File

@ -34,12 +34,14 @@ import ActivityIndicator from "@/components/indicators/activity-indicator";
import { FrigateConfig } from "@/types/frigateConfig";
import ImagePicker from "@/components/overlay/ImagePicker";
import { Trigger, TriggerAction, TriggerType } from "@/types/trigger";
import { Switch } from "@/components/ui/switch";
type CreateTriggerDialogProps = {
show: boolean;
trigger: Trigger | null;
selectedCamera: string;
onCreate: (
enabled: boolean,
name: string,
type: TriggerType,
data: string,
@ -74,6 +76,7 @@ export default function CreateTriggerDialog({
}, [config, selectedCamera]);
const formSchema = z.object({
enabled: z.boolean(),
name: z
.string()
.min(2, t("triggers.dialog.form.name.error.minLength"))
@ -101,6 +104,7 @@ export default function CreateTriggerDialog({
resolver: zodResolver(formSchema),
mode: "onChange",
defaultValues: {
enabled: trigger?.enabled ?? true,
name: trigger?.name ?? "",
type: trigger?.type ?? "description",
data: trigger?.data ?? "",
@ -115,6 +119,7 @@ export default function CreateTriggerDialog({
onEdit({ ...values });
} else {
onCreate(
values.enabled,
values.name,
values.type,
values.data,
@ -128,6 +133,7 @@ export default function CreateTriggerDialog({
useEffect(() => {
if (!show) {
form.reset({
enabled: true,
name: "",
type: "description",
data: "",
@ -136,6 +142,7 @@ export default function CreateTriggerDialog({
});
} else if (trigger) {
form.reset({
enabled: trigger.enabled,
name: trigger.name,
type: trigger.type,
data: trigger.data,
@ -194,6 +201,29 @@ export default function CreateTriggerDialog({
)}
/>
<FormField
control={form.control}
name="enabled"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between">
<div className="space-y-0.5">
<FormLabel className="text-base">
{t("enabled", { ns: "common" })}
</FormLabel>
<div className="text-sm text-muted-foreground">
{t("triggers.dialog.form.enabled.description")}
</div>
</div>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="type"

View File

@ -224,6 +224,7 @@ export interface CameraConfig {
semantic_search: {
triggers: {
[triggerName: string]: {
enabled: boolean;
type: TriggerType;
data: string;
threshold: number;

View File

@ -2,6 +2,7 @@ export type TriggerType = "thumbnail" | "description";
export type TriggerAction = "alert" | "notification";
export type Trigger = {
enabled: boolean;
name: string;
type: TriggerType;
data: string;

View File

@ -36,6 +36,7 @@ type ConfigSetBody = {
triggers?: {
[key: string]:
| {
enabled: boolean;
type: string;
data: string;
threshold: number;
@ -84,6 +85,7 @@ export default function TriggerView({
return Object.entries(
config.cameras[selectedCamera].semantic_search.triggers,
).map(([name, trigger]) => ({
enabled: trigger.enabled,
name,
type: trigger.type,
data: trigger.data,
@ -99,7 +101,7 @@ export default function TriggerView({
const saveToConfig = useCallback(
(trigger: Trigger, isEdit: boolean) => {
setIsLoading(true);
const { name, type, data, threshold, actions } = trigger;
const { enabled, name, type, data, threshold, actions } = trigger;
const embeddingBody: TriggerEmbeddingBody = { type, data, threshold };
const embeddingUrl = isEdit
? `/trigger/embedding/${selectedCamera}/${name}`
@ -117,6 +119,7 @@ export default function TriggerView({
semantic_search: {
triggers: {
[name]: {
enabled,
type,
data,
threshold,
@ -172,6 +175,7 @@ export default function TriggerView({
const onCreate = useCallback(
(
enabled: boolean,
name: string,
type: TriggerType,
data: string,
@ -179,7 +183,7 @@ export default function TriggerView({
actions: TriggerAction[],
) => {
setUnsavedChanges(true);
saveToConfig({ name, type, data, threshold, actions }, false);
saveToConfig({ enabled, name, type, data, threshold, actions }, false);
setShowCreate(false);
},
[saveToConfig, setUnsavedChanges],