PERL daemon to test for 0 events in a set time period.

If you've made a patch to quick fix a bug or to add a new feature not yet in the main tree then post it here so others can try it out.
Post Reply
rockedge
Posts: 1173
Joined: Fri Apr 04, 2014 1:46 pm
Location: Connecticut,USA

PERL daemon to test for 0 events in a set time period.

Post by rockedge »

PERL program that runs as a daemon and checks zoneminder monitor status and if there are no 'Alarm' states after 90 minutes created by a selected monitor, an email will be sent.
set the email to your specs. and the timer is $setseconds = 5400 (90 minutes).
$camera_id sets which camera the no event timer is monitoring
Make sure all the PERL modules are present on your system.

The second program is the controller for the daemon.

/usr/bin/zmalarm5.pl

Code: Select all

#!/usr/bin/env perl

# While this script is running, it checks out the state of each monitor on the system.
# $setseconds is the time period in seconds to check for no Alarms.
# $camera_id sets which camera the no event timer is monitoring.
# 
use POSIX qw( strftime );
use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP ();
use Email::Simple ();
use Email::Simple::Creator ();
use autodie;
use Proc::Daemon;
use strict;
use warnings;
use ZoneMinder;
use Switch;

my @monitors;
my $dbh = zmDbConnect();
my $sql = "SELECT * FROM Monitors";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
my $sttime = time;
my $diff = 0;
my $continue = 1;
my $camera_id = 2;
my $setseconds = 5400;

Proc::Daemon::Init;
$SIG{TERM} = sub { $continue = 0 };

open (my $LOG, '>>', '/var/log/zm-alarm5.log');
select $LOG;

$| = 1;

print localtime()." Started zmalarm5\r\n";
while ($continue) {
while ( my $monitor = $sth->fetchrow_hashref() ) {
    push( @monitors, $monitor );
}

while ($continue) {
        foreach my $monitor (@monitors) {
                my $monitorState = zmGetMonitorState($monitor);
                printState($monitor->{Id}, $monitor->{Name}, $monitorState);
        }
        sleep 1;
}

sub printState {
        my ($monitor_id, $monitor_name, $state) = @_;
        my $time = localtime();
        switch ($state) {
                case 0 { 
					$diff = time - $sttime;
	                  if ($diff >= $setseconds and $monitor_id = $camera_id){
						   noeventemail();
                      }
					}
                case 1 { 
#					print "$time - $monitor_name:\t Prealarm!\n" 
					}
                case 2 { 
					print "$time - $monitor_name:\t Alarm!  $diff\n"; 
					if ($monitor_id = $camera_id ){$sttime = time;}
#                    $sttime = time;
					}
                case 3 { 
#					print "$time - $monitor_name:\t Alert!\n" 
					}
        }
}

sub noeventemail {
my ($monitor_id, $monitor_name, $state) = @_;
my $dt = strftime("%a %B %H:%M:%S", localtime($sttime));
my $time = localtime();
my $smtpserver = 'smtp.gmail.com';
my $smtpssl = 'SSL';
my $smtpport = 465;
my $smtpuser   = 'some.name@gmail.com';
my $smtppassword = 'somepassword';

my $transport = Email::Sender::Transport::SMTP->new({
  host => $smtpserver,
  ssl  => $smtpssl,
  port => $smtpport,
  sasl_username => $smtpuser,
  sasl_password => $smtppassword,
 });

my $email = Email::Simple->create(
  header => [
    To      => 'needs.a.name@gmail.com',
    From    => 'some.name@gmail.com',
    Subject => 'No Events occured!',
  ],
  body => "From $dt until $time Monitor- $camera_id: No Events occured during this time period.\n",
 );
 
 sendmail($email, { transport => $transport });

	$sttime = time;
	print "$time Monitor - $camera_id:\t Sent!\n";
}	
}
print localtime()." Stopped zmalarm5\r\n";
close $LOG;
controller for the daemon. /etc/init.d/zmalarm5x.sh

Code: Select all

#!/bin/sh
zmalarm5_PID=/tmp/zmalarm5.pid
function show_status {
	if [ ! -f $zmalarm5_PID ]; then
		echo -e "zmalarm5 NOTRUNNING"
		exit 3
	fi
	
	PID=`cat ${zmalarm5_PID}`

	if [ ! -d /proc/${PID} &>/dev/null ]; then
		echo -e "zmalarm5 NOTRUNNING"
		exit 1
	fi

	echo -e "zmalarm5  RUNNING"
}

case "$1" in
    start)
	if [ -f /tmp/zmalarm5.pid ]; then
		PID=$(cat /tmp/zmalarm5.pid)
		kill -0 ${PID} &>/dev/null
		if [ $? = 0 ]; then
			echo "zmalarm5 is already running."
		else
			/usr/bin/zmalarm5.pl
#			pidof zmalarm5.pl > /tmp/zmalarm5.pid
			pgrep -f zmalarm5.pl > /tmp/zmalarm5.pid
			PID=$(cat /tmp/zmalarm5.pid)
			kill -0 ${PID} &>/dev/null
			if [ $? = 0 ]; then
				echo "zmalarm5 started succesfully."
			else
				echo "Error starting zmalarm5"
			fi
		fi
	else
		/usr/bin/zmalarm5.pl
#		pidof zmalarm5.pl > /tmp/zmalarm5.pid
		pgrep -f zmalarm5.pl > /tmp/zmalarm5.pid
		PID=$(cat /tmp/zmalarm5.pid)
		kill -0 ${PID} &>/dev/null
		
		if [ $? = 0 ]; then
			echo "zmalarm5 started succesfully."
		else
			echo "Error starting zmalarm5"
		fi
        fi
        ;;
    stop)
	if [ -f /tmp/zmalarm5.pid ];then
		PID=$(cat /tmp/zmalarm5.pid)
		kill -0 ${PID} &>/dev/null
		rm -f /tmp/zmalarm5.pid
		if [ $? = 0 ]; then
			/bin/kill ${PID}
			kill -0 ${PID} &>/dev/null
			if [ $? = 0 ]; then
				echo "zmalarm5 stopped succesfully."
			else
				echo "Error stopping zmalarm5"
			fi
		else
			echo "zmalarm5 is already stopped."
		fi
	else
		echo "zmalarm5 is already stopped."
	fi
        ;;
    reload|restart)
        $0 stop
        $0 start
        ;;
    status)
		show_status
		;;
    *)
        echo "Usage: $0 start|stop|restart|reload|status"
        exit 1
esac
exit 0
Post Reply