Ability to enable / disable motion detection via MQTT (#3117)

* Starting working on adding motion toggle

* Add all info to mqtt command

* Send motion to correct funs

* Update mqtt docs

* Fixes for contingencies

* format

* mypy

* Tweak behavior

* Fix motion breaking frames

* Fix bad logic in detect set

* Always set value for motion boxes
This commit is contained in:
Nicolas Mowen 2022-04-26 06:29:28 -06:00 committed by GitHub
parent b75929a846
commit 0a4d658c7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 2 deletions

View File

@ -118,6 +118,15 @@ Topic to turn snapshots for a camera on and off. Expected values are `ON` and `O
Topic with current state of snapshots for a camera. Published values are `ON` and `OFF`. Topic with current state of snapshots for a camera. Published values are `ON` and `OFF`.
### `frigate/<camera_name>/motion/set`
Topic to turn motion detection for a camera on and off. Expected values are `ON` and `OFF`.
NOTE: Turning off motion detection will fail if detection is not disabled.
### `frigate/<camera_name>/motion/state`
Topic with current state of motion detection for a camera. Published values are `ON` and `OFF`.
### `frigate/<camera_name>/improve_contrast/set` ### `frigate/<camera_name>/improve_contrast/set`
Topic to turn improve_contrast for a camera on and off. Expected values are `ON` and `OFF`. Topic to turn improve_contrast for a camera on and off. Expected values are `ON` and `OFF`.

View File

@ -91,6 +91,7 @@ class FrigateApp:
"detection_enabled": mp.Value( "detection_enabled": mp.Value(
"i", self.config.cameras[camera_name].detect.enabled "i", self.config.cameras[camera_name].detect.enabled
), ),
"motion_enabled": mp.Value("i", True),
"improve_contrast_enabled": mp.Value( "improve_contrast_enabled": mp.Value(
"i", self.config.cameras[camera_name].motion.improve_contrast "i", self.config.cameras[camera_name].motion.improve_contrast
), ),

View File

@ -78,6 +78,12 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics):
logger.info(f"Turning on detection for {camera_name} via mqtt") logger.info(f"Turning on detection for {camera_name} via mqtt")
camera_metrics[camera_name]["detection_enabled"].value = True camera_metrics[camera_name]["detection_enabled"].value = True
detect_settings.enabled = True detect_settings.enabled = True
if not camera_metrics[camera_name]["motion_enabled"].value:
logger.info(
f"Turning on motion for {camera_name} due to detection being enabled."
)
camera_metrics[camera_name]["motion_enabled"].value = True
elif payload == "OFF": elif payload == "OFF":
if camera_metrics[camera_name]["detection_enabled"].value: if camera_metrics[camera_name]["detection_enabled"].value:
logger.info(f"Turning off detection for {camera_name} via mqtt") logger.info(f"Turning off detection for {camera_name} via mqtt")
@ -89,6 +95,32 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics):
state_topic = f"{message.topic[:-4]}/state" state_topic = f"{message.topic[:-4]}/state"
client.publish(state_topic, payload, retain=True) client.publish(state_topic, payload, retain=True)
def on_motion_command(client, userdata, message):
payload = message.payload.decode()
logger.debug(f"on_motion_toggle: {message.topic} {payload}")
camera_name = message.topic.split("/")[-3]
if payload == "ON":
if not camera_metrics[camera_name]["motion_enabled"].value:
logger.info(f"Turning on motion for {camera_name} via mqtt")
camera_metrics[camera_name]["motion_enabled"].value = True
elif payload == "OFF":
if camera_metrics[camera_name]["detection_enabled"].value:
logger.error(
f"Turning off motion is not allowed when detection is enabled."
)
return
if camera_metrics[camera_name]["motion_enabled"].value:
logger.info(f"Turning off motion for {camera_name} via mqtt")
camera_metrics[camera_name]["motion_enabled"].value = False
else:
logger.warning(f"Received unsupported value at {message.topic}: {payload}")
state_topic = f"{message.topic[:-4]}/state"
client.publish(state_topic, payload, retain=True)
def on_improve_contrast_command(client, userdata, message): def on_improve_contrast_command(client, userdata, message):
payload = message.payload.decode() payload = message.payload.decode()
logger.debug(f"on_improve_contrast_toggle: {message.topic} {payload}") logger.debug(f"on_improve_contrast_toggle: {message.topic} {payload}")
@ -156,6 +188,9 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics):
client.message_callback_add( client.message_callback_add(
f"{mqtt_config.topic_prefix}/{name}/detect/set", on_detect_command f"{mqtt_config.topic_prefix}/{name}/detect/set", on_detect_command
) )
client.message_callback_add(
f"{mqtt_config.topic_prefix}/{name}/motion/set", on_motion_command
)
client.message_callback_add( client.message_callback_add(
f"{mqtt_config.topic_prefix}/{name}/improve_contrast/set", f"{mqtt_config.topic_prefix}/{name}/improve_contrast/set",
on_improve_contrast_command, on_improve_contrast_command,

View File

@ -14,6 +14,7 @@ class CameraMetricsTypes(TypedDict):
detection_frame: Synchronized detection_frame: Synchronized
ffmpeg_pid: Synchronized ffmpeg_pid: Synchronized
frame_queue: Queue frame_queue: Queue
motion_enabled: Synchronized
improve_contrast_enabled: Synchronized improve_contrast_enabled: Synchronized
process: Optional[Process] process: Optional[Process]
process_fps: Synchronized process_fps: Synchronized

View File

@ -361,6 +361,7 @@ def track_camera(
frame_queue = process_info["frame_queue"] frame_queue = process_info["frame_queue"]
detection_enabled = process_info["detection_enabled"] detection_enabled = process_info["detection_enabled"]
motion_enabled = process_info["motion_enabled"]
improve_contrast_enabled = process_info["improve_contrast_enabled"] improve_contrast_enabled = process_info["improve_contrast_enabled"]
frame_shape = config.frame_shape frame_shape = config.frame_shape
@ -393,6 +394,7 @@ def track_camera(
objects_to_track, objects_to_track,
object_filters, object_filters,
detection_enabled, detection_enabled,
motion_enabled,
stop_event, stop_event,
) )
@ -479,6 +481,7 @@ def process_frames(
objects_to_track: list[str], objects_to_track: list[str],
object_filters, object_filters,
detection_enabled: mp.Value, detection_enabled: mp.Value,
motion_enabled: mp.Value,
stop_event, stop_event,
exit_on_empty: bool = False, exit_on_empty: bool = False,
): ):
@ -512,8 +515,8 @@ def process_frames(
logger.info(f"{camera_name}: frame {frame_time} is not in memory store.") logger.info(f"{camera_name}: frame {frame_time} is not in memory store.")
continue continue
# look for motion # look for motion if enabled
motion_boxes = motion_detector.detect(frame) motion_boxes = motion_detector.detect(frame) if motion_enabled.value else []
regions = [] regions = []

View File

@ -115,6 +115,7 @@ class ProcessClip:
} }
detection_enabled = mp.Value("d", 1) detection_enabled = mp.Value("d", 1)
motion_enabled = mp.Value("d", True)
stop_event = mp.Event() stop_event = mp.Event()
model_shape = (self.config.model.height, self.config.model.width) model_shape = (self.config.model.height, self.config.model.width)
@ -133,6 +134,7 @@ class ProcessClip:
objects_to_track, objects_to_track,
object_filters, object_filters,
detection_enabled, detection_enabled,
motion_enabled,
stop_event, stop_event,
exit_on_empty=True, exit_on_empty=True,
) )