limit the numer of emails

Forum for questions and support relating to the 1.31.x releases only.
Locked
__simon
Posts: 3
Joined: Thu Oct 12, 2017 7:49 pm

limit the numer of emails

Post by __simon »

is there a way to limit the emails received to like one every 5 minutes or so?
zoneminder was active, and the cleaning lady came home and stayed cleaning for an hour or so. and i received like 100 mails, one for every event.
i like receiving an email when the alarm triggers, but if i get one email for the alarm, then silence for 10 minutes, and then an other mail that would be better than 1 email every minute.
is there a way to set zoneminder like that?
rockedge
Posts: 1173
Joined: Fri Apr 04, 2014 1:46 pm
Location: Connecticut,USA

Re: limit the numer of emails

Post by rockedge »

I use the filter option to execute a command. Which triggers a PERL script that sends only 1 email for a series of events in close time proximity. I just set a flag as the first event occurs and after a configurable time/event elapses the flag is unset. The PERL script uses the same email modules as ZM does. It would be nice to have that feature in ZM's Email Options.
__simon
Posts: 3
Joined: Thu Oct 12, 2017 7:49 pm

Re: limit the numer of emails

Post by __simon »

can you share the perl script?
VladSI
Posts: 8
Joined: Mon May 01, 2017 9:33 pm

Re: limit the numer of emails

Post by VladSI »

+1 on sharing the perl script. Would love to implement this myself.
rockedge
Posts: 1173
Joined: Fri Apr 04, 2014 1:46 pm
Location: Connecticut,USA

Re: limit the numer of emails

Post by rockedge »

I will have the script for you very soon....I am testing a small addition to the timing logic....then I will post both versions of the PERL daemon scripts. You will deactivate the email function in zoneminder. this will be used instead.
rockedge
Posts: 1173
Joined: Fri Apr 04, 2014 1:46 pm
Location: Connecticut,USA

Re: limit the numer of emails

Post by rockedge »

here is the first version. There are 3 scripts, 2 PERL one BASH. the first one is the daemon monitoring the events which when necessary calls sendx3.pl which send the email. In one_mail.pl set the monitor ID and time in seconds for email delay. Set Email addresses in sendx3.pl. one_mailx will start|stop|restart|reload|status the daemon one_mail.pl.
Note: tested using version 1.30.4 the daemon did not work with ZoneMinder with StorageAreas 1.31.9 (yet!)

turn off the send email function in Options->Email and turn off any background filters for sending the emails. Start the daemon which will monitor the database for new events and send the notification email.

set the monitor to check and the time is set to 15 minutes
my $camera_id = 1;
my $setseconds = 900;

Needed PERL modules are Switch and Proc::Daemon. I added these using cpanminus like this:

Code: Select all

#cpanm Proc::Daemon
or add the modules via the package manager as PERL libs.

To start the daemon :

Code: Select all

#service one_mailx start|stop|restart|reload|status
or:

Code: Select all

#/etc/init.d/one_mailx start|stop|restart|reload|status 
The daemon:
/usr/bin/one_mail.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 block outgoing event emails.
# $camera_id sets which camera the is being monitored.
# 
use strict;
use warnings;
use POSIX qw( strftime );
use autodie;
use Proc::Daemon;
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 $diff_flag = 0;

my $camera_id = 1;
my $setseconds = 900;

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

open (my $LOG, '>>', '/var/log/one_mail.log');
select $LOG;

$| = 1;

print localtime()." Started one_mail\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) {
					 	  $sttime = time;
					 	  $diff_flag = 0;					 
					 
					  }
#					  print "$time - $monitor_name:\t Idle!- $diff_flag\n";
					 } 
                case 1 { 
# 					  print "$time - $monitor_name:\t Prealarm!\n" 
					}
                case 2 { 
			   
				      if ($diff_flag == 0 and $monitor_id = $camera_id){
				        print "$time - $monitor_name:\t Send Alarm! $diff\n";
                        $diff_flag = 1;
                      my $output = `sendx3.pl $camera_id`;
				      }
					}
                case 3 { 
#					print "$time - $monitor_name:\t Alert!\n" 
					}
        }
}

}
print localtime()." Stopped one_mail\r\n";
close $LOG;
the daemon controller:
/etc/init.d/one_mailx

Code: Select all

