Zoneminder Recording Status & Home Assistant

Hey all,
Plugging away on getting my HA setup built out, and am now working on integrating Zoneminder into it.

One of the things I want to do is trigger some actions (don’t know which, yet) in HA based on motion being detected & recording happening within Zoneminder. I’ve read a number of posts - both here in the forum and elsewhere (Reddit, Blogs, etc), and I think that it should be possible to get the notification of activity from ZM into HA based on what I’ve read.

I have my ZM configured in HA, and can see images displayed on the home page:

# Zoneminder
zoneminder:
  host: 192.168.86.5:7070
  path_zms: /zm/cgi-bin/nph-zms

# IP Cameras
camera:
  - platform: zoneminder

If I look in the Logbook, I see two entires regarding the Motion-1 Camera, one stating that it’s changed to recording and one indicating that it’s changed to idle:

Screenshot from 2017-12-09 12-58-27

But that’s all I get…just the two entries. They never update.

If I look in the ZoneMinder UI, I can see all sorts of recording events. It was my expectation that I’d be seeing them in HA.

Is my understanding here incorrect? Is there not a way to do it? I saw some old (12+ month) posts indicating I needed to do it via MQTT, but the more recent ones suggest that it’s now native.

Anything I’m missing? Thanks for the help!

1 Like

Any luck with this? I am wanting to use my ZM instance to monitor cameras for movement, hopefully on “MOCORD” as most of my cameras are always recording.

I was able to curl a few my Foscam cameras but unfortunately I have a few different models of Amrest & Foscam so I would like a more ‘universal’ way to detect motion.

Have you added the zoneminder sensor ?
Sensor:

  • platform: zoneminder

For each camera in zoneminder, you get 2 sensors : sensor._events that counts events (including archived or not) and sensor._status (that is monitor, modect, etc etc)

You declared the zoneminder switch too ?
switch:

  • platform: zoneminder
    command_on: Modect
    command_off: Monitor

That will add a switch by camera declared in zoneminder and will change the status of that camera to the on or off status you declared.

You can also create a script to call preset positions using zmcontrol.

But as always with Zoneminder, there’s no way to know which zone created the event, and then act in consequence.

1 Like

I do not think that will work for me. Most of my cameras are set to record all the time. If there was a way (reliable/fast) to get the alarm notification of motion as well, then that is what I want. I do not believe counting events would work since I get an event every 10 minutes for each camera as it starts a new recording period.

What are you calling “motion detection” in zoneminder ? The only motion information you get is AFTER the event is closed. It increases the event count and the event has the cause (‘motion’, ‘signal’…) in it.
I don’t use mocord so I don’t know what cause it triggers but anyway, it isn’t in the event data. Neither is the zone that triggered the motion. So you’re limited to trigger on the increase of event count for one camera.
Because of that, I haven’t (yet ?) set an automation based on zoneminder events. Too much false positive.

If you only have an event every 10 minutes, you can in an automation, forget this one and trigger an alarm if repeat frequency is below 10 minutes ?

I guess I misunderstood how motion works in ZM. I am looking for immediate response. I use motion as both general presence detection and for alarm/security purposes. If I can’t figure out how to get it from ZM or direct from my cameras I will just have to invest in more standalone motion sensors or build more BRUH sensors.

Do you have false positive with ZM ? I have many when the house isn’t closed due to brightness variations, so that I can’t use it as a motion detection. It records when it sees a motion, and I have filters to remove what I found to be false positives (alarms with a very high score per image, and very short) so the disk doesn’t get full !

I’ll have to check the ZM API in details, to get it work with HA. Right now, the shell scripts calling zmcontrol.pl makes PTZ the camera easy (same command from HA, the specificity comes from ZM control file). But that’s about it…
If I could get per event information, including the zone that triggered it, I could use it in automations and notifications.

For ZM, I run 11 of my 12 cameras in record mode with a 5-day purge. I was hoping to get real-time notification of motion to increase the detectable areas in & around my home.

So far I have ended up with a Frankenstein approach:
ZM: for standalone camera recording/viewing and have ZM component in HA for viewing
Foscam cameras: use a curl command to retrieve motion alarm
Amcrest cameras: use Amcrest component & sensor to retrieve motion alarm then hide the camera view (since ZM already provides this)
2 manufactured PIR sensors
3 BRUH PIR sensors
2 tablets running IP Camera w/motion enabled

Did you ever work this out?

Zoneminder gave me a recording status once but never again.

1:41 PM
FrontDoor changed to idle
1:41 PM
FrontDoor changed to recording

No unfortunately. I ended up using rest? sensors to each camera. Not ideal and too much of a delay imho.

I made some progress, now I have something I find reliable with ZM and HA. It’s far from perfect but I get notifications when needed.
I’m using the number of events added to a template sensor, derive a trend binary-sensor from this value, and trigger the notification when it turns on, but with conditions to prevent too many notifications (only one in 10mn time) and false positive because of fast light change :

The template sensor :

   - platform: template
    sensors:
      alarmes:
        friendly_name : 'Mouvements ZM'
        unit_of_measurement: 'Events'
        value_template: "{{ ((states.sensor.cam1_events.state | int) + (states.sensor.cam2_events.state | int) + ((states.sensor.camext_events.state | int) * 0.66) + ((states.sensor.cam2ext_events.state | int) * 0.75) + ((states.sensor.cam3_events.state | int)) *1.5) | round(2) }}"

Notice that you can weight differently the cameras, I chose to limit the influence of the exterior cams, but add importance to the latest that is the basement, so no external interference except when the garage door opens !

Then the trend sensor, you’ll have to play a bit with the parameters to achieve what you expect.
In my case, I don’t want the sensor to turn on when there is no significant motion, I have a dog at home, doesn’t move that much when nobody’s home but he’s big enough to be detected. Not only min_gradient is important, but also limiting both sample number and sample duration makes the sensor forget about older events (whether they’ve been notified or not) :

  - platform: trend
    sensors:
      alerte_mouvement:
        # 3 events/minute
        entity_id: sensor.alarmes
        sample_duration: 600
        min_gradient: 0.05
        device_class: moving
        max_samples: 10

And last, the notification automation, won’t send the mail if the trend is too much. I sometimes have the camera report lots of very short events, dozen per minute, depending on the light condition. First “condition” filters that out. I’d rather have a “max_gradient” option to the trend sensor.

- alias: 'A_ Alerte ZM'
  trigger:
    platform: state
    entity_id: binary_sensor.alerte_mouvement
    to: 'on'
  condition:
    - condition: template
      value_template: "{{ (states.binary_sensor.alerte_mouvement.attributes['gradient'] | float) < 1.0 }}"
    - condition: state
      entity_id: binary_sensor.somebody_home
      state: 'off'
    - condition: template
      value_template: "{{ (as_timestamp(now()) - (as_timestamp(states.automation.a__alerte_zm.attributes['last_triggered']) | int)) > 600 }}"
  action:
    service: notify.alerte
    data_template:
      title: 'ZM ALARM'
      message: "Il y a {{ states.sensor.alarmes.state }} mouvements."

Note the parenthesis in the last condition that offer an ugly workaround for a never triggered automation : if “last triggered” is “None”, as_timestamp won’t fail but returns ‘None’, then the int cast will turn it into a convenient 0…

Of course, this comes after tuning ZoneMinder itself, for instance using the blend % parameter to have short events (but still significant…)

1 Like