Zoneminder trigger + HikVision motion sensing. "How to"

dingbatca

n3wb
Jun 25, 2015
11
5
I have seen this question come up a few times. How can you use hikvisions internal motion sensing to trigger zoneminder to capture an event. It took a bit of doing and a lot of Linux hacking, but I got.

Here is how I did it. If any one finds a cleaner way, please respond to this thread!

My setup:
HikVision DS-2CD2132-I, firmware 5.2.5, 192.168.0.16
Zoneminder 1.29.0, 192.168.0.5

I am going to assume you at least have a basic working knowledge of Linux if you are running Zoneminder.

Firstly, the default firmware of the camera is rather limited when it comes to tools. So we need to get a full blow version of busybox installed.

Download busybox on the zoneminder system then copy it to the camera.
Code:
wget https://www.busybox.net/downloads/binaries/busybox-armv5l
cat busybox-armv5l | ssh admin@192.168.0.16 "mkdir /dav/opt/ ; cat > /dav/opt/busybox"

Now that we have busybox in place, lets go setup our environment on the camera.
ssh admin@192.168.0.16
Code:
cd /dav/opt
chmod 755 busybox

/dav/opt/busybox --install -s
export PATH=.:/bin:/sbin:/usr/sbin:/usr/bin 

#busybox setup automatically at boot time:
echo "/dav/opt/busybox --install -s" >> /dav/initrun.sh

Lets try a basic test, from the camera. Just sends a start event from the camera to zoneminder. If this does not work, you need to check that zoneminder triggers are setup to take actions on events.
Code:
 #Event syntax: camera|action|priority|Cause
echo "2|on+120|1|Motion test" | nc 192.168.0.5 6802

If the above zoneminder test worked, lets test the cameras internal motion sensing is setup. If this does not work, please log into the web interface for the camera and setup motion sensing.
Code:
#Shut everything up
setDebug -m ALL -l 0

#Enable debugging for only alarms
setDebug -m ALARM_EXP -l 7

#Open the debug log
outputOpen

#Now trigger a motion event, and you should see (below), along with a lot of other stuff.
[05-25 14:39:02][pid:849][ALARM_EXP][DEBUG]excepCtrl: chan 1 motion start.
[05-25 14:40:16][pid:849][ALARM_EXP][DEBUG]excepCtrl: chan 1 motion stop, time=1464187216.

outputClose with stop the logging


Now the fun begins. HikVision has a built in set of debugging tools. The problem is all the output is dumped to /dev/pts/X, which means the only way to capture it, is scrape a session. I dont like this, but it is the only way I have found.
Code for telnet to use.
Code:
vi /dav/opt/telnet.input.sh
sleep 1
echo "setDebug -m ALL -l 0"
echo "setDebug -m ALARM_EXP -l 7"
echo "outputClose"
echo "outputOpen"
sleep 86400
echo "outputClose"

outputXlogger.sh is the program that does all the work. To tweak it to your enviroment, all that we need to change is the ZONEMINDER_IP and the CAMERA_NUMBER.
Code:
vi /dav/opt/outputXlogger.sh
#!/bin/sh
export PATH=.:/bin:/sbin:/usr/sbin:/usr/bin

ZONEMINDER_IP="192.168.0.5"
ZONEMINDER_PORT="6802"
MAX_EVENT_LENGTH="120"

#Camera number as definded by zoneminder
CAMERA_NUMBER="2"

LOG_OUTPUT="/dav/opt/dump.tmp"
TELNET_INPUT="/dav/opt/telnet.input.sh"

#monitor#|action|priority|Cause|text|showtext where
#Generate the start and stop scripts
echo "echo \"$CAMERA_NUMBER|on+$MAX_EVENT_LENGTH|1|Motion detect start\" | nc $ZONEMINDER_IP $ZONEMINDER_PORT >> $LOG_OUTPUT" > /tmp/zmmstart.sh
echo "echo \"$CAMERA_NUMBER|off|1|Motion detect stop\" | nc $ZONEMINDER_IP $ZONEMINDER_PORT >> $LOG_OUTPUT" > /tmp/zmmstop.sh
chmod 755 /tmp/zmmstart.sh /tmp/zmmstop.sh

while true; do
  #Telnet running on 127.0.0.1:2323?
  TELNET=`ps | grep telnet | grep "127.0.0.1:2323" | grep -v grep`
  if [ "$TELNET" = "" ]; then
  echo "Telnet is not running, restarting"

  #Setup telnet, no login, localhost only!, port 2323
  telnetd -l /bin/sh -b 127.0.0.1:2323
  fi

#Magic, take the arguments from telnet.input.sh, pipe to telnet aginst local host, then capture the output.
  #FYI: I hate this.  If some one finds a better way to gather outputOpen, let me know.
  /dav/opt/telnet.input.sh | telnet 127.0.0.1 2323 | awk '
  /excepCtrl: chan . motion start/ { system("/tmp/zmmstart.sh &") }
  /excepCtrl: chan . motion stop/ { system("/tmp/zmmstop.sh &") }
  /excepCtrl: chan . line detect start/ { system("/tmp/zmmstart.sh &") }
  /excepCtrl: chan . line detect stop/ { system("/tmp/zmmstop.sh &") } ' > $LOG_OUTPUT

  #If for some odd reason the telnet function fails, I dont want this script going crazy
  sleep 1
done

Last steps, make it executable and give it a test!
Code:
cd /dav/opt/
chmod 755 outputXlogger.sh telnet.input.sh
/dav/opt/outputXlogger.sh

More to come later. Just wanted to get this much posted.
 
Last edited by a moderator:
  • Like
Reactions: alastairstevenson
Excellent.
An eye-opener on what can be done with some eLinux skills.
A very minor comment for info - the full-blown busybox has a handy --install feature that can set up all the symlinks.
 
Updated to support the built in line detection:
Code:
#motion event, and you should see (below), along with a lot of other stuff.
[05-25 14:39:02][pid:849][ALARM_EXP][DEBUG]excepCtrl: chan 1 motion start.
[05-25 14:40:16][pid:849][ALARM_EXP][DEBUG]excepCtrl: chan 1 motion stop, time=1464187216.

#Line cross event, and you should see (below), along with a lot of other stuff.
[06-02 08:37:39][pid:849][ALARM_EXP][DEBUG]excepCtrl: chan 1 line detect start.
[06-02 08:37:44][pid:849][ALARM_EXP][DEBUG]excepCtrl: chan 1 line detect stop.

outputXlogger.sh in the "how to" now watchs for both types of changes. Also tweaked it so, in theory, it supports more then one motion/line area. I am sure this can be done much cleaner with some regex, but I suck at regex.
 
Last edited by a moderator: