Zoneminder + object detection + zmeventnotification + mqtt + appdemon = virtual motion sensor = success!

I’ve got zoneminder configured with object detection and zmevenotification and it all works very well. I’m not using the zm integration in HA, couldn’t see the point, however I do have zmeventnotification setup to publish to my mqtt server. I had the idea that maybe somehow when zm detected a “person” on my drive or in my back garden I’d like to use that in my HA setup. So using an input_boolean, a binary_sensor and some code in appdaemon I’ve made myself a virtual motion sensor. When a person is detected the motion sensor records “detected” for 30 seconds, which of course can be used in your automations, I use mine in my alarm system… I also use the front drive one to make an announcement over my google home speaker.

Here is how it works.

First of all in your appropriate config file configuration.yaml for me create an input_boolean for the appdaemon script to use.

input_boolean:
  person_front_drive:
    name: Person front drive
    initial: off

Then create a binary_sensor to act as the motion sensor which uses the input_boolean to set its state.

binary_sensor:
  - platform: template
    sensors:
      zm_person_front_drive:
        value_template: "{{ is_state('input_boolean.person_front_drive', 'on') }}"
        device_class: motion

Now for appdaemon, first of all in your apps.yaml add the following.

object_drive:
  module: zoneminder
  class: ZoneminderHass
  monitor_id: 4
  alarm_duration: 30
  switch: input_boolean.person_front_drive
  object_detect: "person"

Monitor Id = your zoneminder monitor id
alarm_duration = how long to leave your virtual motion sensor as “Detected” in seconds.
switch = the boolean_switch we created
object_detect = the object type to trigger a motion event, the object is as named by zoneminder

Next you need this code in your appdaemon apps directory, simply paste it into a file called zoneminder.py

import adbase as ad
import json

class ZoneminderHass(ad.ADBase):

  def initialize(self):
     self.adbase = self.get_ad_api()
     self.hass = self.get_plugin_api("HASS")
     self.mqtt = self.get_plugin_api("MQTT")

     self.monitor_id = self.args['monitor_id']
     self.alarm_duration = self.args['alarm_duration']
     self.switch = self.args['switch']
     self.object_detect = self.args['object_detect']

     self.mqtt.listen_event(self.event_callback, "MQTT_MESSAGE", topic = 'zoneminder/' + str(self.monitor_id))

# HANDLE A ZM MOTION EVENT, IF ITS A PERSON THEN SET THE MOTION SENSOR TO ON
  def event_callback(self, event_name, data, kwargs):
#     self.adbase.log("======================" + data['payload'])
     details = json.loads(data['payload'])
     personCount = 0

     for detection in details['detection']:
       if detection['label'] == self.object_detect:
         personCount += 1

     logMessage = "Num %s detected %s" % (self.object_detect,str(personCount))
     self.adbase.log(logMessage)

     if personCount > 0:
       logMessage = "Setting %s to on" % (self.switch)
       self.adbase.log(logMessage)
       self.hass.turn_on(self.switch)
       self.adbase.run_in(self.timeout_callback, self.alarm_duration)

# SET THE VIRTUAL MOTION DETECTION TO CLEAR
  def timeout_callback(self, kwargs):
    self.hass.turn_off(self.switch)
    logMessage = "Setting %s to off" % (self.switch)
    self.adbase.log(logMessage)

And there you go, you end up with a virtual motion sensor (the binary_sensor you created above).

Hope this helps someone, if anyone has a better way of doing this then let me know.

Cheers,

Jon

I did something very similar in nodered with the nodered customer component.

node red subscribes to the mqtt topics for 4 camera, when zoneminder sends the motion it turns on the motion sensors (configured in nodered) , then waits 10 seconds and turns motion sensor off.

I just added to it the logic that finds the image in zoneminder and sends it to my phone when nobody is home . Works great .

My zoneminder is running in docker on a under powered 10 year old unraid server . I wish it could do face detection but its just too slow. The object detection works great considering.

yes my zoneminder is running in a virtualbox instance on an old-ish intel i7. Object detection takes around 4 seconds, I can live with that.

A future upgrade might be to buy a google coral usb accelerator, I’ve read that reduces detection time to around 20ms and takes all the load off the cpu… might be an option for you

Yes I have read about those. How would they integrate into ZoneMinder, rather how would you tell zoneminder to use it.

zmeventnotification uses Darknet/YOLO for object detection… I suspect it would require a recompile of darknet in order to use the coral. Not got one so not looked into it too much, I’ve read about peeps who’ve used one tho

Hello,

