Files
zoneminder/db
Isaac Connor eafdffcd95 feat: add per-monitor actions that drive a light or a speaker on alarm
A camera that detects motion should be able to sound a speaker, and the
speaker is rarely the camera: it is a separate device with its own address,
credentials, stream and Controls entry. Model it as a monitor and let a
monitor's alarm drive actions on other monitors.

Add Monitors.DeviceClass enum('Camera','Speaker'). This is what the device
is, as distinct from Type, which selects the capture backend - an IP speaker
still captures over Ffmpeg like any other RTSP device, so Type could not
carry the distinction.

Add the MonitorActions table: MonitorId is the monitor that triggers,
TargetMonitorId the device acted on, and the two are frequently different.
TriggerOn covers EventStart, EventEnd, Alarm and Manual.

Which actions a device is offered is decided by its Controls row - CanLight,
CanIndicatorLight, CanAudioPlay - so a device can only be asked to do what it
has been measured to do. The editor filters on this and the save path
re-checks it, because the request is not to be trusted.

Execution goes straight to the target's zmcontrol socket rather than forking
zmcontrol.pl per action: the daemon already accepts a line of JSON there, and
it is the same path the control panel uses. ActionCommandName maps the DB
enum onto a method name as a whitelist, so nothing out of the database
reaches the control daemon uninspected. Actions are fire-and-forget - a
speaker that is offline is logged and skipped, never allowed to hold up event
handling.

Alarm actions fire only on the genuine entry into alarm, not on the
ALERT->ALARM re-entry, which would re-sound a speaker within one incident.
EventEnd runs on the calling thread before the event is handed to the closing
thread, which does not capture `this`.

Manual actions appear as buttons on the watch page, and are the reason the
control panel is now shown for a monitor that has actions but no control of
its own. Firing one sends only the action id; the command and target are
rebuilt server side, and Control rights are required on the target device and
not merely on the monitor the action hangs off.

Also add --file to zmcontrol.pl, without which audioPlay could not be driven
from the command line. The web path was unaffected as it bypasses GetOptions.

Tests: tests/zm_monitor_action.cpp covers the command whitelist, the message
format (including that file id 0 is a real id and that a stale AudioFile is
never passed to a command that takes none), trigger names, and that every
value of the ActionType enum maps to a command.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UvTCzCbvGt8xKQRNCSA7o8
(cherry picked from commit b561341e988af69c3a46db854da410309f7cfa82)
2026-09-11 20:13:02 -05:00
..
2013-12-24 11:07:27 +00:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2013-03-17 00:45:21 +01:00
2014-10-18 15:23:13 -05:00
2016-01-01 10:15:36 -06:00
2016-05-31 19:41:17 -05:00
2017-05-02 13:25:56 -05:00
2017-05-09 09:54:48 -05:00
2020-11-23 19:31:21 -05:00
2017-10-03 13:28:56 -07:00
2020-11-23 19:33:53 -05:00
2017-10-16 08:30:28 -07:00
2017-11-26 15:08:12 -05:00
2018-02-18 11:01:33 -05:00
2018-01-19 13:29:45 -05:00
2018-01-19 12:17:42 -05:00
2018-01-24 12:16:18 -05:00
2018-02-05 22:59:37 -05:00
2018-02-18 11:29:22 -05:00
2018-09-12 07:27:45 -05:00
2018-10-02 07:37:55 -05:00
2018-10-13 13:36:15 -05:00
2018-12-12 09:17:14 -05:00
2019-05-13 14:48:26 -04:00
2024-04-08 09:50:12 -04:00
2020-02-04 16:47:33 -05:00
2020-02-19 13:50:27 -05:00
2020-03-06 14:52:38 -05:00
2020-03-26 15:34:36 -04:00
2020-03-04 10:15:44 -05:00
2020-05-12 15:46:07 -04:00
2020-10-02 14:49:59 -04:00
2021-01-27 09:58:55 -05:00
2021-04-23 14:52:29 -04:00
2021-07-07 09:45:53 -04:00
2022-01-10 09:07:59 -05:00
2022-01-10 23:22:37 -06:00
2022-01-22 12:30:59 -05:00
2022-12-24 09:18:04 -05:00
2023-02-25 12:44:28 -05:00
2025-09-24 09:53:11 -04:00