Merge branch 'storageareas' into zma_to_thread

This commit is contained in:
Isaac Connor 2017-11-21 12:28:41 -05:00
commit c6515b7564
20 changed files with 797 additions and 346 deletions

View File

@ -30,6 +30,7 @@ env:
- OS=el DIST=7
- OS=fedora DIST=25
- OS=fedora DIST=26 DOCKER_REPO=knnniggett/packpack
- OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack
- OS=ubuntu DIST=trusty
- OS=ubuntu DIST=xenial
- OS=ubuntu DIST=trusty ARCH=i386

View File

@ -31,6 +31,8 @@ This is the recommended method to install ZoneMinder onto your system. ZoneMinde
- Fedora via [RPM Fusion](http://rpmfusion.org)
- OpenSuse via [third party repository](http://www.zoneminder.com/wiki/index.php/Installing_using_ZoneMinder_RPMs_for_SuSE)
- Mageia from their default repository
- Arch via the [AUR](https://aur.archlinux.org/packages/zoneminder/)
- Gentoo from their [default repository](https://packages.gentoo.org/packages/www-misc/zoneminder)
If a repository that hosts ZoneMinder packages is not available for your distro, then you are encouraged to build your own package, rather than build from source. While each distro is different in ways that set it apart from all the others, they are often similar enough to allow you to adapt another distro's package building instructions to your own.

View File

@ -16,3 +16,5 @@ SET @s = (SELECT IF(
PREPARE stmt FROM @s;
EXECUTE stmt;
INSERT INTO `Controls` VALUES (28,'Floureon 1080P','Ffmpeg','Floureon',0,0,0,1,0,0,0,1,1,18,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,8,0,0,1,0,0,0,0,1,1,8,0,0,0,0);

View File

@ -15,9 +15,11 @@ achieve the same result by running:
::
tasksel install lamp-server
sudo tasksel install lamp-server
During installation it will ask you to set up a master/root password for the MySQL.
Installing LAMP is not ZoneMinder specific so you will find plenty of resources to
guide you with a quick search.
**Step 1:** Either run commands in this install using sudo or use the below to become root
::

View File

@ -0,0 +1,390 @@
# Modified on 2017-11-17 by Ognyan Bankov
# ==========================================================================
#
# ZoneMinder Floureon 1080p IP Control Protocol Module, $Date: 2017-11-17 09:20:00 +0000 $, $Revision: 0001 $
# Copyright (C) 2017 Ognyan Bankov
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================
#
# This module contains the implementation of the Floureon 1080p 18x (Model: BT-HD54F) IP camera control
# protocol. It should work with other Floureon cameras too.
#
#
package MyAgent;
use base 'LWP::UserAgent';
package ZoneMinder::Control::Floureon;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# Floureon IP Control Protocol
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
my $logindetails = "";
bless( $self, $class );
srand( time() );
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
if ( exists($self->{$name}) )
{
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
}
our $stop_command;
sub open
{
my $self = shift;
$self->loadMonitor();
$self->{ua} = MyAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/" );
$self->{state} = 'open';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd"."&".$self->{Monitor}->{ControlDevice});
print ("Sending $req\n");
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
Error( "Error REALLY check failed:'".$res->status_line()."'" );
Error ("Cmd:".$req);
}
return( $result );
}
sub reset
{
my $self = shift;
Debug( "Camera Reset" );
my $cmd = "reboot.cgi?";
$self->sendCmd( $cmd );
}
# PP - in all move operations, added auto stop after timeout
#Up Arrow
sub moveConUp
{
my $self = shift;
my $params = shift;
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Up" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=1&PanSpeed=6&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Down Arrow
sub moveConDown
{
my $self = shift;
my $params = shift;
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Down" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=2&PanSpeed=6&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Left Arrow
sub moveConLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
Debug( "Move Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=3&PanSpeed=$panspeed&TiltSpeed=6";
$self->sendCmd( $cmd );
$self->autoStop($panspeed);
}
#Right Arrow
sub moveConRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
Debug( "Move Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=4&PanSpeed=$panspeed&TiltSpeed=6";
$self->sendCmd( $cmd );
$self->autoStop($panspeed);
}
#Diagonally Up Right Arrow
sub moveConUpRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Up Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=7&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Down Right Arrow
sub moveConDownRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Down Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=8&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Up Left Arrow
sub moveConUpLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Up Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=5&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Down Left Arrow
sub moveConDownLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Down Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=6&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Stop
sub moveStop
{
my $self = shift;
Debug( "Move Stop" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Stop=0";
$self->sendCmd( $cmd );
}
sub zoomConTele
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Zoom=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub zoomConWide
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Zoom=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub focusConNear
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Focus=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub focusConFar
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Focus=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub irisConOpen
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Iris=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub irisConClose
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Iris=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
#Set preset
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=0";
$self->sendCmd( $cmd );
}
#Goto preset
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=1";
$self->sendCmd( $cmd );
}
sub autoStop
{
my $self = shift;
my $timeout = shift;
if ($timeout)
{
if ($timeout > 1) {
usleep(100000*$timeout);
}
}
Debug( "Auto Stop" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Stop=0";
$self->sendCmd( $cmd );
}
1;
__END__
=head1 Floureon
ZoneMinder::Database - Perl extension for Floureon 1080P
=head1 SYNOPSIS
Control script for Floureon 1080P IP camera
=head1 DESCRIPTION
When setuping you monitor in the "Control" tab:
1. Select "Control type": Floureon 1080P
2. Leave "Control device" empty
3. Fill "Control Address" like username:password@ip/domain. Example: admin:admin123@192.168.1.110
=head2 EXPORT
None by default.
=head1 SEE ALSO
=head1 AUTHOR
Ognyan Bankov, E<lt>ogibankov@gmail.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2017 Ognyan Bankov
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -21,34 +21,6 @@
#
# ==========================================================================
=head1 NAME
zmaudit.pl - ZoneMinder event file system and database consistency checker
=head1 SYNOPSIS
zmaudit.pl [-r,-report|-i,-interactive]
=head1 DESCRIPTION
This script checks for consistency between the event filesystem and
the database. If events are found in one and not the other they are
deleted (optionally). Additionally any monitor event directories that
do not correspond to a database monitor are similarly disposed of.
However monitors in the database that don't have a directory are left
alone as this is valid if they are newly created and have no events
yet.
=head1 OPTIONS
-c, --continuous - Run continuously
-i, --interactive - Ask before applying any changes
-m, --monitor_id - Restrict zmaudit actions to events pertaining to the specified monitor id
-r, --report - Just report don't actually do anything
-v, --version - Print the installed version of ZoneMinder
=cut
use strict;
use bytes;
@ -701,3 +673,30 @@ sub delete_empty_directories {
1;
__END__
=head1 NAME
zmaudit.pl - ZoneMinder event file system and database consistency checker
=head1 SYNOPSIS
zmaudit.pl [-r,-report|-i,-interactive]
=head1 DESCRIPTION
This script checks for consistency between the event filesystem and
the database. If events are found in one and not the other they are
deleted (optionally). Additionally any monitor event directories that
do not correspond to a database monitor are similarly disposed of.
However monitors in the database that don't have a directory are left
alone as this is valid if they are newly created and have no events
yet.
=head1 OPTIONS
-c, --continuous - Run continuously
-i, --interactive - Ask before applying any changes
-r, --report - Just report don't actually do anything
-v, --version - Print the installed version of ZoneMinder
=cut

View File

@ -21,20 +21,6 @@
#
# ==========================================================================
=head1 NAME
zmpkg.pl - ZoneMinder Package Control Script
=head1 SYNOPSIS
zmpkg.pl {start|stop|restart|status|logrot|'state'|version}
=head1 DESCRIPTION
This script is used to start and stop the ZoneMinder package primarily to
allow command line control for automatic restart on reboot (see zm script)
=cut
use strict;
use bytes;
@ -61,48 +47,41 @@ logInit();
my $command = $ARGV[0]||'';
if ( $command eq 'version' ) {
print ZoneMinder::Base::ZM_VERSION . "\n";
exit(0);
print ZoneMinder::Base::ZM_VERSION . "\n";
exit(0);
}
my $state;
my $dbh;
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ )
{
if ( $command )
{
$dbh = zmDbConnect();
# Check to see if it's a valid run state
my $sql = 'select * from States where Name = ?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $command )
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $state = $sth->fetchrow_hashref() )
{
$state->{Name} = $command;
$state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) )
{
my ( $id, $function, $enabled ) = split( /:/, $_ );
push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled }
);
}
$store_state=$command; # PP - Remember the name that was passed to search in DB
$command = 'state';
}
else
{
$command = undef;
}
}
if ( !$command )
{
pod2usage(-exitstatus => -1);
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) {
if ( $command ) {
$dbh = zmDbConnect();
# Check to see if it's a valid run state
my $sql = 'SELECT * FROM States WHERE Name=?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $command )
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $state = $sth->fetchrow_hashref() ) {
$state->{Name} = $command;
$state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) ) {
my ( $id, $function, $enabled ) = split( /:/, $_ );
push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled }
);
}
$store_state=$command; # PP - Remember the name that was passed to search in DB
$command = 'state';
} else {
$command = undef;
}
}
if ( !$command ) {
pod2usage(-exitstatus => -1);
}
}
$dbh = zmDbConnect() if ! $dbh;
# PP - Sane state check
@ -110,324 +89,293 @@ isActiveSanityCheck();
# Move to the right place
chdir( $Config{ZM_PATH_WEB} )
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" );
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" );
my $dbg_id = "";
my $dbg_id = '';
Info( "Command: $command\n" );
Info( "Command: $command\n" );
my $retval = 0;
my $retval = 0;
if ( $command eq "state" )
{
if ( $command eq 'state' ) {
Info( "Updating DB: $state->{Name}\n" );
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=? ORDER BY Id ASC' : 'SELECT * FROM Monitors ORDER BY Id ASC';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() )
{
foreach my $definition ( @{$state->{Definitions}} )
{
if ( $monitor->{Id} =~ /^$definition->{Id}$/ )
{
$monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
)
{
my $sql = "update Monitors set Function = ?, Enabled = ? where Id = ?";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
or Fatal( "Can't execute: ".$sth->errstr() );
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) {
foreach my $definition ( @{$state->{Definitions}} ) {
if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) {
$monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
) {
my $sql = 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
or Fatal( "Can't execute: ".$sth->errstr() );
}
}
$sth->finish();
# PP - Now mark a specific state as active
# PP - Now mark a specific state as active
resetStates();
Info ("Marking $store_state as Enabled");
$sql = "update States set IsActive = '1' where Name = ?";
$sql = "UPDATE States SET IsActive = '1' WHERE Name = ?";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute( $store_state )
or Fatal( "Can't execute: ".$sth->errstr() );
or Fatal( "Can't execute: ".$sth->errstr() );
# PP - zero out other states isActive
$command = "restart";
}
# PP - zero out other states isActive
$command = 'restart';
}
# Check if we are running systemd and if we have been called by the system
if ( $command =~ /^(start|stop|restart)$/ )
{
# We have to detaint to keep perl from complaining
$command = $1;
if ( $command =~ /^(start|stop|restart)$/ ) {
# We have to detaint to keep perl from complaining
$command = $1;
if ( systemdRunning() && !calledBysystem() ) {
qx(@BINDIR@/zmsystemctl.pl $command);
$command = "";
}
if ( systemdRunning() && !calledBysystem() ) {
qx(@BINDIR@/zmsystemctl.pl $command);
$command = '';
}
}
if ( $command =~ /^(?:stop|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command =~ /^(?:stop|restart)$/ ) {
my $status = runCommand('zmdc.pl check');
if ( $status eq "running" )
{
runCommand( "zmdc.pl shutdown" );
zmMemTidy();
}
else
{
$retval = 1;
}
if ( $status eq 'running' ) {
runCommand('zmdc.pl shutdown');
zmMemTidy();
} else {
$retval = 1;
}
}
#runCommand( "zmupdate.pl -f" );
if ( $command =~ /^(?:start|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command =~ /^(?:start|restart)$/ ) {
my $status = runCommand('zmdc.pl check');
if ( $status eq "stopped" )
{
if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
)
{
Fatal( "Version mismatch, system is version ".ZM_VERSION
.", database is ".$Config{ZM_DYN_DB_VERSION}
.", please run zmupdate.pl to update."
);
exit( -1 );
}
if ( $status eq 'stopped' ) {
if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
) {
Fatal( 'Version mismatch, system is version '.ZM_VERSION
.', database is '.$Config{ZM_DYN_DB_VERSION}
.', please run zmupdate.pl to update.'
);
exit( -1 );
}
# Recreate the temporary directory if it's been wiped
verifyFolder("@ZM_TMPDIR@");
# Recreate the temporary directory if it's been wiped
verifyFolder('@ZM_TMPDIR@');
# Recreate the run directory if it's been wiped
verifyFolder("@ZM_RUNDIR@");
# Recreate the run directory if it's been wiped
verifyFolder('@ZM_RUNDIR@');
# Recreate the sock directory if it's been wiped
verifyFolder("@ZM_SOCKDIR@");
# Recreate the sock directory if it's been wiped
verifyFolder('@ZM_SOCKDIR@');
zmMemTidy();
runCommand( "zmdc.pl startup" );
zmMemTidy();
runCommand('zmdc.pl startup');
if ( $Config{ZM_SERVER_ID} ) {
Info( "Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
if ( $Config{ZM_SERVER_ID} ) {
Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
} else {
Info('Single server configuration detected. Starting up services.');
}
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) {
if ( $monitor->{Function} ne 'None' ) {
if ( $monitor->{Type} eq 'Local' ) {
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
} else {
Info( "Single server configuration detected. Starting up services." );
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" );
}
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() )
{
if ( $monitor->{Function} ne 'None' )
{
if ( $monitor->{Type} eq 'Local' )
{
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
}
else
{
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" );
}
if ( $monitor->{Function} ne 'Monitor' )
{
#runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
}
if ( $Config{ZM_OPT_CONTROL} )
{
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' )
{
if ( $monitor->{Controllable} && $monitor->{TrackMotion} )
{
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
}
}
}
if ( $Config{ZM_OPT_CONTROL} ) {
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) {
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
}
}
}
$sth->finish();
}
}
$sth->finish();
# This is now started unconditionally
runCommand( "zmdc.pl start zmfilter.pl" );
if ( $Config{ZM_RUN_AUDIT} )
{
runCommand( "zmdc.pl start zmaudit.pl -c" );
}
if ( $Config{ZM_OPT_TRIGGERS} )
{
runCommand( "zmdc.pl start zmtrigger.pl" );
}
if ( $Config{ZM_OPT_X10} )
{
runCommand( "zmdc.pl start zmx10.pl -c start" );
}
runCommand( "zmdc.pl start zmwatch.pl" );
if ( $Config{ZM_CHECK_FOR_UPDATES} )
{
runCommand( "zmdc.pl start zmupdate.pl -c" );
}
if ( $Config{ZM_TELEMETRY_DATA} )
{
runCommand( "zmdc.pl start zmtelemetry.pl" );
}
# This is now started unconditionally
runCommand('zmdc.pl start zmfilter.pl');
if ( $Config{ZM_RUN_AUDIT} ) {
runCommand('zmdc.pl start zmaudit.pl -c');
}
else
{
$retval = 1;
if ( $Config{ZM_OPT_TRIGGERS} ) {
runCommand('zmdc.pl start zmtrigger.pl');
}
if ( $Config{ZM_OPT_X10} ) {
runCommand('zmdc.pl start zmx10.pl -c start');
}
runCommand('zmdc.pl start zmwatch.pl');
if ( $Config{ZM_CHECK_FOR_UPDATES} ) {
runCommand('zmdc.pl start zmupdate.pl -c');
}
if ( $Config{ZM_TELEMETRY_DATA} ) {
runCommand('zmdc.pl start zmtelemetry.pl');
}
} else {
$retval = 1;
}
}
if ( $command eq "status" )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command eq 'status' ) {
my $status = runCommand('zmdc.pl check');
print( STDOUT $status."\n" );
}
if ( $command eq "logrot" )
{
runCommand( "zmdc.pl logrot" );
print( STDOUT $status."\n" );
} elsif ( $command eq 'logrot' ) {
runCommand('zmdc.pl logrot');
}
exit( $retval );
# PP - Make sure isActive is on and only one
sub isActiveSanityCheck
{
sub isActiveSanityCheck {
Info ("Sanity checking States table...");
$dbh = zmDbConnect() if ! $dbh;
# PP - First, make sure default exists and there is only one
my $sql = "select Name from States where Name = 'default'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
Info('Sanity checking States table...');
$dbh = zmDbConnect() if ! $dbh;
if ($sth->rows != 1) # PP - no row, or too many rows. Either case is an error
{
Info( "Fixing States table - either no default state or duplicate default states" );
$sql = "delete from States where Name = 'default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "insert into States (Name,Definition,IsActive) VALUES ('default','','1');";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
# PP - First, make sure default exists and there is only one
my $sql = "SELECT Name FROM States WHERE Name='default'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $sth->rows != 1 ) {
# PP - no row, or too many rows. Either case is an error
Info( 'Fixing States table - either no default state or duplicate default states' );
$sql = "DELETE FROM States WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
# PP - Now make sure no two states have IsActive=1
$sql = "select Name from States where IsActive = '1'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
# PP - Now make sure no two states have IsActive=1
$sql = "SELECT Name FROM States WHERE IsActive = '1'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $sth->rows != 1 )
{
Info( "Fixing States table so only one run state is active" );
resetStates();
$sql = "update States set IsActive='1' WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
if ( $sth->rows != 1 ) {
Info( 'Fixing States table so only one run state is active' );
resetStates();
$sql = "UPDATE States SET IsActive='1' WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
}
# PP - zeroes out isActive for all states
sub resetStates
{
$dbh = zmDbConnect() if ! $dbh;
my $sql = "update States set IsActive = '0'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
sub resetStates {
$dbh = zmDbConnect() if ! $dbh;
my $sql = "UPDATE States SET IsActive='0'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
sub systemdRunning
{
my $result = 0;
sub systemdRunning {
my $result = 0;
my $output = qx(ps -o comm="" -p 1);
chomp( $output );
my $output = qx(ps -o comm="" -p 1);
chomp( $output );
if ($output =~ /systemd/) {
$result = 1;
if ( $output =~ /systemd/ ) {
$result = 1;
}
return $result;
}
sub calledBysystem {
my $result = 0;
my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid);
chomp( $output );
if ($output =~ /^(?:systemd|init)$/) {
$result = 1;
}
return $result;
}
sub verifyFolder {
my $folder = shift;
# Recreate the temporary directory if it's been wiped
if ( !-e $folder ) {
Debug( "Recreating directory '$folder'" );
mkdir( $folder, 0774 )
or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> );
if ( $runName ne $Config{ZM_WEB_USER} ) {
# Not running as web user, so should be root in which case
# chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} )
or Fatal( "Can't get user details for web user '"
.$Config{ZM_WEB_USER}."': $!"
);
chown( $webUid, $webGid, "$folder" )
or Fatal( "Can't change ownership of directory '$folder' to '"
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!"
);
}
return $result;
}
}
sub calledBysystem
{
my $result = 0;
my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid);
chomp( $output );
if ($output =~ /^(?:systemd|init)$/) {
$result = 1;
}
return $result;
}
sub verifyFolder
{
my $folder = shift;
# Recreate the temporary directory if it's been wiped
if ( !-e $folder )
{
Debug( "Recreating directory '$folder'" );
mkdir( "$folder", 0774 )
or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> );
if ( $runName ne $Config{ZM_WEB_USER} )
{
# Not running as web user, so should be root in which case
# chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} )
or Fatal( "Can't get user details for web user '"
.$Config{ZM_WEB_USER}."': $!"
);
chown( $webUid, $webGid, "$folder" )
or Fatal( "Can't change ownership of directory '$folder' to '"
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!"
);
}
}
}
1;
__END__
=head1 NAME
zmpkg.pl - ZoneMinder Package Control Script
=head1 SYNOPSIS
zmpkg.pl {start|stop|restart|status|logrot|'state'|version}
=head1 DESCRIPTION
This script is used to start and stop the ZoneMinder package primarily to
allow command line control for automatic restart on reboot (see zm script)
=cut

View File

@ -180,7 +180,7 @@ while( 1 ) {
my $diskspace_sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
foreach my $Storage ( ZoneMinder::Storage->find() ) {
Error("Updating displace for $$Storage{Name}");
Error("Updating disk space for $$Storage{Name}");
$diskspace_sth->execute( $$Storage{Id} ) or Error( "Can't execute: ".$diskspace_sth->errstr() );
}
$diskspace_sth->finish();

View File

@ -8,6 +8,13 @@ exit;
fi
DEBUILD=`which debuild`;
if [ "$DEBUILD" == "" ]; then
echo "You must install the devscripts package. Try sudo apt-get install devscripts";
exit;
fi
for i in "$@"
do
case $i in

View File

@ -124,7 +124,7 @@ public function beforeFilter() {
if (!$this->Monitor->exists($id)) {
throw new NotFoundException(__('Invalid monitor'));
}
if ($this->Session->Read('systemPermission') != 'Edit')
if ($this->Session->Read('monitorPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;

View File

@ -1450,6 +1450,66 @@ function getDiskBlocks() {
return( $space );
}
function systemStats() {
$load = getLoad();
$diskPercent = getDiskPercent();
$pathMapPercent = getDiskPercent(ZM_PATH_MAP);
$cpus = getcpus();
$normalized_load = $load / $cpus;
# Colorize the system load stat
if ( $normalized_load <= 0.75 ) {
$htmlLoad=$load;
} elseif ( $normalized_load <= 0.9 ) {
$htmlLoad="<span class=\"warning\">$load</span>";
} elseif ( $normalized_load <= 1.1 ) {
$htmlLoad="<span class=\"error\">$load</span>";
} else {
$htmlLoad="<span class=\"critical\">$load</span>";
}
# Colorize the disk space stat
if ( $diskPercent < 98 ) {
$htmlDiskPercent="$diskPercent%";
} elseif ( $diskPercent <= 99 ) {
$htmlDiskPercent="<span class=\"warning\">$diskPercent%</span>";
} else {
$htmlDiskPercent="<span class=\"error\">$diskPercent%</span>";
}
# Colorize the PATH_MAP (usually /dev/shm) stat
if ( $pathMapPercent < 90 ) {
if ( disk_free_space(ZM_PATH_MAP) > 209715200 ) { # have to always have at least 200MiB free
$htmlPathMapPercent="$pathMapPercent%";
} else {
$htmlPathMapPercent="<span class=\"warning\">$pathMapPercent%</span>";
}
} elseif ( $pathMapPercent < 100 ) {
$htmlPathMapPercent="<span class=\"warning\">$pathMapPercent%</span>";
} else {
$htmlPathMapPercent="<span class=\"critical\">$pathMapPercent%</span>";
}
$htmlString = translate('Load').": $htmlLoad - ".translate('Disk').": $htmlDiskPercent - ".ZM_PATH_MAP.": $htmlPathMapPercent";
return( $htmlString );
}
function getcpus() {
if (is_readable("/proc/cpuinfo") ) { # Works on Linux
preg_match_all('/^processor/m', file_get_contents('/proc/cpuinfo'), $matches);
$num_cpus = count($matches[0]);
} else { # Works on BSD
$matches = explode(":", shell_exec("sysctl hw.ncpu"));
$num_cpus = trim($matches[1]);
}
return( $num_cpus );
}
// Function to fix a problem whereby the built in PHP session handling
// features want to put the sid as a hidden field after the form or
// fieldset tag, neither of which will work with strict XHTML Basic.
@ -2077,7 +2137,7 @@ function cache_bust( $file ) {
# Use the last modified timestamp to create a link that gets a different filename
# To defeat caching. Should probably use md5 hash
$parts = pathinfo($file);
$cacheFile = 'cache/'.$parts['filename'].'-'.filemtime($file).'.'.$parts['extension'];
$cacheFile = 'cache/'.$parts['filename'].'-'.$_COOKIE['zmCSS'].'-'.filemtime($file).'.'.$parts['extension'];
if ( file_exists( ZM_PATH_WEB.'/'.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_PATH_WEB.'/'.$cacheFile ) ) {
return $cacheFile;
} else {
@ -2214,6 +2274,7 @@ function getStreamMode( ) {
$streamMode = 'single';
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' );
}
return $streamMode;
} // end function getStreamMode
function folder_size($dir) {

View File

@ -37,7 +37,7 @@ function loadLanguage( $prefix="" )
$fallbackLangFile = $prefix.'lang/en_gb.php';
$systemLangFile = $prefix.'lang/'.ZM_LANG_DEFAULT.'.php';
if ( isset($user['Language']) )
$userLangFile = $prefix.$user['Language'].'.php';
$userLangFile = $prefix.'lang/'.$user['Language'].'.php';
if ( isset($userLangFile) && file_exists( $userLangFile ) )
return( $userLangFile );

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -149,9 +149,9 @@ span.noneCue {
}
.dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
height: 1.5em;
width: 2em;
padding: 0 ;
margin: 0 3px;
}

View File

@ -518,7 +518,6 @@ input[type=submit]:disabled {
.sidebar {
position: absolute;
top: 0;
bottom: 0;
left: 0;
z-index: 1000;
display: block;

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -131,9 +131,9 @@ span.noneCue {
}
.dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
height: 1.5em;
width: 2em;
padding: 0;
margin: 0 3px;
}

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -834,7 +834,7 @@ switch ( $tab ) {
<label for="newMonitor[V4LMultiBuffer]1">Yes</label>
<input type="radio" name="newMonitor[V4LMultiBuffer]" id="newMonitor[V4LMultiBuffer]0" value="0" <?php echo ( $monitor->V4LMultiBuffer() == 0 ? 'checked="checked"' : '' ) ?>/>
<label for="newMonitor[V4LMultiBuffer]0">No</label>
<input type="radio" name="newMonitor[V4LMultiBuffer]" id="newMonitor[V4LMultiBuffer]" value="" <?php echo ( empty($monitor->V4LMultiBuffer()) ? 'checked="checked"' : '' ) ?>/>
<input type="radio" name="newMonitor[V4LMultiBuffer]" id="newMonitor[V4LMultiBuffer]" value="" <?php echo ( $monitor->V4LMultiBuffer() ? 'checked="checked"' : '' ) ?>/>
<label for="newMonitor[V4LMultiBuffer]">Use Config Value</label>
</td></tr>
<tr><td><?php echo translate('V4LCapturesPerFrame') ?></td><td><input type="number" name="newMonitor[V4LCapturesPerFrame]" value="<?php echo $monitor->V4LCapturesPerFrame()?>"/></td></tr>

View File

@ -65,6 +65,7 @@ if ( $tab == 'skins' ) {
$current_css = $_COOKIE['zmCSS'];
if ( isset($_GET['css-choice']) and ( $_GET['css-choice'] != $current_css ) ) {
setcookie('zmCSS',$_GET['css-choice'], time()+3600*24*30*12*10 );
array_map('unlink', glob(ZM_PATH_WEB.'/cache/*')); //cleanup symlinks from cache_bust
//header("Location: index.php?view=options&tab=skins&reset_parent=1");
$reload = true;
}