Difference between revisions of "Modifying ZoneMinder to remember run state names"

From ZoneMinder Wiki
Jump to navigationJump to search
Line 1: Line 1:
[[Various Learnings from getting Zomeminder 1.28.1 working well on Ubuntu Server 14.04|<Home]]
[[Various Learnings from getting Zomeminder 1.28.1 working well on Ubuntu Server 14.04|<Home]]
==Deprecated ==
As of ZoneMinder 1.28.107, this hack is no longer needed.
ZoneMinder now supports the ability to support remembering and restoring run states
== Rest of this document is kept for historical reasons - they will not work in new versions.==


==Why do we need it? ==
==Why do we need it? ==

Revision as of 07:34, 21 November 2015

<Home

Deprecated

As of ZoneMinder 1.28.107, this hack is no longer needed. ZoneMinder now supports the ability to support remembering and restoring run states


Rest of this document is kept for historical reasons - they will not work in new versions.

Why do we need it?

Zone minder already supports run states. You can configure your monitors in specific modes, save then as "run states" and use cron to switch to them. For example, let's take this situation:

  • You have two cameras
  • You want to have them set in "modect" and "disabled" when you are in the house (say 6PM - 8AM)
  • You want to have them set in "modect" and "enabled" when you are out of the house (say 8:01AM - 5:59PM)

So let's say, you create two states, "in" and "out" and set up your cron to switch between them based on time of day. All great!

But now let's say you want to create a state called 'vacation' which is basically the same as "out" but you want to differentiate it from out because if you are in "vacation" mode, you don't want cron to change state back to "in" - you want to record all the time.

How do you do it? Well you can't because Zoneminder only remembers "monitor states". It does not remember the name of the state. And given that "out" is the same as "vacation" in terms of monitor states, there is nothing that differentiates them as far as zone minder goes.

You can of course work around this limitation by having some sort of check where you change cron files but that is not a clean solution. Plus, lets say you leave for vacation and then need to set your mode to vacation remotely - you likely have access to your ZM console but don't have access to ssh to your box - you'd like to set it to vacation via the ZM console and have cron respect it.

So wouldn't it be cool if we could modify ZM to remember run state names and display them like this?

159429902.bmlBefkq.ScreenShot20150313at1.39.35PM.png


To do this, we need to modify a few files. Here is the strategy:

  • The file that changes run states is called "zmpkg.pl" --> we will modify it to write the run state to a text file. That way we can check that file to know the current run state any time ( I could avoid the text file and create a new element in the ZM DB, but I did not want to take a chance if this would mess up future upgrades)
  • When changing states in cron, we will use a wrapper shell script instead of directly calling zmpkg.pl that will change state only if the current state is not "vacation"
  • To make it more integrated, we will modify the web interface to display the current run state name (in addition to just "Running") just as we showed in the image above

The solution then provides a neat interface to make changes directly via the ZM web interface and check the state as well. No cron file swapping etc needed

Assumptions

The rest of the modifications assume you have created the following states in ZoneMinder:

  • in-modect (state of monitors when you are in)
  • out-modect (state of monitors when you are out)
  • vacation (state of monitors when you are on vacation)

Modifying /usr/bin/zmpkg.pl

Here is my modified zmpkg.pl. Look for code after comments starting with #ARC to see changes. PLEASE DO NOT OVERWRITE YOUR zmpkg.pl without making a backup.


https://github.com/pliablepixels/zmhacks/blob/master/zmpkg.pl

With these changes, each time zmpkg makes a run state change, it will write the name of the run state to a file called /usr/share/zoneminder/zm_run_state.txt

Modifying /etc/init.d/zoneminder

We also need to make sure that zmpkg has write permissions to zm_run_state.txt. The best way to do it is when ZM starts, we touch that file and make sure its owner is ww-data

Here is the modified zone minder init script

(ignore the phone_log_state* files - that is for another hack - changing ZM to change state based on iPhone location)

https://github.com/pliablepixels/zmhacks/blob/master/zoneminder

Cron file

Here is my cron file to schedule changes (ignore the iPhone files they are for another hack)

MAILTO=""

# m h  dom mon dow   command
# Updates location of iPhone every hour 
10 */1 * * * /usr/bin/arc_zm_iphone.py

# Check for iPhone status every 5 minutes
*/5 * * * * /usr/bin/arc_zm_checkiPhone.sh

## MON-FRI RULES
# switch to motion recording at 8:45 am M-F
45 10 * * 1-5 /usr/bin/arc_zm_change_state.sh out-modect

# switch to motion monitor at 6:30pm M-F
30 18 * * 1-5 /usr/bin/arc_zm_change_state.sh in-modect

# switch to motion recording 8:45PM M-F
45 20 * * 1-5 /usr/bin/arc_zm_change_state.sh out-modect

# switch to motion monitor 7AM M-F
0 7 * *  1-5 /usr/bin/arc_zm_change_state.sh in-modect

## SAT-SUN RULES
#switch to motion recording 
0 0 * *  6-7 /usr/bin/arc_zm_change_state.sh out-modect

Note that instead of directly calling zmpkg, I am calling arc_zm_change_state.sh

Here is arc_zm_change_state.sh:

#!/bin/bash
runstate=`cat /usr/share/zoneminder/zm_run_state.txt`
if [ "$runstate" != "vacation" ];
then
	/usr/bin/arc_zm_log.pl "ARC:I've been requested to change to $1 - OK"
	/usr/bin/zmpkg.pl $1;
else
	/usr/bin/arc_zm_log.pl "ARC:You are in Vacation, Ignoring request to change to $1"
fi

Console.php

Finally, here is the modified console.php from /usr/share/zoneminder/skins/classic/views/console.php This change is not mandatory, but it shows the run state name which is always helpful. Changes marked with //ARC

https://github.com/pliablepixels/zmhacks/blob/master/console.php

So what this file is really doing is passing the call to zmpkg, except when you are on vacation.


What's this /usr/bin/arc_zm_log.pl ?

It's just a simple perl script I wrote that can print logs directly into ZoneMinder. I call this script from other non perl scripts (like bash shell scripts) to generate logs I can see in Zoneminder. https://github.com/pliablepixels/zmhacks/blob/master/arc_zm_log.pl

Summary

So let's recap:

  • We modified the zone minder init script to make sure a file called zm_run_state.txt exists and is writable by zmpkg in /usr/share/zoneminder
  • We modified /usr/bin/zmpkg.pl to make sure every time a state is changed, the name of the state is written to that file
  • We modified cron to change state via a wrapper script that invokes zmpkg only if zm_run_state.txt doesn't say 'vacation'
  • We modified Console.php to display the run state name in the web interface