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',
|
||||
`Score` smallint(5) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `EventId` (`EventId`),
|
||||
KEY `EventId_ZoneId` (`EventId`, `ZoneId`),
|
||||
KEY `MonitorId` (`MonitorId`),
|
||||
KEY `ZoneId` (`ZoneId`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
|
|
@ -3834,6 +3834,53 @@ our @options = (
|
|||
type => $types{string},
|
||||
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;
|
||||
|
|
|
@ -163,57 +163,81 @@ sub cameraReset {
|
|||
|
||||
sub moveConUp {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panspeed = 0; # purely moving vertically
|
||||
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 );
|
||||
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);
|
||||
}
|
||||
|
||||
sub moveConDown {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panspeed = 0; # purely moving vertically
|
||||
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 ) * -1 ;
|
||||
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);
|
||||
}
|
||||
|
||||
sub moveConLeft {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panspeed = $self->getParam( $params, 'panspeed', 30 ) * -1 ;
|
||||
my $tiltspeed = 0; # purely moving horizontally
|
||||
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);
|
||||
}
|
||||
|
||||
sub moveConRight {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panspeed = $self->getParam( $params, 'panspeed', 30 );
|
||||
my $tiltspeed = 0; # purely moving horizontally
|
||||
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);
|
||||
}
|
||||
|
||||
sub moveConUpRight {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panspeed = $self->getParam( $params, 'panspeed', 30 );
|
||||
my $tiltspeed = $self->getParam( $params, 'tiltspeed', 30 );
|
||||
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);
|
||||
}
|
||||
|
||||
sub moveConUpLeft {
|
||||
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');
|
||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=upleft';
|
||||
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||
$self->sendCmd($cmd);
|
||||
}
|
||||
|
||||
sub moveConDownRight {
|
||||
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');
|
||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=downright';
|
||||
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||
$self->sendCmd( $cmd );
|
||||
}
|
||||
|
||||
sub moveConDownLeft {
|
||||
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');
|
||||
my $cmd = '/axis-cgi/com/ptz.cgi?move=downleft';
|
||||
my $cmd = "/axis-cgi/com/ptz.cgi?continuouspantiltmove=$panspeed,$tiltspeed";
|
||||
$self->sendCmd($cmd);
|
||||
}
|
||||
|
||||
|
@ -248,7 +272,7 @@ sub moveRelDown {
|
|||
sub moveRelLeft {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $step = $self->getParam($params, 'panstep');
|
||||
my $step = abs($self->getParam($params, 'panstep'));
|
||||
Debug("Step Left $step");
|
||||
my $cmd = '/axis-cgi/com/ptz.cgi?rpan=-'.$step;
|
||||
$self->sendCmd($cmd);
|
||||
|
@ -276,8 +300,8 @@ sub moveRelUpRight {
|
|||
sub moveRelUpLeft {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panstep = $self->getParam($params, 'panstep');
|
||||
my $tiltstep = $self->getParam($params, 'tiltstep');
|
||||
my $panstep = abs($self->getParam($params, 'panstep'));
|
||||
my $tiltstep = abs($self->getParam($params, 'tiltstep'));
|
||||
Debug("Step Up/Left $tiltstep/$panstep");
|
||||
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep";
|
||||
$self->sendCmd($cmd);
|
||||
|
@ -303,6 +327,47 @@ sub moveRelDownLeft {
|
|||
$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 {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
|
@ -425,20 +490,15 @@ __END__
|
|||
|
||||
=head1 NAME
|
||||
|
||||
ZoneMinder::Database - Perl extension for blah blah blah
|
||||
ZoneMinder::Control::Axis - Zoneminder control for Axis Cameras using the V2 API
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ZoneMinder::Database;
|
||||
blah blah blah
|
||||
use ZoneMinder::Control::AxisV2 ; place this in /usr/share/perl5/ZoneMinder/Control
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Stub documentation for ZoneMinder, created by h2xs. It looks like the
|
||||
author of the extension was negligent enough to leave the stub
|
||||
unedited.
|
||||
|
||||
Blah blah blah.
|
||||
This module is an implementation of the Axis V2 API
|
||||
|
||||
=head2 EXPORT
|
||||
|
||||
|
@ -448,14 +508,8 @@ None by default.
|
|||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Mention other useful documentation such as the documentation of
|
||||
related modules or operating system documentation (such as man pages
|
||||
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.
|
||||
AXIS VAPIX Library Documentation; e.g.:
|
||||
https://www.axis.com/vapix-library/subjects/t10175981/section/t10036011/display
|
||||
|
||||
=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',
|
||||
'zmcontrol.pl',
|
||||
'zm_rtsp_server',
|
||||
'zmtelemetry.pl'
|
||||
'zmtelemetry.pl',
|
||||
'zmalarm-server.py'
|
||||
);
|
||||
|
||||
if ( $Config{ZM_OPT_USE_EVENTNOTIFICATION} ) {
|
||||
|
|
|
@ -288,6 +288,30 @@ if ( $command =~ /^(?:start|restart)$/ ) {
|
|||
if ( $Config{ZM_MIN_RTSP_PORT} ) {
|
||||
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 {
|
||||
$retval = 1;
|
||||
}
|
||||
|
|
|
@ -262,7 +262,9 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
return;
|
||||
}
|
||||
|
||||
int keyframe_interval = 1;
|
||||
int max_keyframe_interval = 1;
|
||||
int keyframe_interval_count = 1;
|
||||
|
||||
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
|
||||
if (!lp->trylock()) {
|
||||
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->keyframe) {
|
||||
Debug(4, "Have a video keyframe so setting next front to it. Keyframe interval so far is %d", keyframe_interval);
|
||||
keyframe_interval = 1;
|
||||
Debug(4, "Have a video keyframe so setting next front to it. Keyframe interval so far is %d", keyframe_interval_count);
|
||||
|
||||
if (max_keyframe_interval < keyframe_interval_count) max_keyframe_interval = keyframe_interval_count;
|
||||
keyframe_interval_count = 1;
|
||||
next_front = it;
|
||||
} else {
|
||||
keyframe_interval++;
|
||||
keyframe_interval_count++;
|
||||
}
|
||||
++video_packets_to_delete;
|
||||
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;
|
||||
} // 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"
|
||||
" the Max Image Buffer setting is lower than the keyframe interval. We"
|
||||
" 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",
|
||||
( *it == add_packet ),
|
||||
( next_front == pktQueue.begin() ),
|
||||
keyframe_interval
|
||||
keyframe_interval_count
|
||||
);
|
||||
if (next_front != pktQueue.begin()) {
|
||||
while (pktQueue.begin() != next_front) {
|
||||
|
@ -350,7 +354,7 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
void PacketQueue::stop() {
|
||||
deleting = true;
|
||||
condition.notify_all();
|
||||
for (const auto p : pktQueue) p->notify_all();
|
||||
for (const auto &p : pktQueue) p->notify_all();
|
||||
}
|
||||
|
||||
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
|
||||
-P, --password <password> - password combination of the given user
|
||||
-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
|
||||
|
||||
*/
|
||||
|
@ -137,7 +137,9 @@ void Usage(int status=-1) {
|
|||
" -U, --username <username> : When running in authenticated mode the username and\n"
|
||||
" -P, --password <password> : password combination of the given user\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 );
|
||||
|
||||
exit(status);
|
||||
|
@ -167,11 +169,12 @@ typedef enum {
|
|||
ZMU_SUSPEND = 0x00400000,
|
||||
ZMU_RESUME = 0x00800000,
|
||||
ZMU_LIST = 0x10000000,
|
||||
ZMU_TRIGGER = 0x20000000,
|
||||
} Function;
|
||||
|
||||
bool ValidateAccess(User *user, int mon_id, int function) {
|
||||
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 )
|
||||
allowed = false;
|
||||
}
|
||||
|
@ -246,6 +249,7 @@ int main(int argc, char *argv[]) {
|
|||
{"version", 1, nullptr, 'V'},
|
||||
{"help", 0, nullptr, 'h'},
|
||||
{"list", 0, nullptr, 'l'},
|
||||
{"xtrigger", 0, nullptr, 'x'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
|
@ -278,7 +282,7 @@ int main(int argc, char *argv[]) {
|
|||
while (1) {
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
|
@ -297,6 +301,9 @@ int main(int argc, char *argv[]) {
|
|||
case 's':
|
||||
function |= ZMU_STATE;
|
||||
break;
|
||||
case 'x':
|
||||
function |= ZMU_TRIGGER;
|
||||
break;
|
||||
case 'i':
|
||||
function |= ZMU_IMAGE;
|
||||
if (optarg)
|
||||
|
@ -523,6 +530,15 @@ int main(int argc, char *argv[]) {
|
|||
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 ) {
|
||||
SystemTimePoint timestamp = monitor->GetTimestamp(image_idx);
|
||||
if (verbose) {
|
||||
|
|
|
@ -150,9 +150,9 @@ require_once('database.php');
|
|||
require_once('logger.php');
|
||||
loadConfig();
|
||||
if (ZM_LOCALE_DEFAULT) {
|
||||
$dateFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
|
||||
$dateTimeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::LONG);
|
||||
$timeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::NONE, IntlDateFormatter::LONG);
|
||||
$dateFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::NONE,ZM_TIMEZONE);
|
||||
$dateTimeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::SHORT, IntlDateFormatter::LONG,ZM_TIMEZONE);
|
||||
$timeFormatter = new IntlDateFormatter(ZM_LOCALE_DEFAULT, IntlDateFormatter::NONE, IntlDateFormatter::LONG,ZM_TIMEZONE);
|
||||
}
|
||||
if (ZM_DATE_FORMAT_PATTERN) {
|
||||
$dateFormatter->setPattern(ZM_DATE_FORMAT_PATTERN);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
.ptzControls .controlsPanel .arrowControl {
|
||||
width: 60px;
|
||||
margin: 0 4px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ptzControls .controlsPanel .arrowControl button.longArrowBtn {
|
||||
|
@ -42,6 +43,7 @@
|
|||
width: 32px;
|
||||
height: 48px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,11 @@ function ajaxRequest(params) {
|
|||
}
|
||||
function processRows(rows) {
|
||||
$j.each(rows, function(ndx, row) {
|
||||
row.Message = decodeURIComponent(row.Message);
|
||||
try {
|
||||
row.Message = decodeURIComponent(row.Message);
|
||||
} catch (e) {
|
||||
// ignore errors
|
||||
}
|
||||
});
|
||||
return rows;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue