add MQTT and dispatcher integration for profiles

- Subscribe to frigate/profile/set MQTT topic
- Publish profile/state and profiles/available on connect
- Add _on_profile_command handler to dispatcher
- Broadcast active profile state on WebSocket connect
This commit is contained in:
Josh Hawkins 2026-03-05 12:54:32 -06:00
parent f76bb9cfb8
commit 76c65bbf6d
2 changed files with 43 additions and 0 deletions

View File

@ -91,7 +91,9 @@ class Dispatcher:
}
self._global_settings_handlers: dict[str, Callable] = {
"notifications": self._on_global_notification_command,
"profile": self._on_profile_command,
}
self.profile_manager = None
for comm in self.comms:
comm.subscribe(self._receive)
@ -298,6 +300,11 @@ class Dispatcher:
)
self.publish("birdseye_layout", json.dumps(self.birdseye_layout.copy()))
self.publish("audio_detections", json.dumps(audio_detections))
self.publish(
"profile/state",
self.config.active_profile or "none",
retain=True,
)
def handle_notification_test() -> None:
self.publish("notification_test", "Test notification")
@ -556,6 +563,20 @@ class Dispatcher:
)
self.publish("notifications/state", payload, retain=True)
def _on_profile_command(self, payload: str) -> None:
"""Callback for profile/set topic."""
if self.profile_manager is None:
logger.error("Profile manager not initialized")
return
profile_name = payload.strip() if payload.strip() not in ("", "none", "None") else None
err = self.profile_manager.activate_profile(profile_name)
if err:
logger.error("Failed to activate profile: %s", err)
return
self.publish("profile/state", payload.strip() or "none", retain=True)
def _on_audio_command(self, camera_name: str, payload: str) -> None:
"""Callback for audio topic."""
audio_settings = self.config.cameras[camera_name].audio

View File

@ -1,3 +1,4 @@
import json
import logging
import threading
from typing import Any, Callable
@ -163,6 +164,22 @@ class MqttClient(Communicator):
retain=True,
)
self.publish(
"profile/state",
self.config.active_profile or "none",
retain=True,
)
available_profiles: list[str] = []
for camera in self.config.cameras.values():
for profile_name in camera.profiles:
if profile_name not in available_profiles:
available_profiles.append(profile_name)
self.publish(
"profiles/available",
json.dumps(sorted(available_profiles)),
retain=True,
)
self.publish("available", "online", retain=True)
def on_mqtt_command(
@ -289,6 +306,11 @@ class MqttClient(Communicator):
self.on_mqtt_command,
)
self.client.message_callback_add(
f"{self.mqtt_config.topic_prefix}/profile/set",
self.on_mqtt_command,
)
self.client.message_callback_add(
f"{self.mqtt_config.topic_prefix}/onConnect", self.on_mqtt_command
)