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