Merge branch 'storageareas' of github.com:connortechnology/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2018-05-02 14:13:11 -07:00
commit 29140a3012
4 changed files with 233 additions and 315 deletions

View File

@ -55,134 +55,131 @@ my $DefaultFocusSpeed = 50; # Should be between 1 and 100
my $DefaultIrisSpeed = 50; # Should be between 1 and 100 my $DefaultIrisSpeed = 50; # Should be between 1 and 100
sub open { sub open {
my $self = shift; my $self = shift;
$self->loadMonitor(); $self->loadMonitor();
# #
# Create a UserAgent for the requests # Create a UserAgent for the requests
# #
$self->{UA} = LWP::UserAgent->new(); $self->{UA} = LWP::UserAgent->new();
$self->{UA}->cookie_jar( {} ); $self->{UA}->cookie_jar( {} );
# #
# Extract the username/password host/port from ControlAddress # Extract the username/password host/port from ControlAddress
# #
my ($user,$pass,$host,$port); my ($user,$pass,$host,$port);
if( $self->{Monitor}{ControlAddress} =~ /^([^:]+):([^@]+)@(.+)/ ) { # user:pass@host... if ( $self->{Monitor}{ControlAddress} =~ /^([^:]+):([^@]+)@(.+)/ ) { # user:pass@host...
$user = $1; $user = $1;
$pass = $2; $pass = $2;
$host = $3; $host = $3;
} } elsif ( $self->{Monitor}{ControlAddress} =~ /^([^@]+)@(.+)/ ) { # user@host...
elsif( $self->{Monitor}{ControlAddress} =~ /^([^@]+)@(.+)/ ) { # user@host... $user = $1;
$user = $1; $host = $2;
$host = $2; } else { # Just a host
} $host = $self->{Monitor}{ControlAddress};
else { # Just a host }
$host = $self->{Monitor}{ControlAddress}; # Check if it is a host and port or just a host
} if ( $host =~ /([^:]+):(.+)/ ) {
# Check if it is a host and port or just a host $host = $1;
if( $host =~ /([^:]+):(.+)/ ) { $port = $2;
$host = $1; } else {
$port = $2; $port = 80;
} }
else { # Save the credentials
$port = 80; if ( defined($user) ) {
} $self->{UA}->credentials("$host:$port", $self->{Monitor}{ControlDevice}, $user, $pass);
# Save the credentials }
if( defined($user) ) { # Save the base url
$self->{UA}->credentials( "$host:$port", $self->{Monitor}{ControlDevice}, $user, $pass ); $self->{BaseURL} = "http://$host:$port";
}
# Save the base url
$self->{BaseURL} = "http://$host:$port";
} }
sub PutCmd { sub PutCmd {
my $self = shift; my $self = shift;
my $cmd = shift; my $cmd = shift;
my $content = shift; my $content = shift;
my $req = HTTP::Request->new(PUT => "$self->{BaseURL}/$cmd"); my $req = HTTP::Request->new(PUT => "$self->{BaseURL}/$cmd");
if(defined($content)) { if ( defined($content) ) {
$req->content_type("application/x-www-form-urlencoded; charset=UTF-8"); $req->content_type("application/x-www-form-urlencoded; charset=UTF-8");
$req->content('<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $content); $req->content('<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $content);
} }
my $res = $self->{UA}->request($req); my $res = $self->{UA}->request($req);
unless( $res->is_success ) { unless( $res->is_success ) {
# #
# The camera timeouts connections at short intervals. When this # The camera timeouts connections at short intervals. When this
# happens the user agent connects again and uses the same auth tokens. # happens the user agent connects again and uses the same auth tokens.
# The camera rejects this and asks for another token but the UserAgent # The camera rejects this and asks for another token but the UserAgent
# just gives up. Because of this I try the request again and it should # just gives up. Because of this I try the request again and it should
# succeed the second time if the credentials are correct. # succeed the second time if the credentials are correct.
# #
if($res->code == 401) { if ( $res->code == 401 ) {
$res = $self->{UA}->request($req); $res = $self->{UA}->request($req);
unless( $res->is_success ) { unless( $res->is_success ) {
# #
# It has failed authentication. The odds are # It has failed authentication. The odds are
# that the user has set some paramater incorrectly # that the user has set some parameter incorrectly
# so check the realm against the ControlDevice # so check the realm against the ControlDevice
# entry and send a message if different # entry and send a message if different
# #
my $auth = $res->headers->www_authenticate; my $auth = $res->headers->www_authenticate;
foreach (split(/\s*,\s*/,$auth)) { foreach (split(/\s*,\s*/,$auth)) {
if( $_ =~ /^realm\s*=\s*"([^"]+)"/i ) { if ( $_ =~ /^realm\s*=\s*"([^"]+)"/i ) {
if( $self->{Monitor}{ControlDevice} ne $1 ) { if ( $self->{Monitor}{ControlDevice} ne $1 ) {
Info "Control Device appears to be incorrect."; Warning("Control Device appears to be incorrect.
Info "Control Device should be set to \"$1\"."; Control Device should be set to \"$1\".
Info "Control Device currently set to \"$self->{Monitor}{ControlDevice}\"."; Control Device currently set to \"$self->{Monitor}{ControlDevice}\".");
}
} }
} }
#
# Check for username/password
#
if( $self->{Monitor}{ControlAddress} =~ /.+:(.+)@.+/ ) {
Info "Check username/password is correct";
} elsif ( $self->{Monitor}{ControlAddress} =~ /^[^:]+@.+/ ) {
Info "No password in Control Address. Should there be one?";
} elsif ( $self->{Monitor}{ControlAddress} =~ /^:.+@.+/ ) {
Info "Password but no username in Control Address.";
} else {
Info "Missing username and password in Control Address.";
}
Fatal $res->status_line;
} }
#
# Check for username/password
#
if ( $self->{Monitor}{ControlAddress} =~ /.+:(.+)@.+/ ) {
Info("Check username/password is correct");
} elsif ( $self->{Monitor}{ControlAddress} =~ /^[^:]+@.+/ ) {
Info("No password in Control Address. Should there be one?");
} elsif ( $self->{Monitor}{ControlAddress} =~ /^:.+@.+/ ) {
Info("Password but no username in Control Address.");
} else {
Info("Missing username and password in Control Address.");
}
Fatal($res->status_line);
} }
else { } else {
Fatal $res->status_line; Fatal($res->status_line);
}
} }
} } # end unless res->is_success
} # end sub putCmd
# #
# The move continuous functions all call moveVector # The move continuous functions all call moveVector
# with the direction to move in. This includes zoom # with the direction to move in. This includes zoom
# #
sub moveVector { sub moveVector {
my $self = shift; my $self = shift;
my $pandirection = shift; my $pandirection = shift;
my $tiltdirection = shift; my $tiltdirection = shift;
my $zoomdirection = shift; my $zoomdirection = shift;
my $params = shift; my $params = shift;
my $command; # The ISAPI/PTZ command my $command; # The ISAPI/PTZ command
# Calculate autostop time # Calculate autostop time
my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout};
# Change from microseconds to milliseconds # Change from microseconds to milliseconds
$duration = int($duration/1000); $duration = int($duration/1000);
my $momentxml; my $momentxml;
if( $duration ) { if( $duration ) {
$momentxml = "<Momentary><duration>$duration</duration></Momentary>"; $momentxml = "<Momentary><duration>$duration</duration></Momentary>";
$command = "ISAPI/PTZCtrl/channels/$ChannelID/momentary"; $command = "ISAPI/PTZCtrl/channels/$ChannelID/momentary";
} }
else { else {
$momentxml = ""; $momentxml = "";
$command = "ISAPI/PTZCtrl/channels/$ChannelID/continuous"; $command = "ISAPI/PTZCtrl/channels/$ChannelID/continuous";
} }
# Calculate movement speeds # Calculate movement speeds
my $x = $pandirection * $self->getParam( $params, 'panspeed', 0 ); my $x = $pandirection * $self->getParam( $params, 'panspeed', 0 );
my $y = $tiltdirection * $self->getParam( $params, 'tiltspeed', 0 ); my $y = $tiltdirection * $self->getParam( $params, 'tiltspeed', 0 );
my $z = $zoomdirection * $self->getParam( $params, 'speed', 0 ); my $z = $zoomdirection * $self->getParam( $params, 'speed', 0 );
# Create the XML # Create the XML
my $xml = "<PTZData><pan>$x</pan><tilt>$y</tilt><zoom>$z</zoom>$momentxml</PTZData>"; my $xml = "<PTZData><pan>$x</pan><tilt>$y</tilt><zoom>$z</zoom>$momentxml</PTZData>";
# Send it to the camera # Send it to the camera
$self->PutCmd($command,$xml); $self->PutCmd($command,$xml);
} }
sub moveStop { $_[0]->moveVector( 0, 0, 0, splice(@_,1)); } sub moveStop { $_[0]->moveVector( 0, 0, 0, splice(@_,1)); }
sub moveConUp { $_[0]->moveVector( 0, 1, 0, splice(@_,1)); } sub moveConUp { $_[0]->moveVector( 0, 1, 0, splice(@_,1)); }
@ -199,191 +196,191 @@ sub zoomConWide { $_[0]->moveVector( 0, 0,-1, splice(@_,1)); }
# Presets including Home set and clear # Presets including Home set and clear
# #
sub presetGoto { sub presetGoto {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam($params,'preset'); my $preset = $self->getParam($params,'preset');
$self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/presets/$preset/goto"); $self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/presets/$preset/goto");
} }
sub presetSet { sub presetSet {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam($params,'preset'); my $preset = $self->getParam($params,'preset');
my $xml = "<PTZPreset><id>$preset</id></PTZPreset>"; my $xml = "<PTZPreset><id>$preset</id></PTZPreset>";
$self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/presets/$preset",$xml); $self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/presets/$preset",$xml);
} }
sub presetHome { sub presetHome {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
$self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/homeposition/goto"); $self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/homeposition/goto");
} }
# #
# Focus controls all call Focus with a +/- speed # Focus controls all call Focus with a +/- speed
# #
sub Focus { sub Focus {
my $self = shift; my $self = shift;
my $speed = shift; my $speed = shift;
my $xml = "<FocusData><focus>$speed</focus></FocusData>"; my $xml = "<FocusData><focus>$speed</focus></FocusData>";
$self->PutCmd("ISAPI/System/Video/inputs/channels/$ChannelID/focus",$xml); $self->PutCmd("ISAPI/System/Video/inputs/channels/$ChannelID/focus",$xml);
} }
sub focusConNear { sub focusConNear {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Calculate autostop time # Calculate autostop time
my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout};
# Get the focus speed # Get the focus speed
my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed );
$self->Focus(-$speed); $self->Focus(-$speed);
if($duration) { if($duration) {
usleep($duration); usleep($duration);
$self->moveStop($params); $self->moveStop($params);
} }
} }
sub Near { sub Near {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
$self->Focus(-$DefaultFocusSpeed); $self->Focus(-$DefaultFocusSpeed);
} }
sub focusAbsNear { sub focusAbsNear {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the focus speed # Get the focus speed
my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed );
$self->Focus(-$speed); $self->Focus(-$speed);
} }
sub focusRelNear { sub focusRelNear {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the focus speed # Get the focus speed
my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed );
$self->Focus(-$speed); $self->Focus(-$speed);
} }
sub focusConFar { sub focusConFar {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Calculate autostop time # Calculate autostop time
my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout};
# Get the focus speed # Get the focus speed
my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed );
$self->Focus($speed); $self->Focus($speed);
if($duration) { if($duration) {
usleep($duration); usleep($duration);
$self->moveStop($params); $self->moveStop($params);
} }
} }
sub Far { sub Far {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
$self->Focus($DefaultFocusSpeed); $self->Focus($DefaultFocusSpeed);
} }
sub focusAbsFar { sub focusAbsFar {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the focus speed # Get the focus speed
my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed );
$self->Focus($speed); $self->Focus($speed);
} }
sub focusRelFar { sub focusRelFar {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the focus speed # Get the focus speed
my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed );
$self->Focus($speed); $self->Focus($speed);
} }
# #
# Iris controls all call Iris with a +/- speed # Iris controls all call Iris with a +/- speed
# #
sub Iris { sub Iris {
my $self = shift; my $self = shift;
my $speed = shift; my $speed = shift;
my $xml = "<IrisData><iris>$speed</iris></IrisData>"; my $xml = "<IrisData><iris>$speed</iris></IrisData>";
$self->PutCmd("ISAPI/System/Video/inputs/channels/$ChannelID/iris",$xml); $self->PutCmd("ISAPI/System/Video/inputs/channels/$ChannelID/iris",$xml);
} }
sub irisConClose { sub irisConClose {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Calculate autostop time # Calculate autostop time
my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout};
# Get the iris speed # Get the iris speed
my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed );
$self->Iris(-$speed); $self->Iris(-$speed);
if($duration) { if($duration) {
usleep($duration); usleep($duration);
$self->moveStop($params); $self->moveStop($params);
} }
} }
sub Close { sub Close {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
$self->Iris(-$DefaultIrisSpeed); $self->Iris(-$DefaultIrisSpeed);
} }
sub irisAbsClose { sub irisAbsClose {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the iris speed # Get the iris speed
my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed );
$self->Iris(-$speed); $self->Iris(-$speed);
} }
sub irisRelClose { sub irisRelClose {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the iris speed # Get the iris speed
my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed );
$self->Iris(-$speed); $self->Iris(-$speed);
} }
sub irisConOpen { sub irisConOpen {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Calculate autostop time # Calculate autostop time
my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout};
# Get the iris speed # Get the iris speed
my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed );
$self->Iris($speed); $self->Iris($speed);
if($duration) { if($duration) {
usleep($duration); usleep($duration);
$self->moveStop($params); $self->moveStop($params);
} }
} }
sub Open { sub Open {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
$self->Iris($DefaultIrisSpeed); $self->Iris($DefaultIrisSpeed);
} }
sub irisAbsOpen { sub irisAbsOpen {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the iris speed # Get the iris speed
my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed );
$self->Iris($speed); $self->Iris($speed);
} }
sub irisRelOpen { sub irisRelOpen {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
# Get the iris speed # Get the iris speed
my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed );
$self->Iris($speed); $self->Iris($speed);
} }
# #
# reset (reboot) the device # reset (reboot) the device
# #
sub reset { sub reset {
my $self = shift; my $self = shift;
$self->PutCmd("ISAPI/System/reboot"); $self->PutCmd("ISAPI/System/reboot");
} }
1; 1;
__END__

View File

@ -302,7 +302,7 @@ sub run {
if ( ! ( $secs_count % 60 ) ) { if ( ! ( $secs_count % 60 ) ) {
Debug("Connecting"); Debug("Connecting");
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) { while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
Warning("Not connected to db ($dbh). Reconnecting"); Warning("Not connected to db ($dbh) ping(".$dbh->ping().". Reconnecting");
$dbh = zmDbConnect(); $dbh = zmDbConnect();
} }
my @cpuload = CpuLoad(); my @cpuload = CpuLoad();

View File

@ -69,7 +69,7 @@ Event::Event(
untimedEvent = true; untimedEvent = true;
start_time = now; start_time = now;
} else if ( start_time.tv_sec > now.tv_sec ) { } else if ( start_time.tv_sec > now.tv_sec ) {
Error("StartTime in the future %d.%d > $d.%d", Error("StartTime in the future %d.%d > %d.%d",
start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec
); );
start_time = now; start_time = now;

View File

@ -1,49 +1,3 @@
#header {
display: flex;
justify-content: space-between;
}
#menuControls {
display: flex;
align-items: center;
}
#menuControls div {
margin: 0 0 0 1em;
}
#imageFeed{
text-align: center;
}
#monitorStatus {
margin: 4px auto;
text-align: center;
}
#monitorStatus #enableDisableAlarms {
float: left;
}
#monitorStatus #forceCancelAlarm {
float: right;
}
#monitorStatus #monitorState {
}
#dvrControls {
margin-top: 3px;
margin-bottom: 2px;
text-align: center;
}
#dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
margin: 0 3px;
}
#dvrControls input[disabled] { #dvrControls input[disabled] {
color: #aaaaaa; color: #aaaaaa;
@ -61,45 +15,12 @@
border: 1px solid red; border: 1px solid red;
} }
#replayStatus {
margin: 3px 0 2px;
text-align: center;
clear: both;
}
#replayStatus > span {
padding: 0 4px;
}
#events {
margin: 0 auto;
}
#eventList {
width: 100%;
}
#eventList thead td {
font-weight: bold;
}
#eventList th, #eventList td {
text-align: center;
}
li {
display: inline;
list-style-type: none;
}
span.alarm { span.alarm {
color: #DC143C; color: #DC143C;
font-weight: bold;
} }
span.alert { span.alert {
color: #FF8C00; color: #FF8C00;
font-weight: bold;
} }
#eventList tr.recent { #eventList tr.recent {