i’m trying your code, but i keep having an error on AppDaemon launch.

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 00-banner.sh: executing... 
-----------------------------------------------------------
 Add-on: AppDaemon 4
 Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
 Add-on version: 0.2.6
 You are running the latest version of this add-on.
 System: HassOS 4.10  (amd64 / qemux86-64)
 Home Assistant Core: 0.111.4
 Home Assistant Supervisor: 227
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
[cont-init.d] 00-banner.sh: exited 0.
[cont-init.d] 01-log-level.sh: executing... 
[cont-init.d] 01-log-level.sh: exited 0.
[cont-init.d] appdaemon.sh: executing... 
[cont-init.d] appdaemon.sh: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
[14:07:20] INFO: Starting AppDaemon...
2020-06-18 14:07:22.304094 INFO AppDaemon: AppDaemon Version 4.0.3 starting
2020-06-18 14:07:22.304463 INFO AppDaemon: Python version is 3.8.2
2020-06-18 14:07:22.304738 INFO AppDaemon: Configuration read from: /config/appdaemon/appdaemon.yaml
2020-06-18 14:07:22.305075 INFO AppDaemon: Added log: AppDaemon
2020-06-18 14:07:22.305376 INFO AppDaemon: Added log: Error
2020-06-18 14:07:22.305665 INFO AppDaemon: Added log: Access
2020-06-18 14:07:22.305987 INFO AppDaemon: Added log: Diag
2020-06-18 14:07:22.337166 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin
2020-06-18 14:07:22.373048 INFO HASS: HASS Plugin Initializing
2020-06-18 14:07:22.373461 INFO HASS: HASS Plugin initialization complete
2020-06-18 14:07:22.374224 INFO AppDaemon: Initializing HTTP
2020-06-18 14:07:22.374846 INFO AppDaemon: Using 'ws' for event stream
2020-06-18 14:07:22.397726 INFO AppDaemon: Starting API
2020-06-18 14:07:22.405976 INFO AppDaemon: Starting Admin Interface
2020-06-18 14:07:22.406590 INFO AppDaemon: Starting Dashboards
2020-06-18 14:07:22.434247 INFO HASS: Connected to Home Assistant 0.111.4
2020-06-18 14:07:22.449503 INFO AppDaemon: App 'object_drive' added
2020-06-18 14:07:22.451032 INFO AppDaemon: Found 1 total apps
2020-06-18 14:07:22.451873 INFO AppDaemon: Starting Apps with 1 workers and 1 pins
2020-06-18 14:07:22.453741 INFO AppDaemon: Running on port 5050
2020-06-18 14:07:22.497814 INFO HASS: Evaluating startup conditions
2020-06-18 14:07:22.517688 INFO AppDaemon: Got initial state from namespace default
2020-06-18 14:07:24.461432 INFO AppDaemon: Scheduler running in realtime
2020-06-18 14:07:24.466400 INFO AppDaemon: Adding /config/appdaemon/apps to module import path
2020-06-18 14:07:24.469394 INFO AppDaemon: Loading App Module: /config/appdaemon/apps/zoneminder.py
2020-06-18 14:07:24.476284 INFO AppDaemon: Initializing app object_drive using class ZoneminderHass from module zoneminder
2020-06-18 14:07:24.484260 WARNING AppDaemon: Unknown Plugin Configuration in get_plugin_api()
2020-06-18 14:07:24.486863 WARNING object_drive: ------------------------------------------------------------
2020-06-18 14:07:24.487511 WARNING object_drive: Unexpected error running initialize() for object_drive
2020-06-18 14:07:24.488070 WARNING object_drive: ------------------------------------------------------------
2020-06-18 14:07:24.491591 WARNING object_drive: Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/appdaemon/app_management.py", line 145, in initialize_app
    await utils.run_in_executor(self, init)
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 276, in run_in_executor
    response = future.result()
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/appdaemon/apps/zoneminder.py", line 16, in initialize
    self.mqtt.listen_event(self.event_callback, "MQTT_MESSAGE", topic = 'zoneminder/' + str(self.monitor_id))
AttributeError: 'NoneType' object has no attribute 'listen_event'
2020-06-18 14:07:24.492211 WARNING object_drive: ------------------------------------------------------------
2020-06-18 14:07:24.495014 INFO AppDaemon: App initialization complete

Can you please assist?

Seems like you don’t have mqtt set up.

i have Mosquito broker 5.1 installed.
I can see the client connecting in the log, and i can see the messages coming in in the developer tools.

Do you have it set up properly for appdaemon?

ok you were right, i didn´t configure well mqtt inside it.
But now that i don’t have the error, the ninary sensor is not triggered.

Anyway, i went the node red way, and all is working fine now.
Thank you

sounds like you were close… when the switch wasn’t working was prob just the switch you named in your apps.yaml not matching what you’d setup in HA… I did think about using something like node red but wanted to keep it all “in house” with a minimum of moving parts as it were… glad you got it sorted in the end tho

I mean, it’s not really in house if you’re using appdaemon. Node red is a competitor to appdaemon.

I have the dlandon docker image installed and trying to get mqtt te work properly.

Zoneminder is installed and running. Adding cams is no problem. I edited the zmeventnotification.ini and the sectrets.ini.

Nothing happens. I dont’t see anything in my mqtt logs. Its really frustrating.

have you checked you can connect to mqtt from outside your server? There is a free windows client called mqtt-explorer, you could use that to see if you can connect to it

Cool it’s also a Mac app. Thanks I see the messages coming true.

@stryker would you mind explaining the steps to activate mqtt notifications in zoneminder.
thank you

Its done in zmeventnotification.

/etc/zm/zmeventnotification.ini and use the following lines putting in your mqtt server’s ip address

Use MQTT for messaging (default: no)

[mqtt]
enable = yes

MQTT server (default: 127.0.0.1)

server = x.x.x.x

If you’ve not setup zmeventnotification you’ve got a small way to go but google it, the instructions are all there.

Yes thank you. I got it working already
Like everything its quite simple when you know the steps. Problem is the instructions are in different parts.
Not 1 place with it all.