Merge branch 'master' of github.com:ZoneMinder/zoneminder
commit
165ccf5820
|
@ -667,7 +667,7 @@ CREATE TABLE `Stats` (
|
||||||
`MaxY` smallint(5) unsigned NOT NULL default '0',
|
`MaxY` smallint(5) unsigned NOT NULL default '0',
|
||||||
`Score` smallint(5) unsigned NOT NULL default '0',
|
`Score` smallint(5) unsigned NOT NULL default '0',
|
||||||
PRIMARY KEY (`Id`),
|
PRIMARY KEY (`Id`),
|
||||||
KEY `EventId` (`EventId`),
|
KEY `EventId_ZoneId` (`EventId`, `ZoneId`),
|
||||||
KEY `MonitorId` (`MonitorId`),
|
KEY `MonitorId` (`MonitorId`),
|
||||||
KEY `ZoneId` (`ZoneId`)
|
KEY `ZoneId` (`ZoneId`)
|
||||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||||
|
|
|
@ -3834,6 +3834,53 @@ our @options = (
|
||||||
type => $types{string},
|
type => $types{string},
|
||||||
category => 'config',
|
category => 'config',
|
||||||
},
|
},
|
||||||
|
# Add options for Alarm Server
|
||||||
|
{
|
||||||
|
name => 'ZM_OPT_USE_ALARMSERVER',
|
||||||
|
default => 'no',
|
||||||
|
description => 'Enable NETSurveillance WEB Camera ALARM SERVER',
|
||||||
|
help => q`
|
||||||
|
Alarm Server that works with cameras that use Netsurveillance Web Server,
|
||||||
|
and has the Alarm Server option it receives alarms sent by this cameras
|
||||||
|
(once enabled), and pass to Zoneminder the events.
|
||||||
|
It requires pyzm installed, visit https://pyzm.readthedocs.io/en/latest/
|
||||||
|
for installation instructions.
|
||||||
|
`,
|
||||||
|
type => $types{boolean},
|
||||||
|
category => 'system',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'ZM_OPT_ALS_LOGENTRY',
|
||||||
|
default => 'no',
|
||||||
|
description => 'Makes ALARM SERVER create a log entry in ZoneMinder on Human Detected',
|
||||||
|
help => '',
|
||||||
|
type => $types{boolean},
|
||||||
|
category => 'system',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'ZM_OPT_ALS_ALARM',
|
||||||
|
default => 'no',
|
||||||
|
description => 'Send the Human Detected alarm from ALARM SERVER to ZoneMinder, It does not work along with OPT_ALS_TRIGGEREVENT',
|
||||||
|
help => '',
|
||||||
|
type => $types{boolean},
|
||||||
|
category => 'system',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'ZM_OPT_ALS_TRIGGEREVENT',
|
||||||
|
default => 'no',
|
||||||
|
description => 'Trigger an event on Human Detected alarm from ALARM SERVER to ZoneMinder. Requires the zmTrigger option Enabled',
|
||||||
|
help => '',
|
||||||
|
type => $types{boolean},
|
||||||
|
category => 'system',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'ZM_OPT_ALS_PORT',
|
||||||
|
default => '15002',
|
||||||
|
description => 'Port Number to receive alarms from Alarm Server',
|
||||||
|
help => '',
|
||||||
|
type => $types{integer},
|
||||||
|
category => 'system',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
our %options_hash = map { ( $_->{name}, $_ ) } @options;
|
our %options_hash = map { ( $_->{name}, $_ ) } @options;
|
||||||
|
|
|
@ -163,57 +163,81 @@ sub cameraReset {
|
||||||
|
|
||||||
sub moveConUp {
|
sub moveConUp {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = 0; # purely moving vertically
|
||||||
|
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 );
|
||||||
Debug('Move Up');
|
Debug('Move Up');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=up';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveConDown {
|
sub moveConDown {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = 0; # purely moving vertically
|
||||||
|
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 ) * -1 ;
|
||||||
Debug('Move Down');
|
Debug('Move Down');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=down';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveConLeft {
|
sub moveConLeft {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = $self->getParam( $params, 'panspeed', 30 ) * -1 ;
|
||||||
|
my $tiltspeed = 0; # purely moving horizontally
|
||||||
Debug('Move Left');
|
Debug('Move Left');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=left';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveConRight {
|
sub moveConRight {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = $self->getParam( $params, 'panspeed', 30 );
|
||||||
|
my $tiltspeed = 0; # purely moving horizontally
|
||||||
Debug('Move Right');
|
Debug('Move Right');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=right';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveConUpRight {
|
sub moveConUpRight {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = $self->getParam( $params, 'panspeed', 30 );
|
||||||
|
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 );
|
||||||
Debug('Move Up/Right');
|
Debug('Move Up/Right');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=upright';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveConUpLeft {
|
sub moveConUpLeft {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = $self->getParam( $params, 'panspeed', 30 ) * -1;
|
||||||
|
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 );
|
||||||
Debug('Move Up/Left');
|
Debug('Move Up/Left');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=upleft';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveConDownRight {
|
sub moveConDownRight {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = $self->getParam( $params, 'panspeed', 30 );
|
||||||
|
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 ) * -1;
|
||||||
Debug('Move Down/Right');
|
Debug('Move Down/Right');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=downright';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd( $cmd );
|
$self->sendCmd( $cmd );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveConDownLeft {
|
sub moveConDownLeft {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $panspeed = $self->getParam( $params, 'panspeed', 30 ) * -1;
|
||||||
|
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 ) * -1;
|
||||||
Debug('Move Down/Left');
|
Debug('Move Down/Left');
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=downleft';
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +272,7 @@ sub moveRelDown {
|
||||||
sub moveRelLeft {
|
sub moveRelLeft {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $step = $self->getParam($params, 'panstep');
|
my $step = abs($self->getParam($params, 'panstep'));
|
||||||
Debug("Step Left $step");
|
Debug("Step Left $step");
|
||||||
my $cmd = '/axis-cgi/com/ptz.cgi?rpan=-'.$step;
|
my $cmd = '/axis-cgi/com/ptz.cgi?rpan=-'.$step;
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
|
@ -276,8 +300,8 @@ sub moveRelUpRight {
|
||||||
sub moveRelUpLeft {
|
sub moveRelUpLeft {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $panstep = $self->getParam($params, 'panstep');
|
my $panstep = abs($self->getParam($params, 'panstep'));
|
||||||
my $tiltstep = $self->getParam($params, 'tiltstep');
|
my $tiltstep = abs($self->getParam($params, 'tiltstep'));
|
||||||
Debug("Step Up/Left $tiltstep/$panstep");
|
Debug("Step Up/Left $tiltstep/$panstep");
|
||||||
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep";
|
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep";
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
|
@ -303,6 +327,47 @@ sub moveRelDownLeft {
|
||||||
$self->sendCmd($cmd);
|
$self->sendCmd($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub zoomConTele {
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $speed = 20;
|
||||||
|
Debug('Zoom ConTele');
|
||||||
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouszoommove=$speed";
|
||||||
|
$self->sendCmd($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub zoomConWide {
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
#my $step = $self->getParam($params, 'step');
|
||||||
|
my $speed = -20;
|
||||||
|
Debug('Zoom ConWide');
|
||||||
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouszoommove=$speed";
|
||||||
|
$self->sendCmd($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub zoomStop {
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $speed = 0;
|
||||||
|
Debug('Zoom Stop');
|
||||||
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouszoommove=$speed";
|
||||||
|
$self->sendCmd($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveStop {
|
||||||
|
my $self = shift;
|
||||||
|
my $params = shift;
|
||||||
|
my $speed = 0;
|
||||||
|
Debug('Move Stop');
|
||||||
|
# we have to stop both pans and zooms
|
||||||
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$speed,$speed";
|
||||||
|
$self->sendCmd($cmd);
|
||||||
|
my $cmd = "/axis-cgi/com/ptz.cgi?continuouszoommove=$speed";
|
||||||
|
$self->sendCmd($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub zoomRelTele {
|
sub zoomRelTele {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
|
@ -425,20 +490,15 @@ __END__
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
ZoneMinder::Database - Perl extension for blah blah blah
|
ZoneMinder::Control::Axis - Zoneminder control for Axis Cameras using the V2 API
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
use ZoneMinder::Database;
|
use ZoneMinder::Control::AxisV2 ; place this in /usr/share/perl5/ZoneMinder/Control
|
||||||
blah blah blah
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
Stub documentation for ZoneMinder, created by h2xs. It looks like the
|
This module is an implementation of the Axis V2 API
|
||||||
author of the extension was negligent enough to leave the stub
|
|
||||||
unedited.
|
|
||||||
|
|
||||||
Blah blah blah.
|
|
||||||
|
|
||||||
=head2 EXPORT
|
=head2 EXPORT
|
||||||
|
|
||||||
|
@ -448,14 +508,8 @@ None by default.
|
||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
Mention other useful documentation such as the documentation of
|
AXIS VAPIX Library Documentation; e.g.:
|
||||||
related modules or operating system documentation (such as man pages
|
https://www.axis.com/vapix-library/subjects/t10175981/section/t10036011/display
|
||||||
in UNIX), or any relevant external documentation such as RFCs or
|
|
||||||
standards.
|
|
||||||
|
|
||||||
If you have a mailing list set up for your module, mention it here.
|
|
||||||
|
|
||||||
If you have a web site set up for your module, mention it here.
|
|
||||||
|
|
||||||
=head1 AUTHOR
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# ==========================================================================
|
||||||
|
#
|
||||||
|
# ZoneMinder Alarm Server Script for Netsurveillence Software cameras, $Date$, $Revision$
|
||||||
|
# Copyright (C) 2022
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# ==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Adds pyzm support
|
||||||
|
import pyzm.api as zmapi
|
||||||
|
import pyzm.ZMLog as zmlog
|
||||||
|
import pyzm.helpers.utils as utils
|
||||||
|
|
||||||
|
import os, sys, struct, json
|
||||||
|
from time import sleep
|
||||||
|
#import time
|
||||||
|
from socket import *
|
||||||
|
# from datetime import *
|
||||||
|
# telnet
|
||||||
|
from telnetlib import Telnet
|
||||||
|
# multi threading
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
def writezmlog(m,s):
|
||||||
|
zmlog.init()
|
||||||
|
zmlog.Info(m+s)
|
||||||
|
# zmlog.close()
|
||||||
|
|
||||||
|
def alarm_thread(m, monid,eventlenght):
|
||||||
|
import subprocess
|
||||||
|
print("Monitor " + str(monid)+" entered alarm_thread...")
|
||||||
|
result = subprocess.run(['zmu','-m', str(monid), '-s'] ,stdout=subprocess.PIPE)
|
||||||
|
if result.stdout.decode('utf-8') != '3\n':
|
||||||
|
print('Changing monitor '+ str(monid) + ' status to Alarm...')
|
||||||
|
m.arm()
|
||||||
|
sleep(eventlenght)
|
||||||
|
m.disarm()
|
||||||
|
else:
|
||||||
|
print('Monitor '+ str(monid) + ' already in status Alarm...')
|
||||||
|
print('Finishing thread...')
|
||||||
|
|
||||||
|
|
||||||
|
def event_thread(m_id,eventlenght):
|
||||||
|
import subprocess
|
||||||
|
print("Monitor " + str(m_id)+" entered event_thread...")
|
||||||
|
result = subprocess.run(['zmu','-m', str(m_id), '-x'] ,stdout=subprocess.PIPE)
|
||||||
|
if result.stdout.decode('utf-8') == '0\n':
|
||||||
|
print('Firing monitor '+ str(m_id) + ' trigger...')
|
||||||
|
telbuff = str(m_id) + '|on+'+str(eventlenght)+'|1|Human Motion Detected|'
|
||||||
|
with Telnet('localhost', 6802) as tn:
|
||||||
|
tn.write(telbuff.encode('ascii') + alarm_desc.encode('ascii') + b'\n')
|
||||||
|
tn.read_until(b'off')
|
||||||
|
else:
|
||||||
|
print('Monitor '+ str(m_id) + ' already triggered, doing nothing...')
|
||||||
|
print('Finishing thread...')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def tolog(s):
|
||||||
|
logfile = open(datetime.now().strftime('%Y_%m_%d_') + log, 'a+')
|
||||||
|
logfile.write(s)
|
||||||
|
logfile.close()
|
||||||
|
|
||||||
|
|
||||||
|
def GetIP(s):
|
||||||
|
return inet_ntoa(struct.pack('<I', int(s, 16)))
|
||||||
|
|
||||||
|
|
||||||
|
# config variables
|
||||||
|
eventlenght = 60
|
||||||
|
wrzmlog = 'n'
|
||||||
|
wrzmevent ='n'
|
||||||
|
rsealm = 'n'
|
||||||
|
port = '15002'
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
keys = ["--log=","-l=","--alarm=","-a=","--port=","-p=","--event=","-e="]
|
||||||
|
for i in range(1,len(sys.argv)):
|
||||||
|
for key in keys:
|
||||||
|
if sys.argv[i].find(key) == 0:
|
||||||
|
if key == "--log=" or key == "-l=":
|
||||||
|
wrzmlog=sys.argv[i][len(key):]
|
||||||
|
elif key == "--alarm=" or key == "-a=":
|
||||||
|
rsealm=sys.argv[i][len(key):]
|
||||||
|
elif key == "--port=" or key == "-p=":
|
||||||
|
port=sys.argv[i][len(key):]
|
||||||
|
elif key == "--event=" or key == "-e=":
|
||||||
|
wrzmevent=sys.argv[i][len(key):]
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
print('Usage: %s [--port|-p=<value> --log|-l=<y/n> --alarm|-a=<y/n> --event|-e=<y/n>]' % os.path.basename(sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print ('Create log entry: ', wrzmlog)
|
||||||
|
print ('Trigger event: ', wrzmlog)
|
||||||
|
print ('Raise Alarm: ', rsealm)
|
||||||
|
|
||||||
|
server = socket(AF_INET, SOCK_STREAM)
|
||||||
|
server.bind(('0.0.0.0', int(port)))
|
||||||
|
# server.settimeout(0.5)
|
||||||
|
server.listen(1)
|
||||||
|
|
||||||
|
log = "AlarmServer.log"
|
||||||
|
|
||||||
|
conf = utils.read_config('/etc/zm/secrets.ini')
|
||||||
|
api_options = {
|
||||||
|
'apiurl': utils.get(key='ZM_API_PORTAL', section='secrets', conf=conf),
|
||||||
|
'portalurl':utils.get(key='ZM_PORTAL', section='secrets', conf=conf),
|
||||||
|
'user': utils.get(key='ZM_USER', section='secrets', conf=conf),
|
||||||
|
#'disable_ssl_cert_check': True
|
||||||
|
}
|
||||||
|
|
||||||
|
zmapi = zmapi.ZMApi(options=api_options)
|
||||||
|
|
||||||
|
# importing the regex to get ip out of path
|
||||||
|
import re
|
||||||
|
#define regex pattern for IP addresses
|
||||||
|
pattern =re.compile('''((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)''')
|
||||||
|
# store the response of URL
|
||||||
|
#process monitors create dict of monitors
|
||||||
|
list_monit = {}
|
||||||
|
zm_monitors = zmapi.monitors()
|
||||||
|
for m in zm_monitors.list():
|
||||||
|
ip_v4=pattern.search(m.get()['Path'])
|
||||||
|
list_monit[ip_v4.group()]=m.id()
|
||||||
|
|
||||||
|
writezmlog('Listening on port: '+port,' AlarmServer.py')
|
||||||
|
print ('Listening on port: '+port)
|
||||||
|
#run Alarm Server
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
conn, addr = server.accept()
|
||||||
|
head, version, session, sequence_number, msgid, len_data = struct.unpack(
|
||||||
|
'BB2xII2xHI', conn.recv(20)
|
||||||
|
)
|
||||||
|
sleep(0.1) # Just for recive whole packet
|
||||||
|
data = conn.recv(len_data)
|
||||||
|
conn.close()
|
||||||
|
# make the json a Dictionary
|
||||||
|
reply = json.loads(data)
|
||||||
|
# get ip
|
||||||
|
ip_v4 = GetIP(reply.get('Address'))
|
||||||
|
# get alarm_event_desc
|
||||||
|
alarm_desc = reply.get('Event')
|
||||||
|
# print(datetime.now().strftime('[%Y-%m-%d %H:%M:%S]>>>'))
|
||||||
|
print ('Ip Address: ',ip_v4)
|
||||||
|
print ("Alarm Description: ", alarm_desc)
|
||||||
|
print('<<<')
|
||||||
|
# tolog(repr(data) + "\r\n")
|
||||||
|
if alarm_desc == 'HumanDetect':
|
||||||
|
if wrzmlog == 'y':
|
||||||
|
writezmlog(alarm_desc+' in monitor ',str(list_monit[ip_v4]))
|
||||||
|
if rsealm == 'y':
|
||||||
|
print ("Triggering Alarm...")
|
||||||
|
mthread = Thread(target=alarm_thread, args=(zm_monitors.find(list_monit[ip_v4]),list_monit[ip_v4],eventlenght))
|
||||||
|
mthread.start()
|
||||||
|
elif wrzmevent == 'y':
|
||||||
|
print ("Triggering Event Rec on zmtrigger...")
|
||||||
|
mthread = Thread(target=event_thread, args=(list_monit[ip_v4],eventlenght))
|
||||||
|
mthread.start()
|
||||||
|
except (KeyboardInterrupt, SystemExit):
|
||||||
|
break
|
||||||
|
server.close()
|
||||||
|
# needs to be closed again... otherwise it will crash on exit.
|
||||||
|
zmlog.close()
|
||||||
|
sys.exit(1)
|
|
@ -102,7 +102,8 @@ my @daemons = (
|
||||||
'zmtrack.pl',
|
'zmtrack.pl',
|
||||||
'zmcontrol.pl',
|
'zmcontrol.pl',
|
||||||
'zm_rtsp_server',
|
'zm_rtsp_server',
|
||||||
'zmtelemetry.pl'
|
'zmtelemetry.pl',
|
||||||
|
'zmalarm-server.py'
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $Config{ZM_OPT_USE_EVENTNOTIFICATION} ) {
|
if ( $Config{ZM_OPT_USE_EVENTNOTIFICATION} ) {
|
||||||
|
|
|
@ -288,6 +288,30 @@ if ( $command =~ /^(?:start|restart)$/ ) {
|
||||||
if ( $Config{ZM_MIN_RTSP_PORT} ) {
|
if ( $Config{ZM_MIN_RTSP_PORT} ) {
|
||||||
runCommand('zmdc.pl start zm_rtsp_server');
|
runCommand('zmdc.pl start zm_rtsp_server');
|
||||||
}
|
}
|
||||||
|
# run and pass parameters to AlarmServer.py
|
||||||
|
if ($Config{ZM_OPT_USE_ALARMSERVER} ) {
|
||||||
|
my $cmd='zmdc.pl start zmalarm-server.py '. $Config{ZM_OPT_ALS_PORT};
|
||||||
|
if ($Config{ZM_OPT_ALS_LOGENTRY} ) {
|
||||||
|
$cmd = $cmd . ' --log=y';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$cmd = $cmd . ' --log=n';
|
||||||
|
}
|
||||||
|
if ($Config{ZM_OPT_ALS_TRIGGEREVENT} ) {
|
||||||
|
$cmd = $cmd . ' --event=y';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$cmd = $cmd . ' --event=n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Config{ZM_OPT_ALS_ALARM} ) {
|
||||||
|
$cmd = $cmd . ' --alarm=y';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$cmd = $cmd . ' --alarm=n';
|
||||||
|
}
|
||||||
|
runCommand($cmd);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$retval = 1;
|
$retval = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,9 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int keyframe_interval = 1;
|
int max_keyframe_interval = 1;
|
||||||
|
int keyframe_interval_count = 1;
|
||||||
|
|
||||||
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
|
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
|
||||||
if (!lp->trylock()) {
|
if (!lp->trylock()) {
|
||||||
Debug(4, "Failed getting lock on first packet");
|
Debug(4, "Failed getting lock on first packet");
|
||||||
|
@ -297,11 +299,13 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
||||||
|
|
||||||
if (zm_packet->packet->stream_index == video_stream_id) {
|
if (zm_packet->packet->stream_index == video_stream_id) {
|
||||||
if (zm_packet->keyframe) {
|
if (zm_packet->keyframe) {
|
||||||
Debug(4, "Have a video keyframe so setting next front to it. Keyframe interval so far is %d", keyframe_interval);
|
Debug(4, "Have a video keyframe so setting next front to it. Keyframe interval so far is %d", keyframe_interval_count);
|
||||||
keyframe_interval = 1;
|
|
||||||
|
if (max_keyframe_interval < keyframe_interval_count) max_keyframe_interval = keyframe_interval_count;
|
||||||
|
keyframe_interval_count = 1;
|
||||||
next_front = it;
|
next_front = it;
|
||||||
} else {
|
} else {
|
||||||
keyframe_interval++;
|
keyframe_interval_count++;
|
||||||
}
|
}
|
||||||
++video_packets_to_delete;
|
++video_packets_to_delete;
|
||||||
if (packet_counts[video_stream_id] - video_packets_to_delete <= pre_event_video_packet_count + tail_count) {
|
if (packet_counts[video_stream_id] - video_packets_to_delete <= pre_event_video_packet_count + tail_count) {
|
||||||
|
@ -313,7 +317,7 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
||||||
++it;
|
++it;
|
||||||
} // end while
|
} // end while
|
||||||
|
|
||||||
if ((keyframe_interval == 1) and max_video_packet_count) {
|
if ((max_keyframe_interval == 1) and max_video_packet_count) {
|
||||||
Warning("Did not find a second keyframe in the packet queue. It may be that"
|
Warning("Did not find a second keyframe in the packet queue. It may be that"
|
||||||
" the Max Image Buffer setting is lower than the keyframe interval. We"
|
" the Max Image Buffer setting is lower than the keyframe interval. We"
|
||||||
" need it to be greater than the keyframe interval.");
|
" need it to be greater than the keyframe interval.");
|
||||||
|
@ -321,7 +325,7 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
||||||
Debug(1, "Resulting it pointing at latest packet? %d, next front points to begin? %d, Keyframe interval %d",
|
Debug(1, "Resulting it pointing at latest packet? %d, next front points to begin? %d, Keyframe interval %d",
|
||||||
( *it == add_packet ),
|
( *it == add_packet ),
|
||||||
( next_front == pktQueue.begin() ),
|
( next_front == pktQueue.begin() ),
|
||||||
keyframe_interval
|
keyframe_interval_count
|
||||||
);
|
);
|
||||||
if (next_front != pktQueue.begin()) {
|
if (next_front != pktQueue.begin()) {
|
||||||
while (pktQueue.begin() != next_front) {
|
while (pktQueue.begin() != next_front) {
|
||||||
|
@ -350,7 +354,7 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
||||||
void PacketQueue::stop() {
|
void PacketQueue::stop() {
|
||||||
deleting = true;
|
deleting = true;
|
||||||
condition.notify_all();
|
condition.notify_all();
|
||||||
for (const auto p : pktQueue) p->notify_all();
|
for (const auto &p : pktQueue) p->notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketQueue::clear() {
|
void PacketQueue::clear() {
|
||||||
|
|
24
src/zmu.cpp
24
src/zmu.cpp
|
@ -81,7 +81,7 @@ Options for use with monitors:
|
||||||
-U, --username <username> - When running in authenticated mode the username and
|
-U, --username <username> - When running in authenticated mode the username and
|
||||||
-P, --password <password> - password combination of the given user
|
-P, --password <password> - password combination of the given user
|
||||||
-A, --auth <authentication> - Pass authentication hash string instead of user details
|
-A, --auth <authentication> - Pass authentication hash string instead of user details
|
||||||
|
-x, --xtrigger - Output the current monitor trigger state, 0 = not triggered, 1 = triggered
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -137,7 +137,9 @@ void Usage(int status=-1) {
|
||||||
" -U, --username <username> : When running in authenticated mode the username and\n"
|
" -U, --username <username> : When running in authenticated mode the username and\n"
|
||||||
" -P, --password <password> : password combination of the given user\n"
|
" -P, --password <password> : password combination of the given user\n"
|
||||||
" -A, --auth <authentication> : Pass authentication hash string instead of user details\n"
|
" -A, --auth <authentication> : Pass authentication hash string instead of user details\n"
|
||||||
" -T, --token <token> : Pass JWT token string instead of user details\n"
|
" -T, --token <token> : Pass JWT token string instead of user details\n"
|
||||||
|
" -x, --xtrigger : Output the current monitor trigger state, 0 = not triggered, 1 = triggered\n"
|
||||||
|
|
||||||
"", stderr );
|
"", stderr );
|
||||||
|
|
||||||
exit(status);
|
exit(status);
|
||||||
|
@ -167,11 +169,12 @@ typedef enum {
|
||||||
ZMU_SUSPEND = 0x00400000,
|
ZMU_SUSPEND = 0x00400000,
|
||||||
ZMU_RESUME = 0x00800000,
|
ZMU_RESUME = 0x00800000,
|
||||||
ZMU_LIST = 0x10000000,
|
ZMU_LIST = 0x10000000,
|
||||||
|
ZMU_TRIGGER = 0x20000000,
|
||||||
} Function;
|
} Function;
|
||||||
|
|
||||||
bool ValidateAccess(User *user, int mon_id, int function) {
|
bool ValidateAccess(User *user, int mon_id, int function) {
|
||||||
bool allowed = true;
|
bool allowed = true;
|
||||||
if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) ) {
|
if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS|ZMU_TRIGGER) ) {
|
||||||
if ( user->getStream() < User::PERM_VIEW )
|
if ( user->getStream() < User::PERM_VIEW )
|
||||||
allowed = false;
|
allowed = false;
|
||||||
}
|
}
|
||||||
|
@ -246,6 +249,7 @@ int main(int argc, char *argv[]) {
|
||||||
{"version", 1, nullptr, 'V'},
|
{"version", 1, nullptr, 'V'},
|
||||||
{"help", 0, nullptr, 'h'},
|
{"help", 0, nullptr, 'h'},
|
||||||
{"list", 0, nullptr, 'l'},
|
{"list", 0, nullptr, 'l'},
|
||||||
|
{"xtrigger", 0, nullptr, 'x'},
|
||||||
{nullptr, 0, nullptr, 0}
|
{nullptr, 0, nullptr, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -278,7 +282,7 @@ int main(int argc, char *argv[]) {
|
||||||
while (1) {
|
while (1) {
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
|
||||||
int c = getopt_long(argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::RWU:P:A:V:T:", long_options, &option_index);
|
int c = getopt_long(argc, argv, "d:m:vsEDLurweix::S:t::fz::ancqhlB::C::H::O::RWU:P:A:V:T:", long_options, &option_index);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -297,6 +301,9 @@ int main(int argc, char *argv[]) {
|
||||||
case 's':
|
case 's':
|
||||||
function |= ZMU_STATE;
|
function |= ZMU_STATE;
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
function |= ZMU_TRIGGER;
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
function |= ZMU_IMAGE;
|
function |= ZMU_IMAGE;
|
||||||
if (optarg)
|
if (optarg)
|
||||||
|
@ -523,6 +530,15 @@ int main(int argc, char *argv[]) {
|
||||||
have_output = true;
|
have_output = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( function & ZMU_TRIGGER ) {
|
||||||
|
int trgstate = monitor->GetTriggerState();
|
||||||
|
if ( verbose ) {
|
||||||
|
printf("Current Triggered state: %s\n", trgstate==0?"Not Triggered":(trgstate==1?"Triggered":"NA"));
|
||||||
|
} else {
|
||||||
|
printf("%d", trgstate);
|
||||||
|
have_output = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if ( function & ZMU_TIME ) {
|
if ( function & ZMU_TIME ) {
|
||||||
SystemTimePoint timestamp = monitor->GetTimestamp(image_idx);
|
SystemTimePoint timestamp = monitor->GetTimestamp(image_idx);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
|
|
@ -150,9 +150,9 @@ require_once('database.php');
|
||||||
require_once('logger.php');
|
require_once('logger.php');
|
||||||
loadConfig();
|
loadConfig();
|
||||||
if (ZM_LOCALE_DEFAULT) {
|
if (ZM_LOCALE_DEFAULT) {
|
||||||
$dateFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
|
$dateFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::NONE,ZM_TIMEZONE);
|
||||||
$dateTimeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::LONG);
|
$dateTimeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::LONG,ZM_TIMEZONE);
|
||||||
$timeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::NONE, IntlDateFormatter::LONG);
|
$timeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::NONE, IntlDateFormatter::LONG,ZM_TIMEZONE);
|
||||||
}
|
}
|
||||||
if (ZM_DATE_FORMAT_PATTERN) {
|
if (ZM_DATE_FORMAT_PATTERN) {
|
||||||
$dateFormatter->setPattern(ZM_DATE_FORMAT_PATTERN);
|
$dateFormatter->setPattern(ZM_DATE_FORMAT_PATTERN);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
.ptzControls .controlsPanel .arrowControl {
|
.ptzControls .controlsPanel .arrowControl {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
margin: 0 4px;
|
margin: 0 4px;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ptzControls .controlsPanel .arrowControl button.longArrowBtn {
|
.ptzControls .controlsPanel .arrowControl button.longArrowBtn {
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,11 @@ function ajaxRequest(params) {
|
||||||
}
|
}
|
||||||
function processRows(rows) {
|
function processRows(rows) {
|
||||||
$j.each(rows, function(ndx, row) {
|
$j.each(rows, function(ndx, row) {
|
||||||
row.Message = decodeURIComponent(row.Message);
|
try {
|
||||||
|
row.Message = decodeURIComponent(row.Message);
|
||||||
|
} catch (e) {
|
||||||
|
// ignore errors
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue