Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas
This commit is contained in:
commit
f89654f442
|
@ -68,6 +68,7 @@ CREATE TABLE `Controls` (
|
||||||
`CanWake` tinyint(3) unsigned NOT NULL default '0',
|
`CanWake` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`CanSleep` tinyint(3) unsigned NOT NULL default '0',
|
`CanSleep` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`CanReset` tinyint(3) unsigned NOT NULL default '0',
|
`CanReset` tinyint(3) unsigned NOT NULL default '0',
|
||||||
|
`CanReboot` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`CanZoom` tinyint(3) unsigned NOT NULL default '0',
|
`CanZoom` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`CanAutoZoom` tinyint(3) unsigned NOT NULL default '0',
|
`CanAutoZoom` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`CanZoomAbs` tinyint(3) unsigned NOT NULL default '0',
|
`CanZoomAbs` tinyint(3) unsigned NOT NULL default '0',
|
||||||
|
|
|
@ -39,6 +39,8 @@ sub AUTOLOAD
|
||||||
my $class = ref($self) || croak( "$self not object" );
|
my $class = ref($self) || croak( "$self not object" );
|
||||||
my $name = $AUTOLOAD;
|
my $name = $AUTOLOAD;
|
||||||
$name =~ s/.*://;
|
$name =~ s/.*://;
|
||||||
|
## This seems odd... if the method existed would we even be here?
|
||||||
|
## https://perldoc.perl.org/perlsub.html#Autoloading
|
||||||
if ( exists($self->{$name}) )
|
if ( exists($self->{$name}) )
|
||||||
{
|
{
|
||||||
return( $self->{$name} );
|
return( $self->{$name} );
|
||||||
|
@ -46,9 +48,17 @@ sub AUTOLOAD
|
||||||
Fatal( "Can't access $name member of object of class $class" );
|
Fatal( "Can't access $name member of object of class $class" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# FIXME: Do we really have to open a new connection every time?
|
||||||
|
|
||||||
|
#Digest usernbme="bdmin", reblm="Login to 4K05DB3PAJE98BE", nonae="1720242756",
|
||||||
|
#uri="/agi-bin/ptz.agi?bation=getStbtus&ahbnnel=1", response="10dd925b26ebd559353734635b859b8b",
|
||||||
|
#opbque="1a99677524b4ae63bbe3a132b2e9b38e3b163ebd", qop=buth, na=00000001, anonae="ab1bb5d43aa5d542"
|
||||||
|
|
||||||
sub open
|
sub open
|
||||||
{
|
{
|
||||||
|
#Debug("&open invoked by: " . (caller(1))[3]);
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
my $cgi = shift || '/cgi-bin/configManager.cgi?action=getConfig&name=Ptz';
|
||||||
$self->loadMonitor();
|
$self->loadMonitor();
|
||||||
|
|
||||||
# The Dahua camera firmware API supports the concept of having multiple
|
# The Dahua camera firmware API supports the concept of having multiple
|
||||||
|
@ -73,60 +83,55 @@ sub open
|
||||||
}
|
}
|
||||||
|
|
||||||
use LWP::UserAgent;
|
use LWP::UserAgent;
|
||||||
$self->{ua} = LWP::UserAgent->new;
|
$self->{ua} = LWP::UserAgent->new(keep_alive => 1);
|
||||||
$self->{ua}->agent("ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION);
|
$self->{ua}->agent("ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION);
|
||||||
$self->{state} = 'closed';
|
$self->{state} = 'closed';
|
||||||
# credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string)
|
# credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string)
|
||||||
Debug("sendCmd credentials control address:'".$ADDRESS
|
|
||||||
."' realm:'" . $REALM
|
|
||||||
. "' username:'" . $USERNAME
|
|
||||||
. "' password:'".$PASSWORD
|
|
||||||
."'"
|
|
||||||
);
|
|
||||||
$self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD);
|
$self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD);
|
||||||
|
|
||||||
# Detect REALM
|
# Detect REALM
|
||||||
my $get_config_url = $PROTOCOL . $ADDRESS . "/cgi-bin/configManager.cgi?action=getConfig&name=Ptz";
|
my $url = $PROTOCOL . $ADDRESS . $cgi;
|
||||||
my $req = HTTP::Request->new(GET=>$get_config_url);
|
my $req = HTTP::Request->new(GET=>$url);
|
||||||
my $res = $self->{ua}->request($req);
|
my $res = $self->{ua}->request($req);
|
||||||
|
|
||||||
if ($res->is_success) {
|
if ($res->is_success) {
|
||||||
$self->{state} = 'open';
|
$self->{state} = 'open';
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $res->status_line() eq '401 Unauthorized' ) {
|
if ( $res->status_line() eq '401 Unauthorized' ) {
|
||||||
my $headers = $res->headers();
|
my $headers = $res->headers();
|
||||||
foreach my $k (keys %$headers) {
|
|
||||||
Debug("Initial Header $k => $$headers{$k}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($$headers{'www-authenticate'}) {
|
if ($$headers{'www-authenticate'}) {
|
||||||
my ($auth, $tokens) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/;
|
my ($auth, $tokens) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/;
|
||||||
|
Debug("Tokens: " . $tokens);
|
||||||
|
## FIXME: This is necessary because the Dahua spec does not match reality
|
||||||
if ($tokens =~ /\w+="([^"]+)"/i) {
|
if ($tokens =~ /\w+="([^"]+)"/i) {
|
||||||
if ($REALM ne $1) {
|
if ($REALM ne $1) {
|
||||||
$REALM = $1;
|
$REALM = $1;
|
||||||
Debug("Changing REALM to '" . $REALM . "'");
|
Debug("Changing REALM to '" . $REALM . "'");
|
||||||
$self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD);
|
$self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD);
|
||||||
my $req = HTTP::Request->new(GET=>$get_config_url);
|
my $req = HTTP::Request->new(GET=>$url);
|
||||||
$res = $self->{ua}->request($req);
|
$res = $self->{ua}->request($req);
|
||||||
|
|
||||||
if ($res->is_success()) {
|
if ($res->is_success()) {
|
||||||
$self->{state} = 'open';
|
$self->{state} = 'open';
|
||||||
return;
|
Debug('Authentication succeeded...');
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
Debug('Authentication still failed after updating REALM' . $res->status_line);
|
Debug('Authentication still failed after updating REALM' . $res->status_line);
|
||||||
$headers = $res->headers();
|
$headers = $res->headers();
|
||||||
foreach my $k ( keys %$headers ) {
|
foreach my $k ( keys %$headers ) {
|
||||||
Debug("Initial Header $k => $$headers{$k}");
|
Debug("Initial Header $k => $$headers{$k}");
|
||||||
} # end foreach
|
} # end foreach
|
||||||
} else {
|
} else { ## NOTE: Each of these else conditions is fatal as the command will not be
|
||||||
Error('Authentication failed, not a REALM problem');
|
## executed. No use going further.
|
||||||
|
Fatal('Authentication failed: Check username and password.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error('Failed to match realm in tokens');
|
Fatal('Authentication failed: Incorrect realm.');
|
||||||
} # end if
|
} # end if
|
||||||
} else {
|
} else {
|
||||||
Error('No WWW-Authenticate Header');
|
Fatal('Authentication failed: No www-authenticate header returned.');
|
||||||
} # end if headers
|
} # end if headers
|
||||||
} # end if $res->status_line() eq '401 Unauthorized'
|
} # end if $res->status_line() eq '401 Unauthorized'
|
||||||
}
|
}
|
||||||
|
@ -146,45 +151,40 @@ sub printMsg
|
||||||
Debug( $msg."[".$msg_len."]" );
|
Debug( $msg."[".$msg_len."]" );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub sendGetRequest {
|
sub _sendGetRequest {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $url_path = shift;
|
my $url_path = shift;
|
||||||
|
|
||||||
my $result = undef;
|
# Attempt to reuse the connection
|
||||||
|
|
||||||
|
# FIXME: I think we need some sort of keepalive/heartbeat sent to the camera
|
||||||
|
# in order to keep the session alive. As it is, it appears that the
|
||||||
|
# ua's authentication times out or some such.
|
||||||
|
#
|
||||||
|
# This might be of some use:
|
||||||
|
# {"method":"global.keepAlive","params":{"timeout":300,"active":false},"id":1518,"session":"dae233a51c0693519395209b271411b6"}[!http]
|
||||||
|
# The web browser interface POSTs commands as JSON using js
|
||||||
|
|
||||||
my $url = $PROTOCOL . $ADDRESS . $url_path;
|
my $url = $PROTOCOL . $ADDRESS . $url_path;
|
||||||
my $req = HTTP::Request->new(GET=>$url);
|
my $req = HTTP::Request->new(GET => $url);
|
||||||
|
|
||||||
my $res = $self->{ua}->request($req);
|
my $res = $self->{ua}->request($req);
|
||||||
|
|
||||||
if ($res->is_success) {
|
if ($res->is_success) {
|
||||||
$result = !undef;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
if ($res->status_line() eq '401 Unauthorized') {
|
return($self->open($url_path)); # if we have to, open a new connection
|
||||||
Debug("Error check failed, trying again: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD);
|
|
||||||
Debug("Content was " . $res->content() );
|
|
||||||
my $res = $self->{ua}->request($req);
|
|
||||||
if ($res->is_success) {
|
|
||||||
$result = !undef;
|
|
||||||
} else {
|
|
||||||
Error("Content was " . $res->content() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( ! $result ) {
|
|
||||||
Error("Error check failed: '".$res->status_line());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return($result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub sendPtzCommand
|
sub _sendPtzCommand
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $action = shift;
|
my $action = shift;
|
||||||
my $command_code = shift;
|
my $command_code = shift;
|
||||||
my $arg1 = shift;
|
my $arg1 = shift || 0;
|
||||||
my $arg2 = shift;
|
my $arg2 = shift || 0;
|
||||||
my $arg3 = shift;
|
my $arg3 = shift || 0;
|
||||||
|
my $arg4 = shift || 0;
|
||||||
|
|
||||||
my $channel = $self->{dahua_channel_number};
|
my $channel = $self->{dahua_channel_number};
|
||||||
|
|
||||||
|
@ -194,10 +194,12 @@ sub sendPtzCommand
|
||||||
$url_path .= "code=" . $command_code . "&";
|
$url_path .= "code=" . $command_code . "&";
|
||||||
$url_path .= "arg1=" . $arg1 . "&";
|
$url_path .= "arg1=" . $arg1 . "&";
|
||||||
$url_path .= "arg2=" . $arg2 . "&";
|
$url_path .= "arg2=" . $arg2 . "&";
|
||||||
$url_path .= "arg3=" . $arg3;
|
$url_path .= "arg3=" . $arg3 . "&";
|
||||||
$self->sendGetRequest($url_path);
|
$url_path .= "arg4=" . $arg4;
|
||||||
|
return $self->_sendGetRequest($url_path);
|
||||||
}
|
}
|
||||||
sub sendMomentaryPtzCommand
|
|
||||||
|
sub _sendMomentaryPtzCommand
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $command_code = shift;
|
my $command_code = shift;
|
||||||
|
@ -206,92 +208,195 @@ sub sendMomentaryPtzCommand
|
||||||
my $arg3 = shift;
|
my $arg3 = shift;
|
||||||
my $duration_ms = shift;
|
my $duration_ms = shift;
|
||||||
|
|
||||||
$self->sendPtzCommand("start", $command_code, $arg1, $arg2, $arg3);
|
$self->_sendPtzCommand("start", $command_code, $arg1, $arg2, $arg3);
|
||||||
my $duration_ns = $duration_ms * 1000;
|
my $duration_ns = $duration_ms * 1000;
|
||||||
usleep($duration_ns);
|
usleep($duration_ns);
|
||||||
$self->sendPtzCommand("stop", $command_code, $arg1, $arg2, $arg3);
|
$self->_sendPtzCommand("stop", $command_code, $arg1, $arg2, $arg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _sendAbsolutePositionCommand
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
my $arg1 = shift;
|
||||||
|
my $arg2 = shift;
|
||||||
|
my $arg3 = shift;
|
||||||
|
my $arg4 = shift;
|
||||||
|
|
||||||
|
$self->_sendPtzCommand("start", "PositionABS", $arg1, $arg2, $arg3, $arg4);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConLeft
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug("Move Up Left");
|
||||||
|
$self->_sendMomentaryPtzCommand("Left", 0, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConRight
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Right" );
|
||||||
|
$self->_sendMomentaryPtzCommand("Right", 0, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConUp
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Up" );
|
||||||
|
$self->_sendMomentaryPtzCommand("Up", 0, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConDown
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Down" );
|
||||||
|
$self->_sendMomentaryPtzCommand("Down", 0, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConUpRight
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Diagonally Up Right" );
|
||||||
|
$self->_sendMomentaryPtzCommand("RightUp", 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConDownRight
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Diagonally Down Right" );
|
||||||
|
$self->_sendMomentaryPtzCommand("RightDown", 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConUpLeft
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Diagonally Up Left" );
|
||||||
|
$self->_sendMomentaryPtzCommand("LeftUp", 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveConDownLeft
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Diagonally Up Right" );
|
||||||
|
$self->_sendMomentaryPtzCommand("LeftDown", 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub zoomConTele
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Zoom Tele" );
|
||||||
|
$self->_sendMomentaryPtzCommand("ZoomTele", 0, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub zoomConWide
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Zoom Wide" );
|
||||||
|
$self->_sendMomentaryPtzCommand("ZoomWide", 0, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelUpLeft
|
sub moveRelUpLeft
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Up Left");
|
Debug("Move Up Left");
|
||||||
$self->sendMomentaryPtzCommand("LeftUp", 4, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("LeftUp", 4, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelUp
|
sub moveRelUp
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Up");
|
Debug("Move Up");
|
||||||
$self->sendMomentaryPtzCommand("Up", 0, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("Up", 0, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelUpRight
|
sub moveRelUpRight
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Up Right");
|
Debug("Move Up Right");
|
||||||
$self->sendMomentaryPtzCommand("RightUp", 0, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("RightUp", 0, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelLeft
|
sub moveRelLeft
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Left");
|
Debug("Move Left");
|
||||||
$self->sendMomentaryPtzCommand("Left", 0, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("Left", 0, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelRight
|
sub moveRelRight
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Right");
|
Debug("Move Right");
|
||||||
$self->sendMomentaryPtzCommand("Right", 0, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("Right", 0, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelDownLeft
|
sub moveRelDownLeft
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Down Left");
|
Debug("Move Down Left");
|
||||||
$self->sendMomentaryPtzCommand("LeftDown", 4, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("LeftDown", 4, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelDown
|
sub moveRelDown
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Down");
|
Debug("Move Down");
|
||||||
$self->sendMomentaryPtzCommand("Down", 0, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("Down", 0, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelDownRight
|
sub moveRelDownRight
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Move Down Right");
|
Debug("Move Down Right");
|
||||||
$self->sendMomentaryPtzCommand("RightDown", 4, 4, 0, 500);
|
$self->_sendMomentaryPtzCommand("RightDown", 4, 4, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub zoomRelTele
|
sub zoomRelTele
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Zoom Relative Tele");
|
Debug("Zoom Relative Tele");
|
||||||
$self->sendMomentaryPtzCommand("ZoomTele", 0, 0, 0, 500);
|
$self->_sendMomentaryPtzCommand("ZoomTele", 0, 0, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub zoomRelWide
|
sub zoomRelWide
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug("Zoom Relative Wide");
|
Debug("Zoom Relative Wide");
|
||||||
$self->sendMomentaryPtzCommand("ZoomWide", 0, 0, 0, 500);
|
$self->_sendMomentaryPtzCommand("ZoomWide", 0, 0, 0, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub focusRelNear
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $response = $self->_sendPtzCommand("start", "FocusNear", 0, 1, 0, 0);
|
||||||
|
Debug("focusRelNear response: " . $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub focusRelFar
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $response = $self->_sendPtzCommand("start", "FocusFar", 0, 1, 0, 0);
|
||||||
|
Debug("focusRelFar response: " . $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub moveStop
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Move Stop" );
|
||||||
|
# The command does not matter here, just the stop...
|
||||||
|
$self->_sendPtzCommand("stop", "Up", 0, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
sub presetClear
|
sub presetClear
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $preset_id = $self->getParam($params, 'preset');
|
my $preset_id = $self->getParam($params, 'preset');
|
||||||
$self->sendPtzCommand("start", "ClearPreset", 0, $preset_id, 0);
|
$self->_sendPtzCommand("start", "ClearPreset", 0, $preset_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub presetSet
|
sub presetSet
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
@ -308,8 +413,8 @@ sub presetSet
|
||||||
my $control_preset_row = $sth->fetchrow_hashref();
|
my $control_preset_row = $sth->fetchrow_hashref();
|
||||||
my $new_label_name = $control_preset_row->{'Label'};
|
my $new_label_name = $control_preset_row->{'Label'};
|
||||||
|
|
||||||
$self->sendPtzCommand("start", "SetPreset", 0, $preset_id, 0);
|
$self->_sendPtzCommand("start", "SetPreset", 0, $preset_id, 0);
|
||||||
$self->sendPtzCommand("start", "SetPresetName", $preset_id, $new_label_name, 0);
|
$self->_sendPtzCommand("start", "SetPresetName", $preset_id, $new_label_name, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub presetGoto
|
sub presetGoto
|
||||||
|
@ -318,12 +423,39 @@ sub presetGoto
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $preset_id = $self->getParam($params, 'preset');
|
my $preset_id = $self->getParam($params, 'preset');
|
||||||
|
|
||||||
$self->sendPtzCommand("start", "GotoPreset", 0, $preset_id, 0);
|
$self->_sendPtzCommand("start", "GotoPreset", 0, $preset_id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub presetHome
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
$self->_sendAbsolutePositionCommand( 0, 0, 0, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub reset
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Camera Reset" );
|
||||||
|
$self->_sendPtzCommand("Reset", 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub reboot
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
Debug( "Camera Reboot" );
|
||||||
|
my $cmd = "/cgi-bin/magicBox.cgi?action=reboot";
|
||||||
|
$self->_sendGetRequest($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=encoding utf8
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
ZoneMinder::Control::Dahua - Perl module for Dahua cameras
|
ZoneMinder::Control::Dahua - Perl module for Dahua cameras
|
||||||
|
@ -337,10 +469,6 @@ place this in /usr/share/perl5/ZoneMinder/Control
|
||||||
|
|
||||||
This module is an implementation of the Dahua IP camera HTTP control API.
|
This module is an implementation of the Dahua IP camera HTTP control API.
|
||||||
|
|
||||||
=head2 EXPORT
|
|
||||||
|
|
||||||
None by default.
|
|
||||||
|
|
||||||
=head1 COPYRIGHT AND LICENSE
|
=head1 COPYRIGHT AND LICENSE
|
||||||
|
|
||||||
Copyright (C) 2018 ZoneMinder LLC
|
Copyright (C) 2018 ZoneMinder LLC
|
||||||
|
@ -359,4 +487,138 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
=head1 Private Methods
|
||||||
|
|
||||||
|
Methods intended for use internally but documented here for future developers.
|
||||||
|
|
||||||
|
=head2 _sendAbsolutePositionCommand( $arg1, $arg2, $arg3, $arg4 )
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
$arg1 = Horizontal angle 0° to 360°
|
||||||
|
$arg2 = Vertical angle 0° to -90°
|
||||||
|
$arg3 = Zoom multiplier
|
||||||
|
$arg4 = Speed 1 to 8
|
||||||
|
|
||||||
|
This is an private method used to send an absolute position command to the
|
||||||
|
camera.
|
||||||
|
|
||||||
|
=head1 Public Methods
|
||||||
|
|
||||||
|
Methods made available to control.pl via ZoneMinder::Control
|
||||||
|
|
||||||
|
=head2 Notes:
|
||||||
|
|
||||||
|
=over 1
|
||||||
|
|
||||||
|
Which methods are invoked depends on which types of movement are selected in
|
||||||
|
the camera control type. For example: if the 'Can Move Continuous' option is
|
||||||
|
checked, then methods including 'Con' in their names are invoked. Likewise if
|
||||||
|
the 'Can Move Relative" option is checked, then methods including 'Rel' in
|
||||||
|
their names are invoked.
|
||||||
|
|
||||||
|
|
||||||
|
At present, these types of movement are prioritized and exclusive. This applies
|
||||||
|
to all types of movement, not just PTZ, but focus, iris, etc. as well. The options
|
||||||
|
are tested in the following order:
|
||||||
|
|
||||||
|
1. Continuous
|
||||||
|
|
||||||
|
2. Relative
|
||||||
|
|
||||||
|
3. Absolute
|
||||||
|
|
||||||
|
These types are exclusive meaning that the first one that matches is the one
|
||||||
|
ZoneMinder will use to control with. It would be nice to allow the user to
|
||||||
|
select the type used given that some cameras support all three types of
|
||||||
|
movement.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 new
|
||||||
|
|
||||||
|
This method instantiates a new control object based upon this control module
|
||||||
|
and sets the 'id' attribute to the value passed in.
|
||||||
|
|
||||||
|
=head2 open
|
||||||
|
|
||||||
|
This method opens an HTTP connection to the camera. It handles authentication,
|
||||||
|
etc. Upon success it sets the 'state' attribute to 'open.'
|
||||||
|
|
||||||
|
=head2 close
|
||||||
|
|
||||||
|
This method effectively closes the HTTP connection to the camera. It sets the
|
||||||
|
'state' attribute to 'close.'
|
||||||
|
|
||||||
|
=head2 printMsg
|
||||||
|
|
||||||
|
This method appears to be used for debugging.
|
||||||
|
|
||||||
|
=head2 moveCon<direction>
|
||||||
|
|
||||||
|
This set of methods invoke continuous movement in the direction indicated by
|
||||||
|
the <direction> portion of their name. They accept no arguments and move the
|
||||||
|
camera at a speed of 1 for 0ms. The speed index of 1 is the lowest of the
|
||||||
|
accepted range of 1-8.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
|
||||||
|
This is not true continuous movmement as currently implemented.
|
||||||
|
|
||||||
|
=head2 focusCon<range>
|
||||||
|
|
||||||
|
This set of methods invoke continuous focus in the range direction indicated
|
||||||
|
by the <range> portion of their name. They accept no arguments.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
|
||||||
|
This is not true continuous movmement as currently implemented.
|
||||||
|
|
||||||
|
=head2 moveRel<direction>
|
||||||
|
|
||||||
|
This set of methods invoke relatvie movement in the direction indicated by
|
||||||
|
the <direction> portion of their name. They accept no arguments and move the
|
||||||
|
camera at a speed of 4 for 500ms. The speed index of 4 is half-way between
|
||||||
|
the accepted range of 1-8.
|
||||||
|
|
||||||
|
=head2 focusRel<range>
|
||||||
|
|
||||||
|
This set of methods invoke realtive focus in the range direction indicated by
|
||||||
|
the <range> portion of their name. They accept no arguments.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
|
||||||
|
This only just does work. The Dahua API specifies "multiples" as the input.
|
||||||
|
We pass in a 1 for that as it does not seem to matter what number (0-8) is
|
||||||
|
provided, the camera focus behaves the same.
|
||||||
|
|
||||||
|
=head2 moveStop
|
||||||
|
|
||||||
|
This method attempts to stop the camera. The problem is that if continuous
|
||||||
|
motion is occurring in multiple directions, this will only stop the motion
|
||||||
|
in the 'Up' direction. Dahua does not support an "all-stop" command.
|
||||||
|
|
||||||
|
=head2 presetHome
|
||||||
|
|
||||||
|
This method "homes" the camera to a preset position. It accepts no arguments.
|
||||||
|
When either continuous or relative movement is enabled, pressing the center
|
||||||
|
button on the movement controls invokes this method.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
|
||||||
|
The Dahua protocol does not appear to support a preset Home feature. We could
|
||||||
|
allow the user to assign a preset slot as the "home" slot. Dahua does appear
|
||||||
|
to support naming presets which may lend itself to this sort of thing. At
|
||||||
|
this point, we'll just send the camera back to center and zoom wide. (0°,0°,0)
|
||||||
|
|
||||||
|
=head2 reset
|
||||||
|
|
||||||
|
This method will reset the PTZ controls to their "default." It is not clear
|
||||||
|
what that is.
|
||||||
|
|
||||||
|
=head2 reboot
|
||||||
|
|
||||||
|
This method performs a reboot of the camera. This will take the camera offline
|
||||||
|
for the time it takes to reboot.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
|
@ -1005,17 +1005,17 @@ sub delete_empty_directories {
|
||||||
Error("delete_empty_directories: Can't open directory '/$_[0]': $!" );
|
Error("delete_empty_directories: Can't open directory '/$_[0]': $!" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
my @contents = map { ( $_ eq '.' or $_ eq '..' ) ? () : $_ } readdir( $DIR );
|
my @contents = map { ( $_ eq '.' or $_ eq '..' ) ? () : $_ } readdir($DIR);
|
||||||
#Debug("delete_empty_directories $_[0] has " . @contents .' entries:' . ( @contents <= 2 ? join(',',@contents) : '' ));
|
#Debug("delete_empty_directories $_[0] has " . @contents .' entries:' . ( @contents <= 2 ? join(',',@contents) : '' ));
|
||||||
my @dirs = map { -d $_[0].'/'.$_ ? $_ : () } @contents;
|
my @dirs = map { -d $_[0].'/'.$_ ? $_ : () } @contents;
|
||||||
if ( @dirs ) {
|
if ( @dirs ) {
|
||||||
Debug("Have " . @dirs . " dirs in $_[0]");
|
Debug('Have ' . @dirs . " dirs in $_[0]");
|
||||||
foreach ( @dirs ) {
|
foreach ( @dirs ) {
|
||||||
delete_empty_directories( $_[0].'/'.$_ );
|
delete_empty_directories($_[0].'/'.$_);
|
||||||
}
|
}
|
||||||
#Reload, since we may now be empty
|
#Reload, since we may now be empty
|
||||||
rewinddir $DIR;
|
rewinddir $DIR;
|
||||||
@contents = map { ($_ eq '.' or $_ eq '..') ? () : $_ } readdir( $DIR );
|
@contents = map { ($_ eq '.' or $_ eq '..') ? () : $_ } readdir($DIR);
|
||||||
}
|
}
|
||||||
closedir($DIR);
|
closedir($DIR);
|
||||||
if ( ! @contents ) {
|
if ( ! @contents ) {
|
||||||
|
|
|
@ -923,10 +923,10 @@ if ( $version ) {
|
||||||
die( "Can't find upgrade from version '$version'" );
|
die( "Can't find upgrade from version '$version'" );
|
||||||
}
|
}
|
||||||
# Re-enable the privacy popup after each upgrade
|
# Re-enable the privacy popup after each upgrade
|
||||||
my $sql = "update Config set Value = 1 where Name = 'ZM_SHOW_PRIVACY'";
|
#my $sql = "update Config set Value = 1 where Name = 'ZM_SHOW_PRIVACY'";
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
#my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
my $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() );
|
#my $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() );
|
||||||
$sth->finish();
|
#$sth->finish();
|
||||||
print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" );
|
print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" );
|
||||||
}
|
}
|
||||||
zmDbDisconnect();
|
zmDbDisconnect();
|
||||||
|
|
|
@ -248,15 +248,19 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
|
|
||||||
//Function to check Username length
|
//Function to check Username length
|
||||||
bool checkUser ( const char *username) {
|
bool checkUser ( const char *username) {
|
||||||
if ( strlen(username) > 32) {
|
if ( ! username )
|
||||||
return false;
|
return false;
|
||||||
}
|
if ( strlen(username) > 32 )
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//Function to check password length
|
//Function to check password length
|
||||||
bool checkPass (const char *password) {
|
bool checkPass (const char *password) {
|
||||||
if ( strlen(password) > 64) {
|
if ( !password )
|
||||||
return false;
|
return false;
|
||||||
}
|
if ( strlen(password) > 64 )
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
46
src/zmu.cpp
46
src/zmu.cpp
|
@ -394,7 +394,7 @@ int main(int argc, char *argv[]) {
|
||||||
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
|
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} // end getopt loop
|
||||||
|
|
||||||
if ( optind < argc ) {
|
if ( optind < argc ) {
|
||||||
fprintf(stderr, "Extraneous options, ");
|
fprintf(stderr, "Extraneous options, ");
|
||||||
|
@ -425,44 +425,38 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if ( config.opt_use_auth ) {
|
if ( config.opt_use_auth ) {
|
||||||
if ( strcmp(config.auth_relay, "none") == 0 ) {
|
if ( strcmp(config.auth_relay, "none") == 0 ) {
|
||||||
if ( !checkUser(username)) {
|
|
||||||
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
|
|
||||||
exit_zmu(-1);
|
|
||||||
}
|
|
||||||
if ( !username ) {
|
if ( !username ) {
|
||||||
fprintf(stderr, "Error, username must be supplied\n");
|
fprintf(stderr, "Error, username must be supplied\n");
|
||||||
exit_zmu(-1);
|
exit_zmu(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( username ) {
|
|
||||||
user = zmLoadUser(username);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ( !(username && password) && !auth ) {
|
|
||||||
fprintf(stderr, "Error, username and password or auth string must be supplied\n");
|
|
||||||
exit_zmu(-1);
|
|
||||||
}
|
|
||||||
if ( !checkUser(username)) {
|
if ( !checkUser(username)) {
|
||||||
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
|
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
|
||||||
exit_zmu(-1);
|
exit_zmu(-1);
|
||||||
}
|
}
|
||||||
if ( !checkPass(password)) {
|
|
||||||
fprintf(stderr, "Error, password greater than allowed 64 characters\n");
|
user = zmLoadUser(username);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if ( !(username && password) && !auth ) {
|
||||||
|
fprintf(stderr, "Error, username and password or auth string must be supplied\n");
|
||||||
exit_zmu(-1);
|
exit_zmu(-1);
|
||||||
}
|
}
|
||||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
if ( auth ) {
|
||||||
{
|
user = zmLoadAuthUser(auth, false);
|
||||||
if ( auth ) {
|
|
||||||
user = zmLoadAuthUser(auth, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
if ( username && password ) {
|
||||||
{
|
if ( !checkUser(username)) {
|
||||||
if ( username && password ) {
|
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
|
||||||
user = zmLoadUser(username, password);
|
exit_zmu(-1);
|
||||||
}
|
}
|
||||||
}
|
if ( !checkPass(password)) {
|
||||||
}
|
fprintf(stderr, "Error, password greater than allowed 64 characters\n");
|
||||||
|
exit_zmu(-1);
|
||||||
|
}
|
||||||
|
user = zmLoadUser(username, password);
|
||||||
|
} // end if username && password
|
||||||
|
} // end if relay or not
|
||||||
if ( !user ) {
|
if ( !user ) {
|
||||||
fprintf(stderr, "Error, unable to authenticate user\n");
|
fprintf(stderr, "Error, unable to authenticate user\n");
|
||||||
return exit_zmu(-1);
|
return exit_zmu(-1);
|
||||||
|
|
|
@ -1,14 +1,88 @@
|
||||||
<?php
|
<?php
|
||||||
App::uses('Component', 'Controller');
|
App::uses('Component', 'Controller');
|
||||||
|
|
||||||
class FilterComponent extends Component {
|
class FilterComponent extends Component {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid MySQL operands that can be used from namedParams with two operands
|
||||||
|
* where the right-hand side (RHS) is a literal.
|
||||||
|
* These came from https://dev.mysql.com/doc/refman/8.0/en/non-typed-operators.html
|
||||||
|
*/
|
||||||
|
public $twoOperandSQLOperands = array(
|
||||||
|
'AND',
|
||||||
|
'&&',
|
||||||
|
'=',
|
||||||
|
//':=',
|
||||||
|
//'BETWEEN ... AND ...',
|
||||||
|
//'BINARY',
|
||||||
|
'&',
|
||||||
|
'~',
|
||||||
|
//'|',
|
||||||
|
'^',
|
||||||
|
//'CASE',
|
||||||
|
'DIV',
|
||||||
|
'/',
|
||||||
|
'=',
|
||||||
|
'<=>',
|
||||||
|
'>',
|
||||||
|
'>=',
|
||||||
|
'IS',
|
||||||
|
'IS NOT',
|
||||||
|
//'IS NOT NULL',
|
||||||
|
//'IS NULL',
|
||||||
|
//'->',
|
||||||
|
//'->>',
|
||||||
|
'<<',
|
||||||
|
'<',
|
||||||
|
'<=',
|
||||||
|
'LIKE',
|
||||||
|
'-',
|
||||||
|
'%',
|
||||||
|
'MOD',
|
||||||
|
//'NOT',
|
||||||
|
//'!',
|
||||||
|
//'NOT BETWEEN ... AND ...',
|
||||||
|
'!=',
|
||||||
|
'<>',
|
||||||
|
'NOT LIKE',
|
||||||
|
'NOT REGEXP',
|
||||||
|
// `or` operators aren't safe as they can
|
||||||
|
// be used to skip an existing condition
|
||||||
|
// enforcing access to only certain
|
||||||
|
// monitors/events.
|
||||||
|
//'||',
|
||||||
|
//'OR',
|
||||||
|
'+',
|
||||||
|
'REGEXP',
|
||||||
|
'>>',
|
||||||
|
'RLIKE',
|
||||||
|
'SOUNDS LIKE',
|
||||||
|
//'*',
|
||||||
|
'-',
|
||||||
|
//'XOR',
|
||||||
|
);
|
||||||
|
|
||||||
// Build a CakePHP find() condition based on the named parameters
|
// Build a CakePHP find() condition based on the named parameters
|
||||||
// that are passed in
|
// that are passed in
|
||||||
public function buildFilter($namedParams) {
|
public function buildFilter($namedParams) {
|
||||||
|
$conditions = array();
|
||||||
if ($namedParams) {
|
if ($namedParams) {
|
||||||
$conditions = array();
|
|
||||||
|
|
||||||
foreach ($namedParams as $attribute => $value) {
|
foreach ($namedParams as $attribute => $value) {
|
||||||
|
// We need to sanitize $attribute to avoid SQL injection.
|
||||||
|
$lhs = trim($attribute);
|
||||||
|
$matches = NULL;
|
||||||
|
if (preg_match('/^(?P<field>[a-z0-9]+)(?P<operator>.+)?$/i', $lhs, $matches) !== 1) {
|
||||||
|
throw new Exception('Invalid argument before `:`: ' . $lhs);
|
||||||
|
}
|
||||||
|
$operator = trim($matches['operator']);
|
||||||
|
|
||||||
|
// Only allow operators on our allow list. No operator
|
||||||
|
// specified defaults to `=` by cakePHP.
|
||||||
|
if ($operator != '' && !in_array($operator, $this->twoOperandSQLOperands)) {
|
||||||
|
throw new Exception('Invalid operator: ' . $operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
$lhs = '`' . $matches['field'] . '` ' . $operator;
|
||||||
// If the named param contains an array, we want to turn it into an IN condition
|
// If the named param contains an array, we want to turn it into an IN condition
|
||||||
// Otherwise, we add it right into the $conditions array
|
// Otherwise, we add it right into the $conditions array
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
|
@ -18,10 +92,10 @@ class FilterComponent extends Component {
|
||||||
array_push($array, $term);
|
array_push($array, $term);
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = array($attribute => $array);
|
$query = array($lhs => $array);
|
||||||
array_push($conditions, $query);
|
array_push($conditions, $query);
|
||||||
} else {
|
} else {
|
||||||
$conditions[$attribute] = $value;
|
$conditions[$lhs] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,8 @@ class EventsController extends AppController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $this->request->params['named'] ) {
|
if ( $this->request->params['named'] ) {
|
||||||
//$this->FilterComponent = $this->Components->load('Filter');
|
$this->FilterComponent = $this->Components->load('Filter');
|
||||||
//$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
||||||
$conditions = $this->request->params['named'];
|
|
||||||
} else {
|
} else {
|
||||||
$conditions = array();
|
$conditions = array();
|
||||||
}
|
}
|
||||||
|
@ -234,18 +233,34 @@ class EventsController extends AppController {
|
||||||
|
|
||||||
public function search() {
|
public function search() {
|
||||||
$this->Event->recursive = -1;
|
$this->Event->recursive = -1;
|
||||||
|
// Unmodified conditions to pass to find()
|
||||||
|
$find_conditions = array();
|
||||||
|
// Conditions to be filtered by buildFilter
|
||||||
$conditions = array();
|
$conditions = array();
|
||||||
|
|
||||||
foreach ($this->params['named'] as $param_name => $value) {
|
foreach ($this->params['named'] as $param_name => $value) {
|
||||||
// Transform params into mysql
|
// Transform params into conditions
|
||||||
if ( preg_match('/interval/i', $value, $matches) ) {
|
if ( preg_match('/^\s?interval\s?/i', $value) ) {
|
||||||
$condition = array("$param_name >= (date_sub(now(), $value))");
|
if (preg_match('/^[a-z0-9]+$/i', $param_name) !== 1) {
|
||||||
|
throw new Exception('Invalid field name: ' . $param_name);
|
||||||
|
}
|
||||||
|
$matches = NULL;
|
||||||
|
$value = preg_replace('/^\s?interval\s?/i', '', $value);
|
||||||
|
if (preg_match('/^(?P<expr>[ -.:0-9\']+)\s+(?P<unit>[_a-z]+)$/i', trim($value), $matches) !== 1) {
|
||||||
|
throw new Exception('Invalid interval: ' . $value);
|
||||||
|
}
|
||||||
|
$expr = trim($matches['expr']);
|
||||||
|
$unit = trim($matches['unit']);
|
||||||
|
array_push($find_conditions, "$param_name >= DATE_SUB(NOW(), INTERVAL $expr $unit)");
|
||||||
} else {
|
} else {
|
||||||
$condition = array($param_name => $value);
|
$conditions[$param_name] = $value;
|
||||||
}
|
}
|
||||||
array_push($conditions, $condition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->FilterComponent = $this->Components->load('Filter');
|
||||||
|
$conditions = $this->FilterComponent->buildFilter($conditions);
|
||||||
|
array_push($conditions, $find_conditions);
|
||||||
|
|
||||||
$results = $this->Event->find('all', array(
|
$results = $this->Event->find('all', array(
|
||||||
'conditions' => $conditions
|
'conditions' => $conditions
|
||||||
));
|
));
|
||||||
|
@ -261,18 +276,32 @@ class EventsController extends AppController {
|
||||||
// consoleEvents/1 hour/AlarmFrames >=: 1/AlarmFrames <=: 20.json
|
// consoleEvents/1 hour/AlarmFrames >=: 1/AlarmFrames <=: 20.json
|
||||||
|
|
||||||
public function consoleEvents($interval = null) {
|
public function consoleEvents($interval = null) {
|
||||||
|
$matches = NULL;
|
||||||
|
// https://dev.mysql.com/doc/refman/5.5/en/expressions.html#temporal-intervals
|
||||||
|
// Examples: `'1-1' YEAR_MONTH`, `'-1 10' DAY_HOUR`, `'1.999999' SECOND_MICROSECOND`
|
||||||
|
if (preg_match('/^(?P<expr>[ -.:0-9\']+)\s+(?P<unit>[_a-z]+)$/i', trim($interval), $matches) !== 1) {
|
||||||
|
throw new Exception('Invalid interval: ' . $interval);
|
||||||
|
}
|
||||||
|
$expr = trim($matches['expr']);
|
||||||
|
$unit = trim($matches['unit']);
|
||||||
|
|
||||||
$this->Event->recursive = -1;
|
$this->Event->recursive = -1;
|
||||||
$results = array();
|
$results = array();
|
||||||
|
$this->FilterComponent = $this->Components->load('Filter');
|
||||||
|
$conditions = $this->FilterComponent->buildFilter($conditions);
|
||||||
|
array_push($conditions, array("StartTime >= DATE_SUB(NOW(), INTERVAL $expr $unit)"));
|
||||||
|
|
||||||
$moreconditions = '';
|
$query = $this->Event->find('all', array(
|
||||||
foreach ($this->request->params['named'] as $name => $param) {
|
'fields' => array(
|
||||||
$moreconditions = $moreconditions . ' AND '.$name.$param;
|
'MonitorId',
|
||||||
}
|
'COUNT(*) AS Count',
|
||||||
|
),
|
||||||
$query = $this->Event->query("SELECT MonitorId, COUNT(*) AS Count FROM Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;");
|
'conditions' => $conditions,
|
||||||
|
'group' => 'MonitorId',
|
||||||
|
));
|
||||||
|
|
||||||
foreach ($query as $result) {
|
foreach ($query as $result) {
|
||||||
$results[$result['Events']['MonitorId']] = $result[0]['Count'];
|
$results[$result['Event']['MonitorId']] = $result[0]['Count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
|
|
|
@ -40,8 +40,7 @@ class MonitorsController extends AppController {
|
||||||
|
|
||||||
if ( $this->request->params['named'] ) {
|
if ( $this->request->params['named'] ) {
|
||||||
$this->FilterComponent = $this->Components->load('Filter');
|
$this->FilterComponent = $this->Components->load('Filter');
|
||||||
//$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
||||||
$conditions = $this->request->params['named'];
|
|
||||||
} else {
|
} else {
|
||||||
$conditions = array();
|
$conditions = array();
|
||||||
}
|
}
|
||||||
|
@ -318,6 +317,10 @@ class MonitorsController extends AppController {
|
||||||
throw new NotFoundException(__('Invalid monitor'));
|
throw new NotFoundException(__('Invalid monitor'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preg_match('/^[a-z]+$/i', $daemon) !== 1) {
|
||||||
|
throw new BadRequestException(__('Invalid command'));
|
||||||
|
}
|
||||||
|
|
||||||
$monitor = $this->Monitor->find('first', array(
|
$monitor = $this->Monitor->find('first', array(
|
||||||
'fields' => array('Id', 'Type', 'Device'),
|
'fields' => array('Id', 'Type', 'Device'),
|
||||||
'conditions' => array('Id' => $id)
|
'conditions' => array('Id' => $id)
|
||||||
|
|
|
@ -122,7 +122,12 @@ class Event {
|
||||||
|
|
||||||
public function Path() {
|
public function Path() {
|
||||||
$Storage = $this->Storage();
|
$Storage = $this->Storage();
|
||||||
return $Storage->Path().'/'.$this->Relative_Path();
|
if ( $Storage->Path() and $this->Relative_Path() ) {
|
||||||
|
return $Storage->Path().'/'.$this->Relative_Path();
|
||||||
|
} else {
|
||||||
|
Error("Event Path not complete. Storage: " . $Storage->Path() . " relative: " . $this->Relative_Path());
|
||||||
|
return '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Relative_Path() {
|
public function Relative_Path() {
|
||||||
|
@ -148,17 +153,19 @@ class Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
# This wouldn't work with foreign keys
|
if ( ! $this->{'Id'} ) {
|
||||||
dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) );
|
Error('Event delete on event with empty Id');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ( !ZM_OPT_FAST_DELETE ) {
|
if ( !ZM_OPT_FAST_DELETE ) {
|
||||||
dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) );
|
dbQuery('DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}));
|
||||||
dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}) );
|
dbQuery('DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}));
|
||||||
if ( $this->{'Scheme'} == 'Deep' ) {
|
if ( $this->{'Scheme'} == 'Deep' ) {
|
||||||
|
|
||||||
# Assumption: All events have a start time
|
# Assumption: All events have a start time
|
||||||
$start_date = date_parse( $this->{'StartTime'} );
|
$start_date = date_parse($this->{'StartTime'});
|
||||||
if ( ! $start_date ) {
|
if ( ! $start_date ) {
|
||||||
Error('Unable to parse start time for event ' . $this->{'Id'} . ' not deleting files.' );
|
Error('Unable to parse start time for event ' . $this->{'Id'} . ' not deleting files.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$start_date['year'] = $start_date['year'] % 100;
|
$start_date['year'] = $start_date['year'] % 100;
|
||||||
|
@ -166,37 +173,42 @@ class Event {
|
||||||
# So this is because ZM creates a link under the day pointing to the time that the event happened.
|
# So this is because ZM creates a link under the day pointing to the time that the event happened.
|
||||||
$link_path = $this->Link_Path();
|
$link_path = $this->Link_Path();
|
||||||
if ( ! $link_path ) {
|
if ( ! $link_path ) {
|
||||||
Error('Unable to determine link path for event ' . $this->{'Id'} . ' not deleting files.' );
|
Error('Unable to determine link path for event ' . $this->{'Id'} . ' not deleting files.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$Storage = $this->Storage();
|
$Storage = $this->Storage();
|
||||||
$eventlink_path = $Storage->Path().'/'.$link_path;
|
$eventlink_path = $Storage->Path().'/'.$link_path;
|
||||||
|
|
||||||
if ( $id_files = glob( $eventlink_path ) ) {
|
if ( $id_files = glob($eventlink_path) ) {
|
||||||
if ( ! $eventPath = readlink($id_files[0]) ) {
|
if ( ! $eventPath = readlink($id_files[0]) ) {
|
||||||
Error("Unable to read link at $id_files[0]");
|
Error("Unable to read link at $id_files[0]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
# I know we are using arrays here, but really there can only ever be 1 in the array
|
# I know we are using arrays here, but really there can only ever be 1 in the array
|
||||||
$eventPath = preg_replace( '/\.'.$this->{'Id'}.'$/', $eventPath, $id_files[0] );
|
$eventPath = preg_replace( '/\.'.$this->{'Id'}.'$/', $eventPath, $id_files[0] );
|
||||||
deletePath( $eventPath );
|
deletePath($eventPath);
|
||||||
deletePath( $id_files[0] );
|
deletePath($id_files[0]);
|
||||||
$pathParts = explode( '/', $eventPath );
|
$pathParts = explode('/', $eventPath);
|
||||||
for ( $i = count($pathParts)-1; $i >= 2; $i-- ) {
|
for ( $i = count($pathParts)-1; $i >= 2; $i-- ) {
|
||||||
$deletePath = join( '/', array_slice( $pathParts, 0, $i ) );
|
$deletePath = join('/', array_slice($pathParts, 0, $i));
|
||||||
if ( !glob( $deletePath."/*" ) ) {
|
if ( !glob($deletePath.'/*') ) {
|
||||||
deletePath( $deletePath );
|
deletePath($deletePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Warning( "Found no event files under $eventlink_path" );
|
Warning("Found no event files under $eventlink_path");
|
||||||
} # end if found files
|
} # end if found files
|
||||||
} else {
|
} else {
|
||||||
$eventPath = $this->Path();
|
$eventPath = $this->Path();
|
||||||
deletePath( $eventPath );
|
if ( ! $eventPath ) {
|
||||||
|
Error("No event Path in Event delete. Not deleting");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deletePath($eventPath);
|
||||||
} # USE_DEEP_STORAGE OR NOT
|
} # USE_DEEP_STORAGE OR NOT
|
||||||
} # ! ZM_OPT_FAST_DELETE
|
} # ! ZM_OPT_FAST_DELETE
|
||||||
|
dbQuery('DELETE FROM Events WHERE Id = ?', array($this->{'Id'}));
|
||||||
} # end Event->delete
|
} # end Event->delete
|
||||||
|
|
||||||
public function getStreamSrc( $args=array(), $querySep='&' ) {
|
public function getStreamSrc( $args=array(), $querySep='&' ) {
|
||||||
|
|
|
@ -27,28 +27,32 @@ if ( $action == 'donate' && isset($_REQUEST['option']) ) {
|
||||||
$option = $_REQUEST['option'];
|
$option = $_REQUEST['option'];
|
||||||
switch( $option ) {
|
switch( $option ) {
|
||||||
case 'go' :
|
case 'go' :
|
||||||
// Ignore this, the caller will open the page itself
|
// Ignore this, the caller will open the page itself
|
||||||
break;
|
break;
|
||||||
case 'hour' :
|
case 'hour' :
|
||||||
case 'day' :
|
case 'day' :
|
||||||
case 'week' :
|
case 'week' :
|
||||||
case 'month' :
|
case 'month' :
|
||||||
$nextReminder = time();
|
$nextReminder = time();
|
||||||
if ( $option == 'hour' ) {
|
if ( $option == 'hour' ) {
|
||||||
$nextReminder += 60*60;
|
$nextReminder += 60*60;
|
||||||
} elseif ( $option == 'day' ) {
|
} elseif ( $option == 'day' ) {
|
||||||
$nextReminder += 24*60*60;
|
$nextReminder += 24*60*60;
|
||||||
} elseif ( $option == 'week' ) {
|
} elseif ( $option == 'week' ) {
|
||||||
$nextReminder += 7*24*60*60;
|
$nextReminder += 7*24*60*60;
|
||||||
} elseif ( $option == 'month' ) {
|
} elseif ( $option == 'month' ) {
|
||||||
$nextReminder += 30*24*60*60;
|
$nextReminder += 30*24*60*60;
|
||||||
}
|
}
|
||||||
dbQuery("UPDATE Config SET Value = '".$nextReminder."' WHERE Name = 'ZM_DYN_DONATE_REMINDER_TIME'");
|
dbQuery("UPDATE Config SET Value = '".$nextReminder."' WHERE Name = 'ZM_DYN_DONATE_REMINDER_TIME'");
|
||||||
break;
|
break;
|
||||||
case 'never' :
|
case 'never' :
|
||||||
case 'already' :
|
case 'already' :
|
||||||
dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_DYN_SHOW_DONATE_REMINDER'");
|
dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_DYN_SHOW_DONATE_REMINDER'");
|
||||||
break;
|
break;
|
||||||
|
default :
|
||||||
|
Warning("Unknown value for option in donate: $option");
|
||||||
|
break;
|
||||||
} // end switch option
|
} // end switch option
|
||||||
|
$view = 'none';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -211,7 +211,7 @@ global $user;
|
||||||
if ( ZM_OPT_USE_AUTH ) {
|
if ( ZM_OPT_USE_AUTH ) {
|
||||||
$close_session = 0;
|
$close_session = 0;
|
||||||
if ( !is_session_started() ) {
|
if ( !is_session_started() ) {
|
||||||
session_start();
|
zm_session_start();
|
||||||
$close_session = 1;
|
$close_session = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
//
|
//
|
||||||
namespace ZM;
|
|
||||||
|
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ define('ZM_BASE_URL', '');
|
||||||
|
|
||||||
require_once('includes/functions.php');
|
require_once('includes/functions.php');
|
||||||
if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
|
if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
|
||||||
Logger::Debug("OPTIONS Method, only doing CORS");
|
ZM\Logger::Debug("OPTIONS Method, only doing CORS");
|
||||||
# Add Cross domain access headers
|
# Add Cross domain access headers
|
||||||
CORSHeaders();
|
CORSHeaders();
|
||||||
return;
|
return;
|
||||||
|
@ -159,7 +158,7 @@ CORSHeaders();
|
||||||
|
|
||||||
// Check for valid content dirs
|
// Check for valid content dirs
|
||||||
if ( !is_writable(ZM_DIR_EVENTS) ) {
|
if ( !is_writable(ZM_DIR_EVENTS) ) {
|
||||||
Warning("Cannot write to event folder ".ZM_DIR_EVENTS.". Check that it exists and is owned by the web account user.");
|
ZM\Warning("Cannot write to event folder ".ZM_DIR_EVENTS.". Check that it exists and is owned by the web account user.");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Globals
|
# Globals
|
||||||
|
@ -181,7 +180,7 @@ if ( isset($_REQUEST['request']) )
|
||||||
require_once('includes/auth.php');
|
require_once('includes/auth.php');
|
||||||
|
|
||||||
foreach ( getSkinIncludes('skin.php') as $includeFile ) {
|
foreach ( getSkinIncludes('skin.php') as $includeFile ) {
|
||||||
#Logger::Debug("including $includeFile");
|
#ZM\Logger::Debug("including $includeFile");
|
||||||
require_once $includeFile;
|
require_once $includeFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +193,7 @@ isset($view) || $view = NULL;
|
||||||
isset($request) || $request = NULL;
|
isset($request) || $request = NULL;
|
||||||
isset($action) || $action = NULL;
|
isset($action) || $action = NULL;
|
||||||
|
|
||||||
Logger::Debug("View: $view Request: $request Action: $action User: " . ( isset($user) ? $user['Username'] : 'none' ));
|
ZM\Logger::Debug("View: $view Request: $request Action: $action User: " . ( isset($user) ? $user['Username'] : 'none' ));
|
||||||
if (
|
if (
|
||||||
ZM_ENABLE_CSRF_MAGIC &&
|
ZM_ENABLE_CSRF_MAGIC &&
|
||||||
( $action != 'login' ) &&
|
( $action != 'login' ) &&
|
||||||
|
@ -205,17 +204,17 @@ if (
|
||||||
( $view != 'archive' )
|
( $view != 'archive' )
|
||||||
) {
|
) {
|
||||||
require_once( 'includes/csrf/csrf-magic.php' );
|
require_once( 'includes/csrf/csrf-magic.php' );
|
||||||
#Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
#ZM\Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
||||||
csrf_check();
|
csrf_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
# Need to include actions because it does auth
|
# Need to include actions because it does auth
|
||||||
if ( $action ) {
|
if ( $action ) {
|
||||||
if ( file_exists('includes/actions/'.$view.'.php') ) {
|
if ( file_exists('includes/actions/'.$view.'.php') ) {
|
||||||
Logger::Debug("Including includes/actions/$view.php");
|
ZM\Logger::Debug("Including includes/actions/$view.php");
|
||||||
require_once('includes/actions/'.$view.'.php');
|
require_once('includes/actions/'.$view.'.php');
|
||||||
} else {
|
} else {
|
||||||
Warning("No includes/actions/$view.php for action $action");
|
ZM\Warning("No includes/actions/$view.php for action $action");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +226,7 @@ if ( ZM_OPT_USE_AUTH and !isset($user) and ($view != 'login') ) {
|
||||||
header('HTTP/1.1 401 Unauthorized');
|
header('HTTP/1.1 401 Unauthorized');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
Logger::Debug('Redirecting to login');
|
ZM\Logger::Debug('Redirecting to login');
|
||||||
$view = 'none';
|
$view = 'none';
|
||||||
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login';
|
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login';
|
||||||
$request = null;
|
$request = null;
|
||||||
|
@ -240,7 +239,7 @@ if ( ZM_OPT_USE_AUTH and !isset($user) and ($view != 'login') ) {
|
||||||
CSPHeaders($view, $cspNonce);
|
CSPHeaders($view, $cspNonce);
|
||||||
|
|
||||||
if ( $redirect ) {
|
if ( $redirect ) {
|
||||||
Logger::Debug("Redirecting to $redirect");
|
ZM\Logger::Debug("Redirecting to $redirect");
|
||||||
header('Location: '.$redirect);
|
header('Location: '.$redirect);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -248,7 +247,7 @@ if ( $redirect ) {
|
||||||
if ( $request ) {
|
if ( $request ) {
|
||||||
foreach ( getSkinIncludes('ajax/'.$request.'.php', true, true) as $includeFile ) {
|
foreach ( getSkinIncludes('ajax/'.$request.'.php', true, true) as $includeFile ) {
|
||||||
if ( !file_exists($includeFile) )
|
if ( !file_exists($includeFile) )
|
||||||
Fatal("Request '$request' does not exist");
|
ZM\Fatal("Request '$request' does not exist");
|
||||||
require_once $includeFile;
|
require_once $includeFile;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -257,7 +256,7 @@ if ( $request ) {
|
||||||
if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
|
if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
|
||||||
foreach ( $includeFiles as $includeFile ) {
|
foreach ( $includeFiles as $includeFile ) {
|
||||||
if ( !file_exists($includeFile) )
|
if ( !file_exists($includeFile) )
|
||||||
Fatal("View '$view' does not exist");
|
ZM\Fatal("View '$view' does not exist");
|
||||||
require_once $includeFile;
|
require_once $includeFile;
|
||||||
}
|
}
|
||||||
// If the view overrides $view to 'error', and the user is not logged in, then the
|
// If the view overrides $view to 'error', and the user is not logged in, then the
|
||||||
|
|
|
@ -216,6 +216,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Podržava Relativno kretanje',
|
'CanMoveRel' => 'Podržava Relativno kretanje',
|
||||||
'CanPan' => 'Podržava Pomak' ,
|
'CanPan' => 'Podržava Pomak' ,
|
||||||
'CanReset' => 'PodržavaReset',
|
'CanReset' => 'PodržavaReset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Podržava presetove',
|
'CanSetPresets' => 'Podržava presetove',
|
||||||
'CanSleep' => 'Podržava Sleep',
|
'CanSleep' => 'Podržava Sleep',
|
||||||
'CanTilt' => 'Podržava nagib',
|
'CanTilt' => 'Podržava nagib',
|
||||||
|
|
|
@ -209,6 +209,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -205,6 +205,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => '可以相对移动',
|
'CanMoveRel' => '可以相对移动',
|
||||||
'CanPan' => '可以平移' ,
|
'CanPan' => '可以平移' ,
|
||||||
'CanReset' => '可以复位',
|
'CanReset' => '可以复位',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => '可以进行预设',
|
'CanSetPresets' => '可以进行预设',
|
||||||
'CanSleep' => '可以休眠',
|
'CanSleep' => '可以休眠',
|
||||||
'CanTilt' => '可以倾斜',
|
'CanTilt' => '可以倾斜',
|
||||||
|
|
|
@ -205,6 +205,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Umí relativní pohyb',
|
'CanMoveRel' => 'Umí relativní pohyb',
|
||||||
'CanPan' => 'Umí otáčení',
|
'CanPan' => 'Umí otáčení',
|
||||||
'CanReset' => 'Umí reset',
|
'CanReset' => 'Umí reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Umí navolit předvolby',
|
'CanSetPresets' => 'Umí navolit předvolby',
|
||||||
'CanSleep' => 'Může spát',
|
'CanSleep' => 'Může spát',
|
||||||
'CanTilt' => 'Umí náklon',
|
'CanTilt' => 'Umí náklon',
|
||||||
|
|
|
@ -207,6 +207,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Kann relative Bewegung',
|
'CanMoveRel' => 'Kann relative Bewegung',
|
||||||
'CanPan' => 'Kann Pan' ,
|
'CanPan' => 'Kann Pan' ,
|
||||||
'CanReset' => 'Kann Reset',
|
'CanReset' => 'Kann Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Kann Voreinstellungen setzen',
|
'CanSetPresets' => 'Kann Voreinstellungen setzen',
|
||||||
'CanSleep' => 'Kann Sleep',
|
'CanSleep' => 'Kann Sleep',
|
||||||
'CanTilt' => 'Kann Neigung',
|
'CanTilt' => 'Kann Neigung',
|
||||||
|
|
|
@ -206,6 +206,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -216,6 +216,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -156,6 +156,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -205,6 +205,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Puede moverse de forma relativa',
|
'CanMoveRel' => 'Puede moverse de forma relativa',
|
||||||
'CanPan' => 'Puede desplazarse' ,
|
'CanPan' => 'Puede desplazarse' ,
|
||||||
'CanReset' => 'Puede restablecerse',
|
'CanReset' => 'Puede restablecerse',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Puede fefinir programaciones',
|
'CanSetPresets' => 'Puede fefinir programaciones',
|
||||||
'CanSleep' => 'Puede dormirse',
|
'CanSleep' => 'Puede dormirse',
|
||||||
'CanTilt' => 'Puede inclinarse',
|
'CanTilt' => 'Puede inclinarse',
|
||||||
|
|
|
@ -212,6 +212,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -211,6 +211,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Relatif',
|
'CanMoveRel' => 'Relatif',
|
||||||
'CanPan' => 'Panoramique' ,
|
'CanPan' => 'Panoramique' ,
|
||||||
'CanReset' => 'RàZ',
|
'CanReset' => 'RàZ',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Stockage prépos.',
|
'CanSetPresets' => 'Stockage prépos.',
|
||||||
'CanSleep' => 'Veille',
|
'CanSleep' => 'Veille',
|
||||||
'CanTilt' => 'Inclinaison',
|
'CanTilt' => 'Inclinaison',
|
||||||
|
|
|
@ -205,6 +205,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'àôùø úæåæä éçñéú',
|
'CanMoveRel' => 'àôùø úæåæä éçñéú',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'àôùø àúçåì',
|
'CanReset' => 'àôùø àúçåì',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'àôùø îöá ùéðä',
|
'CanSleep' => 'àôùø îöá ùéðä',
|
||||||
'CanTilt' => 'àôùø æòæåò',
|
'CanTilt' => 'àôùø æòæåò',
|
||||||
|
|
|
@ -248,6 +248,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Relatíven tud mozogni',
|
'CanMoveRel' => 'Relatíven tud mozogni',
|
||||||
'CanPan' => 'Tud jobb-bal mozgást' ,
|
'CanPan' => 'Tud jobb-bal mozgást' ,
|
||||||
'CanReset' => 'Tud alaphelyzetbe jönni',
|
'CanReset' => 'Tud alaphelyzetbe jönni',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Tud menteni profilokat',
|
'CanSetPresets' => 'Tud menteni profilokat',
|
||||||
'CanSleep' => 'Tud phihenő üzemmódot',
|
'CanSleep' => 'Tud phihenő üzemmódot',
|
||||||
'CanTilt' => 'Tud fel-le mozgást',
|
'CanTilt' => 'Tud fel-le mozgást',
|
||||||
|
|
|
@ -210,6 +210,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Puo\' Mov. Relativo',
|
'CanMoveRel' => 'Puo\' Mov. Relativo',
|
||||||
'CanPan' => 'Puo\' Pan' ,
|
'CanPan' => 'Puo\' Pan' ,
|
||||||
'CanReset' => 'Puo\' Reset',
|
'CanReset' => 'Puo\' Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Puo\' impostare preset',
|
'CanSetPresets' => 'Puo\' impostare preset',
|
||||||
'CanSleep' => 'Puo\' andare in sleep',
|
'CanSleep' => 'Puo\' andare in sleep',
|
||||||
'CanTilt' => 'Puo\' Tilt',
|
'CanTilt' => 'Puo\' Tilt',
|
||||||
|
|
|
@ -206,6 +206,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -206,6 +206,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relatief',
|
'CanMoveRel' => 'Can Move Relatief',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -220,6 +220,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -145,6 +145,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Can Move Relative',
|
'CanMoveRel' => 'Can Move Relative',
|
||||||
'CanPan' => 'Can Pan' ,
|
'CanPan' => 'Can Pan' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Can Tilt',
|
'CanTilt' => 'Can Tilt',
|
||||||
|
|
|
@ -176,6 +176,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Mişcare relativă',
|
'CanMoveRel' => 'Mişcare relativă',
|
||||||
'CanPan' => 'Rotativ' ,
|
'CanPan' => 'Rotativ' ,
|
||||||
'CanReset' => 'Can Reset',
|
'CanReset' => 'Can Reset',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Can Set Presets',
|
'CanSetPresets' => 'Can Set Presets',
|
||||||
'CanSleep' => 'Can Sleep',
|
'CanSleep' => 'Can Sleep',
|
||||||
'CanTilt' => 'Se poate înclina',
|
'CanTilt' => 'Se poate înclina',
|
||||||
|
|
|
@ -206,6 +206,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Относительное перемещение',
|
'CanMoveRel' => 'Относительное перемещение',
|
||||||
'CanPan' => 'Панорама' ,
|
'CanPan' => 'Панорама' ,
|
||||||
'CanReset' => 'Сброс',
|
'CanReset' => 'Сброс',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Создание предустановок',
|
'CanSetPresets' => 'Создание предустановок',
|
||||||
'CanSleep' => 'Сон',
|
'CanSleep' => 'Сон',
|
||||||
'CanTilt' => 'Наклон',
|
'CanTilt' => 'Наклон',
|
||||||
|
|
|
@ -206,6 +206,7 @@ $SLANG = array(
|
||||||
'CanMoveRel' => 'Har relativ förflyttning',
|
'CanMoveRel' => 'Har relativ förflyttning',
|
||||||
'CanPan' => 'Har panorering',
|
'CanPan' => 'Har panorering',
|
||||||
'CanReset' => 'Har återställning',
|
'CanReset' => 'Har återställning',
|
||||||
|
'CanReboot' => 'Can Reboot',
|
||||||
'CanSetPresets' => 'Har förinställningar',
|
'CanSetPresets' => 'Har förinställningar',
|
||||||
'CanSleep' => 'Kan vila',
|
'CanSleep' => 'Kan vila',
|
||||||
'CanTilt' => 'Kan tilta',
|
'CanTilt' => 'Kan tilta',
|
||||||
|
|
|
@ -24,6 +24,7 @@ function getControlCommands( $monitor ) {
|
||||||
$cmds['Wake'] = 'wake';
|
$cmds['Wake'] = 'wake';
|
||||||
$cmds['Sleep'] = 'sleep';
|
$cmds['Sleep'] = 'sleep';
|
||||||
$cmds['Reset'] = 'reset';
|
$cmds['Reset'] = 'reset';
|
||||||
|
$cmds['Reboot'] = 'reboot';
|
||||||
|
|
||||||
$cmds['PresetSet'] = 'presetSet';
|
$cmds['PresetSet'] = 'presetSet';
|
||||||
$cmds['PresetGoto'] = 'presetGoto';
|
$cmds['PresetGoto'] = 'presetGoto';
|
||||||
|
@ -319,6 +320,11 @@ function controlPower( $monitor, $cmds ) {
|
||||||
if ( $monitor->CanReset() ) {
|
if ( $monitor->CanReset() ) {
|
||||||
?>
|
?>
|
||||||
<button type="button" class="ptzTextBtn" value="Reset" onclick="controlCmd('<?php echo $cmds['Reset'] ?>')"><?php echo translate('Reset') ?></button>
|
<button type="button" class="ptzTextBtn" value="Reset" onclick="controlCmd('<?php echo $cmds['Reset'] ?>')"><?php echo translate('Reset') ?></button>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
if ( $monitor->CanReboot() ) {
|
||||||
|
?>
|
||||||
|
<button type="button" class="ptzTextBtn" value="Reboot" onclick="controlCmd('<?php echo $cmds['Reboot'] ?>')"><?php echo translate('Reboot') ?></button>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -33,7 +33,7 @@ var popupSizes = {
|
||||||
'cycle': {'addWidth': 32, 'minWidth': 384, 'addHeight': 62},
|
'cycle': {'addWidth': 32, 'minWidth': 384, 'addHeight': 62},
|
||||||
'device': {'width': 260, 'height': 150},
|
'device': {'width': 260, 'height': 150},
|
||||||
'devices': {'width': 400, 'height': 240},
|
'devices': {'width': 400, 'height': 240},
|
||||||
'donate': {'width': 500, 'height': 280},
|
'donate': {'width': 500, 'height': 480},
|
||||||
'download': {'width': 350, 'height': 215},
|
'download': {'width': 350, 'height': 215},
|
||||||
'event': {'addWidth': 108, 'minWidth': 496, 'addHeight': 230, 'minHeight': 540},
|
'event': {'addWidth': 108, 'minWidth': 496, 'addHeight': 230, 'minHeight': 540},
|
||||||
'eventdetail': {'width': 600, 'height': 420},
|
'eventdetail': {'width': 600, 'height': 420},
|
||||||
|
|
|
@ -59,6 +59,7 @@ else
|
||||||
'CanWake' => "",
|
'CanWake' => "",
|
||||||
'CanSleep' => "",
|
'CanSleep' => "",
|
||||||
'CanReset' => "",
|
'CanReset' => "",
|
||||||
|
'CanReboot' => "",
|
||||||
'CanMove' => "",
|
'CanMove' => "",
|
||||||
'CanMoveDiag' => "",
|
'CanMoveDiag' => "",
|
||||||
'CanMoveMap' => "",
|
'CanMoveMap' => "",
|
||||||
|
@ -352,6 +353,7 @@ switch ( $tab )
|
||||||
<tr><th scope="row"><?php echo translate('CanWake') ?></th><td><input type="checkbox" name="newControl[CanWake]" value="1"<?php if ( !empty($newControl['CanWake']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
<tr><th scope="row"><?php echo translate('CanWake') ?></th><td><input type="checkbox" name="newControl[CanWake]" value="1"<?php if ( !empty($newControl['CanWake']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('CanSleep') ?></th><td><input type="checkbox" name="newControl[CanSleep]" value="1"<?php if ( !empty($newControl['CanSleep']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
<tr><th scope="row"><?php echo translate('CanSleep') ?></th><td><input type="checkbox" name="newControl[CanSleep]" value="1"<?php if ( !empty($newControl['CanSleep']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||||
<tr><th scope="row"><?php echo translate('CanReset') ?></th><td><input type="checkbox" name="newControl[CanReset]" value="1"<?php if ( !empty($newControl['CanReset']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
<tr><th scope="row"><?php echo translate('CanReset') ?></th><td><input type="checkbox" name="newControl[CanReset]" value="1"<?php if ( !empty($newControl['CanReset']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||||
|
<tr><th scope="row"><?php echo translate('CanReboot') ?></th><td><input type="checkbox" name="newControl[CanReboot]" value="1"<?php if ( !empty($newControl['CanReboot']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||||
<?php
|
<?php
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,25 +18,24 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
//
|
//
|
||||||
|
|
||||||
if ( !canEdit( 'System' ) )
|
if ( !canEdit('System') ) {
|
||||||
{
|
$view = 'error';
|
||||||
$view = "error";
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = array(
|
$options = array(
|
||||||
"go" => translate('DonateYes'),
|
"go" => translate('DonateYes'),
|
||||||
"hour" => translate('DonateRemindHour'),
|
"hour" => translate('DonateRemindHour'),
|
||||||
"day" => translate('DonateRemindDay'),
|
"day" => translate('DonateRemindDay'),
|
||||||
"week" => translate('DonateRemindWeek'),
|
"week" => translate('DonateRemindWeek'),
|
||||||
"month" => translate('DonateRemindMonth'),
|
"month" => translate('DonateRemindMonth'),
|
||||||
"never" => translate('DonateRemindNever'),
|
"never" => translate('DonateRemindNever'),
|
||||||
"already" => translate('DonateAlready'),
|
"already" => translate('DonateAlready'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$focusWindow = true;
|
$focusWindow = true;
|
||||||
|
|
||||||
xhtmlHeaders(__FILE__, translate('Donate') );
|
xhtmlHeaders(__FILE__, translate('Donate'));
|
||||||
?>
|
?>
|
||||||
<body>
|
<body>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
|
@ -46,17 +45,17 @@ xhtmlHeaders(__FILE__, translate('Donate') );
|
||||||
</div>
|
</div>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<form name="contentForm" id="contentForm" method="post" action="?">
|
<form name="contentForm" id="contentForm" method="post" action="?">
|
||||||
<input type="hidden" name="view" value="none"/>
|
<input type="hidden" name="view" value="donate"/>
|
||||||
<input type="hidden" name="action" value="donate"/>
|
<input type="hidden" name="action" value="donate"/>
|
||||||
<p>
|
<p>
|
||||||
<?php echo translate('DonateEnticement') ?>
|
<?php echo translate('DonateEnticement') ?>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<?php echo buildSelect( "option", $options ); ?>
|
<?php echo buildSelect('option', $options); ?>
|
||||||
</p>
|
</p>
|
||||||
<div id="contentButtons">
|
<div id="contentButtons">
|
||||||
<input type="submit" value="<?php echo translate('Apply') ?>" data-on-click-this="submitForm">
|
<button type="submit"><?php echo translate('Apply') ?></button>
|
||||||
<input type="button" value="<?php echo translate('Close') ?>" data-on-click="closeWindow">
|
<button type="button" data-on-click="closeWindow"><?php echo translate('Close') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -26,10 +26,11 @@ function cycleNext() {
|
||||||
window.location.replace('?view=cycle&mid='+monitorData[monIdx].id+'&mode='+mode, cycleRefreshTimeout);
|
window.location.replace('?view=cycle&mid='+monitorData[monIdx].id+'&mode='+mode, cycleRefreshTimeout);
|
||||||
}
|
}
|
||||||
function cyclePrev() {
|
function cyclePrev() {
|
||||||
if ( monIdx )
|
if (monIdx) {
|
||||||
monIdx -= 1;
|
monIdx -= 1;
|
||||||
else
|
} else {
|
||||||
monIdx = monitorData.length-1;
|
monIdx = monitorData.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
window.location.replace('?view=cycle&mid='+monitorData[monIdx].id+'&mode='+mode, cycleRefreshTimeout);
|
window.location.replace('?view=cycle&mid='+monitorData[monIdx].id+'&mode='+mode, cycleRefreshTimeout);
|
||||||
}
|
}
|
||||||
|
@ -82,9 +83,9 @@ function changeScale() {
|
||||||
var scale = $('scale').get('value');
|
var scale = $('scale').get('value');
|
||||||
$('width').set('value', 'auto');
|
$('width').set('value', 'auto');
|
||||||
$('height').set('value', 'auto');
|
$('height').set('value', 'auto');
|
||||||
Cookie.write('zmCycleScale', scale, { duration: 10*365 });
|
Cookie.write('zmCycleScale', scale, {duration: 10*365});
|
||||||
Cookie.write('zmCycleWidth', 'auto', { duration: 10*365 });
|
Cookie.write('zmCycleWidth', 'auto', {duration: 10*365});
|
||||||
Cookie.write('zmCycleHeight', 'auto', { duration: 10*365 });
|
Cookie.write('zmCycleHeight', 'auto', {duration: 10*365});
|
||||||
var newWidth = ( monitorData[monIdx].width * scale ) / SCALE_BASE;
|
var newWidth = ( monitorData[monIdx].width * scale ) / SCALE_BASE;
|
||||||
var newHeight = ( monitorData[monIdx].height * scale ) / SCALE_BASE;
|
var newHeight = ( monitorData[monIdx].height * scale ) / SCALE_BASE;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,3 @@
|
||||||
function submitForm( element ) {
|
|
||||||
var form = element.form;
|
|
||||||
if ( form.option.selectedIndex == 0 ) {
|
|
||||||
form.view.value = currentView;
|
|
||||||
} else {
|
|
||||||
form.view.value = 'none';
|
|
||||||
}
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( action == "donate" && option == "go" ) {
|
if ( action == "donate" && option == "go" ) {
|
||||||
zmWindow();
|
zmWindow();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ function Monitor(monitorData) {
|
||||||
this.alarmState = STATE_IDLE;
|
this.alarmState = STATE_IDLE;
|
||||||
this.lastAlarmState = STATE_IDLE;
|
this.lastAlarmState = STATE_IDLE;
|
||||||
this.streamCmdParms = 'view=request&request=stream&connkey='+this.connKey;
|
this.streamCmdParms = 'view=request&request=stream&connkey='+this.connKey;
|
||||||
this.onclick = monitorData.onclick;
|
|
||||||
if ( auth_hash ) {
|
if ( auth_hash ) {
|
||||||
this.streamCmdParms += '&auth='+auth_hash;
|
this.streamCmdParms += '&auth='+auth_hash;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +25,30 @@ function Monitor(monitorData) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.onclick = function() {
|
||||||
|
var el = this;
|
||||||
|
var url = '?view=watch&mid='+this.id;
|
||||||
|
var name = 'zmWatch'+this.id;
|
||||||
|
var tag = 'watch';
|
||||||
|
var width = el.getAttribute("data-window-width");
|
||||||
|
var height = el.getAttribute("data-window-height");
|
||||||
|
evt.preventDefault();
|
||||||
|
createPopup(url, name, tag, width, height);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setup_onclick = function() {
|
||||||
|
document.querySelectorAll('#imageFeed'+this.id).forEach(function(el) {
|
||||||
|
el.addEventListener('click', this.onclick);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.disable_onclick = function() {
|
||||||
|
document.querySelectorAll('#imageFeed'+this.id).forEach(function(el) {
|
||||||
|
el.removeEventListener('click',this.onclick);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.setStateClass = function(element, stateClass) {
|
this.setStateClass = function(element, stateClass) {
|
||||||
if ( !element.hasClass(stateClass) ) {
|
if ( !element.hasClass( stateClass ) ) {
|
||||||
if ( stateClass != 'alarm' )
|
if ( stateClass != 'alarm' )
|
||||||
element.removeClass('alarm');
|
element.removeClass('alarm');
|
||||||
if ( stateClass != 'alert' )
|
if ( stateClass != 'alert' )
|
||||||
|
@ -359,8 +380,7 @@ function edit_layout(button) {
|
||||||
|
|
||||||
for ( var i = 0, length = monitors.length; i < length; i++ ) {
|
for ( var i = 0, length = monitors.length; i < length; i++ ) {
|
||||||
var monitor = monitors[i];
|
var monitor = monitors[i];
|
||||||
monitor_feed = $j('#imageFeed'+monitor.id)[0];
|
monitor.disable_onclick();
|
||||||
monitor_feed.onclick = '';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$j('#monitors .monitorFrame').draggable({
|
$j('#monitors .monitorFrame').draggable({
|
||||||
|
@ -435,8 +455,9 @@ function initPage() {
|
||||||
if ( monitors[i].type == 'WebSite' && interval > 0 ) {
|
if ( monitors[i].type == 'WebSite' && interval > 0 ) {
|
||||||
setInterval(reloadWebSite, interval*1000, i);
|
setInterval(reloadWebSite, interval*1000, i);
|
||||||
}
|
}
|
||||||
|
monitors[i].setup_onclick();
|
||||||
}
|
}
|
||||||
selectLayout('#zmMontageLayout');
|
selectLayout('#zmMontageLayout');
|
||||||
}
|
}
|
||||||
// Kick everything off
|
// Kick everything off
|
||||||
window.addEventListener( 'DOMContentLoaded', initPage );
|
window.addEventListener('DOMContentLoaded', initPage);
|
||||||
|
|
|
@ -448,10 +448,16 @@ function cmdEnableAlarms() {
|
||||||
|
|
||||||
function cmdForceAlarm() {
|
function cmdForceAlarm() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm");
|
alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm");
|
||||||
|
if (window.event) {
|
||||||
|
window.event.preventDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdCancelForcedAlarm() {
|
function cmdCancelForcedAlarm() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm");
|
alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm");
|
||||||
|
if (window.event) {
|
||||||
|
window.event.preventDefault();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,10 +199,7 @@ foreach ( $monitors as $monitor ) {
|
||||||
<div id="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
|
<div id="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
|
||||||
<div
|
<div
|
||||||
id="imageFeed<?php echo $monitor->Id() ?>"
|
id="imageFeed<?php echo $monitor->Id() ?>"
|
||||||
class="imageFeed popup-link"
|
class="imageFeed"
|
||||||
data-url="?view=watch&mid=<?php echo $monitor->Id() ?>"
|
|
||||||
data-name="zmWatch<?php echo $monitor->Id() ?>"
|
|
||||||
data-tag="watch"
|
|
||||||
data-width="<?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>"
|
data-width="<?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>"
|
||||||
data-height="<?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?>">
|
data-height="<?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?>">
|
||||||
<?php
|
<?php
|
||||||
|
|
Loading…
Reference in New Issue