New ZoneMinder API

A PR would be nice. It might be a good idea to extend pyzm.helpers.Event.Event (ref) with functions to return the associated:

  • video
  • arbitrary image at an index (fid, snapshot, objdetect, alarm)

That way we can chain APIs easily.

I do have my docker setup correctly and currently feeding MQTT events into HA. That’s not the problem I have.
The problem I have is that this is the output ZoneMinder is sending to over MQTT:

{"hookvalue":"0","eventtype":"event_start","monitor":"1","state":"alarm","name":"Front Door:(1037) [a] detected:person:52% Motion Driveway","eventid":"1037"}

What I am trying to do is use some of the data from that in my automations.
For example, I currently use Deepstack to process my images and notify if a person is at the front door. However, lately ZoneMinder has been more accurate. So I’d like to be able to use the MQTT data from ZoneMinder but not send all of the above text. I’d like to be able to have a notification just send:
“Person or Car detected at the front door”

However I’m having a hard time extracting just the “Person” or “Car” from the above MQTT data and use that in a HA notify action.

For example, my current deepstack automation looks like this:

- id: person_detection
  alias: Notify when person detected
  initial_state: 'on'
  hide_entity: true
  condition:
  - condition: state
    entity_id: input_boolean.options_notifications_push
    state: 'on'
  trigger:
    platform: event
    event_type: image_processing.object_detected
    event_data:
      object: person
  action:
    - delay: 00:00:02
    - service: notify.telegram
      data_template:
        message: '{{ trigger.event.data.object }} detected at the front door'
        data:
          photo: 
            - file: '{{ states.camera.deepstack_latest_person.attributes.file_path }}'
              caption: Person Detected

Deepstack gives me the object as “person” or “car” so I can easily use that. I would like to find a way to do it with ZoneMinder. And if I can have the detection image from ZoneMinder included as well, then that would be perfect.

Any suggestion on how I can grab the “person” or “car” plus the detected image from ZoneMinder to use in HA?

1 Like

Ha! You are much more advanced than I :blush:
Yep, I have struggled with parsing the MQTT notification data also.

I did get as far as parsing out the name field using sensor/mqtt yaml descriptions such as this for my garage camera with zoneminder monitor id 1. This breaks out the eventid and the name/description string containing the message from yolo3?

sensor:
  - platform: mqtt
    name: "garage alert id"
    state_topic: "zoneminder/1"
    value_template: "{{ value_json.eventid }}"
  - platform: mqtt
    name: "garage alert desc"
    state_topic: "zoneminder/1"
    value_template: "{{ value_json.name }}"

I used the eventid to build a url (zoneminder api) to include the image as part of the text message sent via hangouts. I used the *garage alert desc" as the body of the text message. However, once I tightened up the authentication on zoneminder, the url building became too cumbersome for me. The only way I came up with is to write python code to do the fine grain parsing you are suggesting. I suspect you could do it via function nodes in node red but I elected to use the appdaemon approach and write an app to implement the automation script in python.

BTW, in case you didn’t see it, I provided a link to this blog article which provides the code he wrote for his appdaemon script/app. Note the image at the top of the article is his alert message via pushover. I was trying to duplicate that via hangups.

Below is the automation I used with the above sensor definition. I should note the garage notify boolean is a gate that allows me to easily shut off the alerts. I gave up on it (this automation) as I indicated and am now coding an app. Within the app, I am using pyzm to login to my zoneminder server and pull the objectdetect image associated with the event id.

- id: '1580088839247'
  alias: garage security alert
  description: ''
  trigger:
  - entity_id: sensor.garage_alert_id
    platform: state
  condition:
  - condition: state
    entity_id: input_boolean.garage_notify
    state: 'on'
  action:
  - data_template:
      message: 'Alert {{ states.sensor.garage_alert_desc.state }} at {{ now().strftime(''%H:%M %A %d %B %Y'') }} '
      data:
        image_file: "https://mydomain.duckdns.org/zm/index.php?view=image&eid={{ states('sensor.garage_alert_id') }}&fid=objdetect&width=600"
      title: Garage Security Alert
    service: notify.home_hangouts

I see you are using telegram, part of my problem may be trying to use hangouts. Really would like to stick with it since I use hangouts from my desktop browser gmail app and don’t want another messaging app.

Hopefully, this info is of use to you or someone reading this discussion. Apologies for implying you might not have zoneminder set up, obviously you are farther along than me.

Cheers

1 Like

This is exactly what I needed to get the info into my notifications. Thank you so much!
Now I should be able to use some splits to pull out his the “person” or “car” text from the event name.

Thank you again.

Thanks, nice of you to comment. I am curious which part was helpful?

Cheers

https://github.com/pliablepixels/zmeventnotification/issues/206 - I’ve just made an update to send out a nice JSON structure too. Testing at the moment. It may be a few days before it shows up in dlandon’s docker as he syncs based on his free time and only after I tag the release. If you are adventurous you can manually grab the updated ES+detection modules to test or wait a few days.

@pliablepixels amazing!
If I just replace the updated files, will that be enough?
Are each of your services (zm, zmevent, ml) available as separate containers (I know zm is. But I want the zmevent and ml pieces too)? I’d rather be able to update as soon as you push features.