#!/bin/sh
# Usage:  one_mailx start|stop|restart|reload|status
one_mail_PID=/tmp/one_mail.pid
function show_status {
	if [ ! -f $one_mail_PID ]; then
		echo -e "one_mail NOTRUNNING"
		exit 3
	fi
	
	PID=`cat ${one_mail_PID}`

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

	echo -e "one_mail RUNNING"
}

case "$1" in
    start)
	if [ -f /tmp/one_mail.pid ]; then
		PID=$(cat /tmp/one_mail.pid)
		kill -0 ${PID} &>/dev/null
		if [ $? = 0 ]; then
			echo "one_mail is already running."
		else
			/usr/bin/one_mail.pl
#			pidof one_mail.pl > /tmp/one_mail.pid
			pgrep -f one_mail.pl > /tmp/one_mail.pid
			PID=$(cat /tmp/one_mail.pid)
			kill -0 ${PID} &>/dev/null
			if [ $? = 0 ]; then
				echo "one_mail started successfully."
			else
				echo "Error starting one_mail"
			fi
		fi
	else
		/usr/bin/one_mail.pl
#		pidof one_mail.pl > /tmp/one_mail.pid
		pgrep -f one_mail.pl > /tmp/one_mail.pid
		PID=$(cat /tmp/one_mail.pid)
		kill -0 ${PID} &>/dev/null
		
		if [ $? = 0 ]; then
			echo "one_mail started successfully."
		else
			echo "Error starting one_mail"
		fi
        fi
        ;;
    stop)
	if [ -f /tmp/one_mail.pid ];then
		PID=$(cat /tmp/one_mail.pid)
		kill -0 ${PID} &>/dev/null
		rm -f /tmp/one_mail.pid
		if [ $? = 0 ]; then
			/bin/kill ${PID}
			kill -0 ${PID} &>/dev/null
			if [ $? = 0 ]; then
				echo "one_mail stopped successfully."
			else
				echo "Error stopping one_mail"
			fi
		else
			echo "one_mail is already stopped."
		fi
	else
		echo "one_mail 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
The third part sends the email. Here set the email addresses and the monitor ID.
/usr/bin/sendx3.pl

Code: Select all

#!/usr/bin/env perl

use strict;
use warnings;
use ZoneMinder;

use MIME::Lite;
use Net::SMTP;

my @events;
my $dbh = zmDbConnect();
my $sql = "SELECT * FROM Events WHERE MonitorId = ".$ARGV[0];
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() );

while ( my $events = $sth->fetchrow_hashref() ) {
    push( @events, $events );
}

### Adjust sender, recipient and your SMTP mailhost
my $from_address = 'from.address@some.server';
my $to_address = 'to.address@some.server'';
my $mail_host = 'some.server.host';

### Adjust subject and body message
my $subject = 'An event occured.';

my $evid = ($events[-1]->{Id});
my $evmonid = ($events[-1]->{MonitorId});
my $url = "http://zoneminder.server/zm/index.php?view=event&mode=stream&mid=$evmonid&eid=$evid/g \n";

#my $message_body = "Here's the attachment file(s) you wanted";
my $message_body = localtime()."--There was motion on camera $evmonid  $url";

my $msg;
### Create the multipart container
$msg = MIME::Lite->new (
  From => $from_address,
  To => $to_address,
  Subject => $subject,
  Type =>'multipart/mixed'
) or die "Error creating multipart container: $!\n";

### Add the text message part
$msg->attach (
  Type => 'TEXT',
  Data => $message_body
) or die "Error adding the text message part: $!\n";



### Send the Message
MIME::Lite->send('smtp', $mail_host, Timeout=>60);
$msg->send;
todo list:
add a configuration file for the adjustable values for email and the amount of seconds delay.
rockedge
Posts: 1173
Joined: Fri Apr 04, 2014 1:46 pm
Location: Connecticut,USA

Re: limit the numer of emails

Post by rockedge »

After upgrade to version 1.31.12 the error log has exploded! I can stop a local web cam from starting and crashing continuously and never showing a stream, also strange errors like the following.

Code: Select all

web_php		9856	WAR	Failed linking skins/classic/js/skin.js to cache/skin-1509894089.js	/usr/share/zoneminder/www/includes/functions.php
these error messages appear when running the one_mail.pl daemon AND also when using zm-alarm.pl example script.

Code: Select all

no memkey in zmMemInvalidate

Code: Select all

Can't read from mapped memory for monitor '1', gone away?
any ideas what I can do to get the webcam going again? The network cams work normally.
the scripts like the above that worked through and include 1.30.4 will not work in the present state with the 1.31.+
is this a authentication issue?
Locked