Initial commit for new zmcamtool.pl script

This commit is contained in:
Andrew Bauer 2014-01-21 16:22:30 -06:00
parent ed40ee4d11
commit f00e72be1e
7 changed files with 366 additions and 1 deletions

View File

@ -143,6 +143,7 @@ fi
%{_bindir}/zmupdate.pl
%{_bindir}/zmvideo.pl
%{_bindir}/zmwatch.pl
%{_bindir}/zmcamtool.pl
%{!?_without_x10:%{_bindir}/zmx10.pl}
%{perl_vendorlib}/ZoneMinder*

View File

@ -237,6 +237,7 @@ fi
%{_bindir}/zmupdate.pl
%{_bindir}/zmvideo.pl
%{_bindir}/zmwatch.pl
%{_bindir}/zmcamtool.pl
%{!?_without_x10:%{_bindir}/zmx10.pl}
%{perl_vendorlib}/ZoneMinder*

View File

@ -135,6 +135,7 @@ rm -rf %{_docdir}/%{name}-%{version}
%{_bindir}/zmupdate.pl
%{_bindir}/zmvideo.pl
%{_bindir}/zmwatch.pl
%{_bindir}/zmcamtool.pl
%{_bindir}/zmx10.pl
%{perl_vendorlib}/ZoneMinder*

View File

@ -244,6 +244,7 @@ fi
%{_bindir}/zmupdate.pl
%{_bindir}/zmvideo.pl
%{_bindir}/zmwatch.pl
%{_bindir}/zmcamtool.pl
%{_bindir}/zmx10.pl
%{perl_vendorlib}/ZoneMinder*

View File