Honestly, it was just the value templates from the mqtt sensors you setup. And then seeing how they were used. It helped me think of how I could utilise it too.

@pliablepixels Just completed the prototype of the appdaemon app (github:zmnotify)
I wrote up a feature request like we discussed on your github:zmeventnotification.

Working great except I need to understand how to leverage the
throttling you mentioned. Looking at that now.

Here is a snapshot.
zmnotify

Cheers

1 Like

One item I forgot to mention. Adding the pyzm package required changes to config for the Appdaemon addon. The build of pyzm was failing due to build failure in psutil.

This is version 0.1.2 of AppDaemon 4.
Config

{
  "system_packages": [
    "python3-dev",
    "gcc",
    "libc-dev",
    "linux-headers"
  ],
  "python_packages": [
    "pyzm"
  ],
  "init_commands": [
    "apk update"
  ],
  "log_level": "info"
}

@pliablepixels i’m not advanced enough to write something like this, but wondered if this API could be used to create a lovelace card to list alarm events with hook detection and the links to their videos?
I know ZMNinja has an option to show only items that are detected. In theory then, knowing that its been a positive trigger from detection, with the event_id and the portal URL one could pull a list of events from a user specified time period in a lovelace card?
This with Dlandon’s docker would make for a killer HA single Lovelace page for home security

Absolutely. Super simple do with pyzm. Here is the full code that lists only events detected with objects from all monitors for the last 1 day. You can easily integrate this with a card.

import pyzm.api as zmapi

api_options = {
    'apiurl': 'https://yourserver/zm/api',
    'portalurl': 'https://yourserver/zm',
    'user': 'admin',
    'password': 'password',
    'logger': None # use none if you don't want to log to ZM
}

zmapi = zmapi.ZMApi(options=api_options)

event_filter = {
    'from': '1 day ago', # this will use localtimezone, use 'tz' for other timezones
    'object_only':True,
}
events = zmapi.events(event_filter)
for e in events.list():
  print ('Monitor:{} Event:{} Notes:{} Detected Frame URL:{}'.format(e.monitor_id(),e.id(),e.notes(), e.get_image_url(fid='objdetect')))
2 Likes

Is there an easy way of creating a sensor based on the mqtt data from zoneminder… I’m thinking a person detected sensor that simply shows the time and date the last time a person was detected… it could work like motion sensors showing no detection by default and detected when a person is seen. I’m new to mqtt so feel a bit lost here

Sure is, look at the mqtt sensor config and the mqtt payload from a zm event. I don’t have access to my exact code to share

I provided an example of a sensor that does what you request earlier in this discussion.

The mqtt topics are enabled via configuring the ES (event server). The topic is based on the monitor id e.g. 1 in my example. I break out the event id field, you can use this as a trigger given zoneminder increments the event id as it generates motion events.

HTH

1 Like

I cracked it in the end by writing an app for the app daemon. I set up a virtual pir sensor and powered it using my code so it came “on” for 30 seconds every time a person is detected… I posted about it under the configuration topic on here

Hi

I installed dlandon’s docker zomeminder yesterday and I’ve enabled mqtt in the zmeventnotification.ini

I was wondering if there is an easy way to trigger a ‘force alarm’ event on a monitor to trigger a recording in ZM from home assistant?

I’d like to use home assistant sensors to decide when to record video, rather than using the motion detection in zoneminder.

Thanks
Mike

Edit - I found this but I’d like an easier method :smiley:

Edit 2 - I think this might be the way to go. --> https://gist.github.com/swilson/89096c289d07fdf7d5d92796354a7b19

This looks interesting, can you tell me where to put this file or point me to a doc? Thanks

I have dlandon’s ZM docker image running on the same server as my docker image of HA. I’ve enabled @pliablepixels ES and have created HA sensors for each of my cameras:

- platform: mqtt
  state_topic: "zoneminder/1" #driveway
  name: driveway_camera_object_detection
  value_template: "{{ value_json.eventid }}"

Although I see a lot of work and success with AppDaemon, I have not yet had to install it and am hoping to be able to avoid this. What I would like is to be able to push the picture from an event as a notification.

Reading the ES documentation, I found that the URL:
https://<IPADDRESS>:<PORT>/zm/index.php?view=image&eid=<EVENTID>&fid=objdetect
gives you the picture corresponding to the event_id pushed to the MQTT sensor. I have tried to create a simple bash script to either cURL or wget this image, but have had no success.

Is there an easy way to download the image without having to rely on the pyzim library? Is there no way with either cURL or wget to grab the image?

Yes here’s how I do it.

# Zoneminder Camera Processing

- alias: Front Door Object
  trigger:
    entity_id: sensor.front_door_event_id
    platform: state

  action:
    - service: downloader.download_file
      data_template:
        url: https://<ZM IP>:8443/zm/index.php?view=image&eid={{ states('sensor.front_door_event_id') }}&fid=objdetect
        filename: front_door_latest.jpg
        overwrite: true

    - service: downloader.download_file
      data_template:
        url: https://<ZM IP>:8443/zm/index.php?view=image&eid={{ states('sensor.front_door_event_id') }}&fid=objdetect
        filename: front_door_{{ now().strftime('%Y%m%d_%H%M%S') }}.jpg

# End Zoneminder Camera