@ -14,6 +14,7 @@ configure_file(zmtrigger.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" @ONLY)
configure_file(zmupdate.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmupdate.pl" @ONLY)
configure_file(zmvideo.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" @ONLY)
configure_file(zmwatch.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" @ONLY)
configure_file(zmcamtool.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmcamtool.pl" @ONLY)
if(NOT ZM_NO_X10)
configure_file(zmx10.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmx10.pl" @ONLY)
endif(NOT ZM_NO_X10)
@ -23,7 +24,7 @@ configure_file(zm.in "${CMAKE_CURRENT_BINARY_DIR}/zm" @ONLY)
#configure_file(zmeventdump.in zmeventdump @ONLY)
# Install the perl scripts
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmaudit.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmupdate.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmaudit.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmupdate.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcamtool.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
if(NOT ZM_NO_X10)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmx10.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif(NOT ZM_NO_X10)

View File

@ -35,6 +35,7 @@ EXTRA_DIST = \
zmvideo.pl.in \
zmcontrol.pl.in \
zmtrack.pl.in \
zmcamtool.pl.in \
ZoneMinder/Makefile.PL \
ZoneMinder/README \
ZoneMinder/Changes \

359
scripts/zmcamtool.pl.in Executable file
View File

@ -0,0 +1,359 @@
#!/usr/bin/perl -w
#
# ==========================================================================
#
# ZoneMinder Update Script, $Date$, $Revision$
# Copyright (C) 2001-2008 Philip Coombes
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ==========================================================================
#
# This script provides a way to import new ptz camera controls & camera presets
# into existing zoneminder systems. This script also provides a way to export
# ptz camera controls & camera presets from an existing zoneminder system into
# a sql file, which can then be easily imported to another zoneminder system.
#
use strict;
use bytes;
@EXTRA_PERL_LIB@
use ZoneMinder::Base qw(:all);
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::General qw(:all);
use ZoneMinder::Database qw(:all);
use ZoneMinder::ConfigAdmin qw( :functions );
use POSIX;
use DBI;
use Getopt::Long;
use Data::Dumper;
# TO-DO - Figure out if "detainting" the environment is really necessary for this script
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
# TO-DO - Decide what, if anything, should be passed to the zoneminder logger
my $web_uid = (getpwnam( $Config{ZM_WEB_USER} ))[2];
my $use_log = (($> == 0) || ($> == $web_uid));
logInit( toFile=>$use_log?DEBUG:NOLOG );
logSetSignal();
my $export = 0;
my $import = 0;
my $overwrite = 0;
my $help = 0;
my $topreset = 0;
my $sqlfile = '';
my $dbUser = $Config{ZM_DB_USER};
my $dbPass = $Config{ZM_DB_PASS};
# Process commandline parameters with getopt long
if ( !GetOptions( 'export'=>\$export, 'import'=>\$import, 'overwrite'=>\$overwrite, 'help'=>\$help, 'topreset'=>\$topreset, 'user:s'=>\$dbUser, 'pass:s'=>\$dbPass ) ) {
Usage();
}
$Config{ZM_DB_USER} = $dbUser;
$Config{ZM_DB_PASS} = $dbPass;
# Check to make sure commandline params make sense
if ( ((!$help) && ($import + $export + $topreset) != 1 )) {
print( STDERR qq/Please give only one of the following: "import", "export", or "topreset".\n/ );
Usage();
}
if ( ($export)&&($overwrite) ) {
print "Warning: Overwrite parameter ignored during an export.\n";
}
# Call the appropriate subroutine based on the params given on the commandline
if ($help) {
Usage();
}
if ($export) {
exportsql();
}
if ($import) {
importsql();
}
if ($topreset) {
toPreset();
}
###############
# SUBROUTINES #
###############
# Usage subroutine help text
sub Usage
{
die("
USAGE:
zmcamtool.pl [--user=<dbuser> --pass=<dbpass>]
[[--overwrite] --import [file.sql]]
[--export [name]]
[--topreset monitor id]
PARAMETERS:
--export - Export all camera controls and presets to STDOUT.
Optionally specify a control or preset name.
--import - Import new camera controls and presets found in
zm_create.sql into the ZoneMinder dB.
Optionally specify an alternate sql file to read from.
--topreset - Copy a monitor to a Camera Preset given the monitor id.
--overwrite - Overwrite any existing controls or presets.
with the same name as the new controls or presets.
--help - Print usage information
--user=<dbuser> - Alternate dB user with privileges to alter dB.
--pass=<dbpass> - Password of alternate dB user with privileges to alter dB.
\n");
}
# Subroutine that checks if a name already exists in a sql table
# Not currently in-use b/c it requires a call to zmdbconnect each time (expensive)
sub checkName
{
my $sqltable = shift;
my $sqlname = shift;
my $result = 0;
my $dbh = zmDbConnect();
my $sql = "select count(*) from $sqltable where Name = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($sqlname) or die( "Can't execute: ".$sth->errstr() );
my $rows = $sth->fetchrow_arrayref();
$sth->finish();
if ($rows->[0] > 0) {
$result = 1;
}
return $result;
}
# Subroutine to import camera control & presets into the zoneminder dB
sub importsql
{
my @newcontrols;
my @overwritecontrols;
my @skippedcontrols;
my @newpresets;
my @overwritepresets;
my @skippedpresets;
my %controls;
my %monitorpresets;
if ($ARGV[0]) {
$sqlfile = $ARGV[0];
} else {
$sqlfile = $Config{ZM_PATH_DATA}.'/db/zm_create.sql';
}
open(SQLFILE, $sqlfile) or die "Can't Open file: $!\n";
# Find and extract ptz control and monitor preset records
while (<SQLFILE>) {
# Our regex replaces the primary key with NULL
if (s/^(INSERT INTO .*?Controls.*? VALUES \().*?(,')(.*?)(',.*)/$1NULL$2$3$4/i) {
$controls{$3} = $_;
} elsif (s/^(INSERT INTO .*?MonitorPresets.*? VALUES \().*?(,')(.*?)(',.*)/$1NULL$2$3$4/i) {
$monitorpresets{$3} = $_;
}
}
close SQLFILE;
if ( ! (%controls || %monitorpresets) ) {
die "Error: No relevant data found in $sqlfile.\n";
}
# Now that we've got what we were looking for, compare to what is already in the dB
my $dbh = zmDbConnect();
foreach (keys %controls) {
my $sql = "select count(*) from Controls where Name = ?";
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 $rows = $sth->fetchrow_arrayref();
$sth->finish();
if ($rows->[0] == 0) {
# No existing Control was found. Add new control to dB.
$sql = $controls{$_};
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
push @newcontrols, $_;
} elsif ($overwrite) {
# An existing Control was found and the overwrite flag is set. Overwrite the control.
$sql = "delete from Controls where Name = ?";
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute($_) or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
$sql = $controls{$_};
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
push @overwritecontrols, $_;
} else {
# An existing Control was found and the overwrite flag was not set. Do nothing.
push @skippedcontrols, $_;
}
$sth->finish();
}
foreach (keys %monitorpresets) {
my $sql = "select count(*) from MonitorPresets where Name = ?";
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 $rows = $sth->fetchrow_arrayref();
$sth->finish();
if ($rows->[0] == 0) {
# No existing MonitorPreset was found. Add new MonitorPreset to dB.
$sql = $monitorpresets{$_};
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
push @newpresets, $_;
} elsif ($overwrite) {
# An existing MonitorPreset was found and the overwrite flag is set. Overwrite the MonitorPreset.
$sql = "delete from MonitorPresets where Name = ?";
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute($_) or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
$sql = $monitorpresets{$_};
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
push @overwritepresets, $_;
} else {
# An existing MonitorPreset was found and the overwrite flag was not set. Do nothing.
push @skippedpresets, $_;
}
$sth->finish();
}
if (@newcontrols) {
print "Number of ptz camera controls added: ".scalar(@newcontrols)."\n";
}
if (@overwritecontrols) {
print "Number of existing ptz camera controls overwritten: ".scalar(@overwritecontrols)."\n";
}
if (@skippedcontrols) {
print "Number of existing ptz camera controls skipped: ".scalar(@skippedcontrols)."\n";
}
if (@newpresets) {
print "Number of monitor presets added: ".scalar(@newpresets)."\n";
}
if (@overwritepresets) {
print "Number of existing monitor presets overwritten: ".scalar(@overwritepresets)."\n";
}
if (@skippedpresets) {
print "Number of existing presets skipped: ".scalar(@skippedpresets)."\n";
}
}
# Subroutine to export camera control & presets from the zoneminder dB to STDOUT
sub exportsql
{
my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
my $command = "mysqldump -t --skip-opt --compact -h".$host;
$command .= " -P".$port if defined($port);
if ( $dbUser ) {
$command .= " -u".$dbUser;
if ( $dbPass ) {
$command .= " -p".$dbPass;
}
}
if ($ARGV[0]) {
$command .= qq( --where="Name = '$ARGV[0]'");
}
$command .= " zm Controls MonitorPresets";
my $output = qx($command);
my $status = $? >> 8;
# TO-DO - This does not seem necessary
#if ( $status || logDebugging() ) {
# chomp( $output );
# print( "Output: $output\n" );
#}
if ( $status ) {
die( "Command '$command' exited with status: $status\n" );
} else {
# NULLify the primary keys before printing the output to STDOUT
$output =~ s/VALUES \((.*?),'/VALUES \(NULL,'/ig;
print $output;
}
}
sub toPreset
{
my $dbh = zmDbConnect();
my $monitorid = $ARGV[0];
my @data;
# Grap the appropriate fields from the Monitors table
my $sql = "select Name, Type, Device, Channel, Format, Protocol, Method, Host, Port, Path, SubPath, Width, Height, Palette, MaxFPS, Controllable, ControlId, ControlDevice, ControlAddress, DefaultRate, DefaultScale from Monitors where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($monitorid) or die( "Can't execute: ".$sth->errstr() );
@data = $sth->fetchrow_array();
$sth->finish();
#
# TO-DO - Add code that tries to intelligently replace certain values with generic ones e.g. <ip>, <user>, <pwd>, etc.
#
# Check that we don't already have a record with the same name
# my $nameexists = checkName("MonitorPresets",$data[0]);
$sql = "select count(*) from MonitorPresets where Name = ?";
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute($data[0]) or die( "Can't execute: ".$sth->errstr() );
my $rows = $sth->fetchrow_arrayref();
$sth->finish();
if ($rows->[0] == 0) {
# No existing Preset was found. Add new Preset to dB.
print "Adding new preset: $data[0]\n";
$sql = "insert into MonitorPresets values (NULL,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute(@data) or die( "Can't execute: ".$sth->errstr() );
} elsif ($overwrite) {
# An existing Control was found and the overwrite flag is set. Overwrite the control.
print "Existing preset $data[0] dedected.\nOverwriting...\n";
$sql = "delete from MonitorPresets where Name = ?";
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute($data[0]) or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
$sql = "insert into MonitorPresets values (NULL,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute(@data) or die( "Can't execute: ".$sth->errstr() );
} else {
# An existing Control was found and the overwrite flag was not set. Do nothing.
print "Existing preset $data[0] detected and overwrite flag not set.\nSkipping...\n";
}
$sth->finish();
}