Bug 232 - Removed .z files.

git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@1680 e3e1d417-86f3-4887-817a-d78f3d33393f
pull/27/merge
stan 2005-12-16 10:27:52 +00:00
parent 01476d308b
commit 786488a990
21 changed files with 0 additions and 8818 deletions

View File

@ -1,5 +0,0 @@
--
-- Current Database: ZM_DB_NAME
--
DROP DATABASE /*!40000 IF EXISTS*/ ZM_DB_NAME;

View File

@ -1,398 +0,0 @@
--
-- Current Database: ZM_DB_NAME
--
CREATE DATABASE /*!32312 IF NOT EXISTS*/ ZM_DB_NAME;
USE ZM_DB_NAME;
--
-- Table structure for table `Config`
--
CREATE TABLE Config (
Id smallint(5) unsigned NOT NULL default '0',
Name varchar(32) NOT NULL default '',
Value text NOT NULL,
Type tinytext NOT NULL,
DefaultValue tinytext,
Hint tinytext,
Pattern tinytext,
Format tinytext,
Prompt tinytext,
Help text,
Category varchar(32) NOT NULL default '',
Readonly tinyint(3) unsigned NOT NULL default '0',
Requires text,
PRIMARY KEY (Name),
UNIQUE KEY UC_Name (Name)
) TYPE=MyISAM;
--
-- Table structure for table `Controls`
--
CREATE TABLE Controls (
Id int(10) unsigned NOT NULL auto_increment,
Name varchar(64) NOT NULL default '',
Type enum('Local','Remote') NOT NULL default 'Local',
Command varchar(255) default NULL,
CanWake tinyint(3) unsigned NOT NULL default '0',
CanSleep tinyint(3) unsigned NOT NULL default '0',
CanReset tinyint(3) unsigned NOT NULL default '0',
CanZoom tinyint(3) unsigned NOT NULL default '0',
CanAutoZoom tinyint(3) unsigned NOT NULL default '0',
CanZoomAbs tinyint(3) unsigned NOT NULL default '0',
CanZoomRel tinyint(3) unsigned NOT NULL default '0',
CanZoomCon tinyint(3) unsigned NOT NULL default '0',
MinZoomRange int(10) unsigned default NULL,
MaxZoomRange int(10) unsigned default NULL,
MinZoomStep int(10) unsigned default NULL,
MaxZoomStep int(10) unsigned default NULL,
HasZoomSpeed tinyint(3) unsigned NOT NULL default '0',
MinZoomSpeed int(10) unsigned default NULL,
MaxZoomSpeed int(10) unsigned default NULL,
CanFocus tinyint(3) unsigned NOT NULL default '0',
CanAutoFocus tinyint(3) unsigned NOT NULL default '0',
CanFocusAbs tinyint(3) unsigned NOT NULL default '0',
CanFocusRel tinyint(3) unsigned NOT NULL default '0',
CanFocusCon tinyint(3) unsigned NOT NULL default '0',
MinFocusRange int(10) unsigned default NULL,
MaxFocusRange int(10) unsigned default NULL,
MinFocusStep int(10) unsigned default NULL,
MaxFocusStep int(10) unsigned default NULL,
HasFocusSpeed tinyint(3) unsigned NOT NULL default '0',
MinFocusSpeed int(10) unsigned default NULL,
MaxFocusSpeed int(10) unsigned default NULL,
CanIris tinyint(3) unsigned NOT NULL default '0',
CanAutoIris tinyint(3) unsigned NOT NULL default '0',
CanIrisAbs tinyint(3) unsigned NOT NULL default '0',
CanIrisRel tinyint(3) unsigned NOT NULL default '0',
CanIrisCon tinyint(3) unsigned NOT NULL default '0',
MinIrisRange int(10) unsigned default NULL,
MaxIrisRange int(10) unsigned default NULL,
MinIrisStep int(10) unsigned default NULL,
MaxIrisStep int(10) unsigned default NULL,
HasIrisSpeed tinyint(3) unsigned NOT NULL default '0',
MinIrisSpeed int(10) unsigned default NULL,
MaxIrisSpeed int(10) unsigned default NULL,
CanGain tinyint(3) unsigned NOT NULL default '0',
CanAutoGain tinyint(3) unsigned NOT NULL default '0',
CanGainAbs tinyint(3) unsigned NOT NULL default '0',
CanGainRel tinyint(3) unsigned NOT NULL default '0',
CanGainCon tinyint(3) unsigned NOT NULL default '0',
MinGainRange int(10) unsigned default NULL,
MaxGainRange int(10) unsigned default NULL,
MinGainStep int(10) unsigned default NULL,
MaxGainStep int(10) unsigned default NULL,
HasGainSpeed tinyint(3) unsigned NOT NULL default '0',
MinGainSpeed int(10) unsigned default NULL,
MaxGainSpeed int(10) unsigned default NULL,
CanWhite tinyint(3) unsigned NOT NULL default '0',
CanAutoWhite tinyint(3) unsigned NOT NULL default '0',
CanWhiteAbs tinyint(3) unsigned NOT NULL default '0',
CanWhiteRel tinyint(3) unsigned NOT NULL default '0',
CanWhiteCon tinyint(3) unsigned NOT NULL default '0',
MinWhiteRange int(10) unsigned default NULL,
MaxWhiteRange int(10) unsigned default NULL,
MinWhiteStep int(10) unsigned default NULL,
MaxWhiteStep int(10) unsigned default NULL,
HasWhiteSpeed tinyint(3) unsigned NOT NULL default '0',
MinWhiteSpeed int(10) unsigned default NULL,
MaxWhiteSpeed int(10) unsigned default NULL,
HasPresets tinyint(3) unsigned NOT NULL default '0',
NumPresets tinyint(3) unsigned NOT NULL default '0',
HasHomePreset tinyint(3) unsigned NOT NULL default '0',
CanSetPresets tinyint(3) unsigned NOT NULL default '0',
CanMove tinyint(3) unsigned NOT NULL default '0',
CanMoveDiag tinyint(3) unsigned NOT NULL default '0',
CanMoveMap tinyint(3) unsigned NOT NULL default '0',
CanMoveAbs tinyint(3) unsigned NOT NULL default '0',
CanMoveRel tinyint(3) unsigned NOT NULL default '0',
CanMoveCon tinyint(3) unsigned NOT NULL default '0',
CanPan tinyint(3) unsigned NOT NULL default '0',
MinPanRange int(10) default NULL,
MaxPanRange int(10) default NULL,
MinPanStep int(10) default NULL,
MaxPanStep int(10) default NULL,
HasPanSpeed tinyint(3) unsigned NOT NULL default '0',
MinPanSpeed int(10) default NULL,
MaxPanSpeed int(10) default NULL,
HasTurboPan tinyint(3) unsigned NOT NULL default '0',
TurboPanSpeed int(10) default NULL,
CanTilt tinyint(3) unsigned NOT NULL default '0',
MinTiltRange int(10) default NULL,
MaxTiltRange int(10) default NULL,
MinTiltStep int(10) default NULL,
MaxTiltStep int(10) default NULL,
HasTiltSpeed tinyint(3) unsigned NOT NULL default '0',
MinTiltSpeed int(10) default NULL,
MaxTiltSpeed int(10) default NULL,
HasTurboTilt tinyint(3) unsigned NOT NULL default '0',
TurboTiltSpeed int(10) default NULL,
CanAutoScan tinyint(3) unsigned NOT NULL default '0',
NumScanPaths tinyint(3) unsigned NOT NULL default '0',
PRIMARY KEY (Id),
UNIQUE KEY UC_Id (Id)
) TYPE=MyISAM;
--
-- Table structure for table `Events`
--
CREATE TABLE Events (
Id int(10) unsigned NOT NULL auto_increment,
MonitorId int(10) unsigned NOT NULL default '0',
Name varchar(64) NOT NULL default '',
Cause varchar(32) NOT NULL default '',
StartTime datetime default NULL,
EndTime datetime default NULL,
Width smallint(5) unsigned NOT NULL default '0',
Height smallint(5) unsigned NOT NULL default '0',
Length decimal(10,2) NOT NULL default '0.00',
Frames int(10) unsigned default NULL,
AlarmFrames int(10) unsigned default NULL,
TotScore int(10) unsigned NOT NULL default '0',
AvgScore smallint(5) unsigned default '0',
MaxScore smallint(5) unsigned default '0',
Archived tinyint(3) unsigned NOT NULL default '0',
Videoed tinyint(3) unsigned NOT NULL default '0',
Uploaded tinyint(3) unsigned NOT NULL default '0',
Emailed tinyint(3) unsigned NOT NULL default '0',
Messaged tinyint(3) unsigned NOT NULL default '0',
Executed tinyint(3) unsigned NOT NULL default '0',
LearnState char(1) default '',
Notes tinytext,
PRIMARY KEY (Id),
UNIQUE KEY UC_Id (Id),
KEY Id (Id,MonitorId),
KEY MonitorId (MonitorId),
KEY StartTime (StartTime),
KEY Frames (Frames),
KEY Archived (Archived)
) TYPE=MyISAM;
--
-- Table structure for table `Filters`
--
CREATE TABLE Filters (
Name varchar(64) NOT NULL default '',
Query text NOT NULL,
AutoArchive tinyint(3) unsigned NOT NULL default '0',
AutoVideo tinyint(3) unsigned NOT NULL default '0',
AutoUpload tinyint(3) unsigned NOT NULL default '0',
AutoEmail tinyint(3) unsigned NOT NULL default '0',
AutoMessage tinyint(3) unsigned NOT NULL default '0',
AutoExecute tinyint(3) unsigned NOT NULL default '0',
AutoExecuteCmd tinytext,
AutoDelete tinyint(3) unsigned NOT NULL default '0',
PRIMARY KEY (Name)
) TYPE=MyISAM;
--
-- Table structure for table `Frames`
--
CREATE TABLE Frames (
Id int(10) unsigned NOT NULL auto_increment,
EventId int(10) unsigned NOT NULL default '0',
FrameId int(10) unsigned NOT NULL default '0',
Type enum('Normal','Bulk','Alarm') NOT NULL default 'Normal',
TimeStamp timestamp(14) NOT NULL,
Delta decimal(8,2) NOT NULL default '0.00',
Score smallint(5) unsigned NOT NULL default '0',
PRIMARY KEY (Id),
UNIQUE KEY UC_Id (Id),
KEY EventId (EventId),
KEY Type (Type),
KEY TimeStamp (TimeStamp)
) TYPE=MyISAM;
--
-- Table structure for table `Groups`
--
CREATE TABLE Groups (
Id int(10) unsigned NOT NULL auto_increment,
Name varchar(64) NOT NULL default '',
MonitorIds tinytext NOT NULL,
PRIMARY KEY (Id)
) TYPE=MyISAM;
--
-- Table structure for table `Monitors`
--
CREATE TABLE Monitors (
Id int(10) unsigned NOT NULL auto_increment,
Name varchar(64) NOT NULL default '',
Type enum('Local','Remote','File') NOT NULL default 'Local',
Function enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
RunMode enum('Continuous','Triggered') NOT NULL default 'Continuous',
Triggers set('X10') NOT NULL default '',
Device tinytext,
Channel tinyint(3) unsigned NOT NULL default '0',
Format tinyint(3) unsigned NOT NULL default '0',
Host varchar(64) default NULL,
Port varchar(8) default '80',
Path varchar(255) default NULL,
Width smallint(5) unsigned NOT NULL default '0',
Height smallint(5) unsigned NOT NULL default '0',
Palette tinyint(3) unsigned NOT NULL default '1',
Orientation enum('0','90','180','270','hori','vert') NOT NULL default '0',
Brightness mediumint(7) NOT NULL default '-1',
Contrast mediumint(7) NOT NULL default '-1',
Hue mediumint(7) NOT NULL default '-1',
Colour mediumint(7) NOT NULL default '-1',
EventPrefix varchar(32) NOT NULL default 'Event-',
LabelFormat varchar(32) NOT NULL default '%%s - %y/%m/%d %H:%M:%S',
LabelX smallint(5) unsigned default NULL,
LabelY smallint(5) unsigned default NULL,
ImageBufferCount smallint(5) unsigned NOT NULL default '100',
WarmupCount smallint(5) unsigned NOT NULL default '25',
PreEventCount smallint(5) unsigned NOT NULL default '10',
PostEventCount smallint(5) unsigned NOT NULL default '10',
AlarmFrameCount smallint(5) unsigned NOT NULL default '1',
SectionLength int(10) unsigned NOT NULL default '600',
FrameSkip smallint(5) unsigned NOT NULL default '0',
MaxFPS decimal(5,2) NOT NULL default '0.00',
FPSReportInterval smallint(5) unsigned NOT NULL default '250',
RefBlendPerc tinyint(3) unsigned NOT NULL default '10',
Controllable tinyint(3) unsigned NOT NULL default '0',
ControlId int(10) unsigned NOT NULL default '0',
ControlDevice varchar(255) default NULL,
ControlAddress varchar(255) default NULL,
AutoStopTimeout decimal(5,2) default NULL,
TrackMotion tinyint(3) unsigned NOT NULL default '0',
TrackDelay smallint(5) unsigned NOT NULL default '0',
ReturnLocation tinyint(3) NOT NULL default '-1',
ReturnDelay smallint(5) unsigned NOT NULL default '0',
DefaultRate smallint(5) unsigned NOT NULL default '100',
DefaultScale smallint(5) unsigned NOT NULL default '100',
WebColour varchar(32) NOT NULL default 'red',
Sequence smallint(5) unsigned default NULL,
PRIMARY KEY (Id)
) TYPE=MyISAM;
--
-- Table structure for table `States`
--
CREATE TABLE States (
Name varchar(64) NOT NULL default '',
Definition tinytext NOT NULL,
PRIMARY KEY (Name)
) TYPE=MyISAM;
--
-- Table structure for table `Stats`
--
CREATE TABLE Stats (
MonitorId int(10) unsigned NOT NULL default '0',
ZoneId int(10) unsigned NOT NULL default '0',
EventId int(10) unsigned NOT NULL default '0',
FrameId int(10) unsigned NOT NULL default '0',
AlarmPixels int(10) unsigned NOT NULL default '0',
FilterPixels int(10) unsigned NOT NULL default '0',
BlobPixels int(10) unsigned NOT NULL default '0',
Blobs smallint(5) unsigned NOT NULL default '0',
MinBlobSize int(10) unsigned NOT NULL default '0',
MaxBlobSize int(10) unsigned NOT NULL default '0',
MinX smallint(5) unsigned NOT NULL default '0',
MaxX smallint(5) unsigned NOT NULL default '0',
MinY smallint(5) unsigned NOT NULL default '0',
MaxY smallint(5) unsigned NOT NULL default '0',
Score smallint(5) unsigned NOT NULL default '0',
KEY EventId (EventId),
KEY MonitorId (MonitorId),
KEY ZoneId (ZoneId)
) TYPE=MyISAM;
--
-- Table structure for table `TriggersX10`
--
CREATE TABLE TriggersX10 (
MonitorId int(10) unsigned NOT NULL default '0',
Activation varchar(32) default NULL,
AlarmInput varchar(32) default NULL,
AlarmOutput varchar(32) default NULL,
PRIMARY KEY (MonitorId)
) TYPE=MyISAM;
--
-- Table structure for table `Users`
--
CREATE TABLE Users (
Id int(10) unsigned NOT NULL auto_increment,
Username varchar(32) binary NOT NULL default '',
Password varchar(64) NOT NULL default '',
Language varchar(8) NOT NULL default '',
Enabled tinyint(3) unsigned NOT NULL default '1',
Stream enum('None','View') NOT NULL default 'None',
Events enum('None','View','Edit') NOT NULL default 'None',
Control enum('None','View','Edit') NOT NULL default 'None',
Monitors enum('None','View','Edit') NOT NULL default 'None',
System enum('None','View','Edit') NOT NULL default 'None',
MaxBandwidth varchar(16) NOT NULL default '',
MonitorIds tinytext NOT NULL,
PRIMARY KEY (Id),
UNIQUE KEY UC_Id (Id),
UNIQUE KEY UC_Username (Username)
) TYPE=MyISAM;
--
-- Table structure for table `Zones`
--
CREATE TABLE Zones (
Id int(10) unsigned NOT NULL auto_increment,
MonitorId int(10) unsigned NOT NULL default '0',
Name varchar(64) NOT NULL default '',
Type enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active',
Units enum('Pixels','Percent') NOT NULL default 'Pixels',
NumCoords tinyint(3) unsigned NOT NULL default '0',
Coordinates tinytext NOT NULL,
Area int(10) NOT NULL unsigned default '0',
LoX smallint(5) unsigned NOT NULL default '0',
LoY smallint(5) unsigned NOT NULL default '0',
HiX smallint(5) unsigned NOT NULL default '0',
HiY smallint(5) unsigned NOT NULL default '0',
AlarmRGB int(10) unsigned default '0',
CheckMethod enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs',
MinPixelThreshold smallint(5) unsigned default NULL,
MaxPixelThreshold smallint(5) unsigned default NULL,
MinAlarmPixels int(10) unsigned default NULL,
MaxAlarmPixels int(10) unsigned default NULL,
FilterX tinyint(3) unsigned default NULL,
FilterY tinyint(3) unsigned default NULL,
MinFilterPixels int(10) unsigned default NULL,
MaxFilterPixels int(10) unsigned default NULL,
MinBlobPixels int(10) unsigned default NULL,
MaxBlobPixels int(10) unsigned default NULL,
MinBlobs smallint(5) unsigned default NULL,
MaxBlobs smallint(5) unsigned default NULL,
PRIMARY KEY (Id),
UNIQUE KEY UC_Id (Id)
) TYPE=MyISAM;
--
-- Create a default admin user.
--
insert into Users values ('','admin',password('admin'),'',1,'View','Edit','Edit','Edit','Edit','','');
--
-- Add in a sample filter to purge the oldest 5 events when the disk is 95% full, delete is disabled though
--
insert into Filters values ('PurgeWhenFull','trms=2&obr1=&cbr1=&attr1=Archived&op1==&val1=0&cnj2=and&obr2=&cbr2=&attr2=DiskPercent&op2=>=&val2=95&sort_field=Id&sort_asc=1&limit=5',0,0,0,0,0,'');
--
-- Add in some sample control protocol definitions
--
insert into Controls values (1,'PELCO-D','Local','zmcontrol-pelco-d.pl',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0);
insert into Controls values (2,'PELCO-P','Local','zmcontrol-pelco-p.pl',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0);
insert into Controls values (3,'Sony VISCA','Local','zmcontrol-visca.pl',1,1,0,1,0,0,0,1,0,16384,10,4000,1,1,6,1,1,1,0,1,0,1536,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,3,1,1,1,1,0,1,1,0,1,-15578,15578,100,10000,1,1,50,1,254,1,-7789,7789,100,5000,1,1,50,1,254,0,0);
INSERT INTO Controls VALUES (4,'Axis API v2','Remote','zmcontrol-axis-v2.pl',0,0,0,1,0,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,1,1,1,1,1,0,1,0,1,-360,360,1,90,0,NULL,NULL,0,NULL,1,-360,360,1,90,0,NULL,NULL,0,NULL,0,0);
insert into Controls values (5,'KX-HCM10','Remote','zmcontrol-kx-hcm10.pl',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,8,1,1,1,0,1,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0);

View File

@ -1,61 +0,0 @@
#!/bin/sh
# description: Control ZoneMinder as a Service
# chkconfig: 2345 99 99
# Source function library.
. /etc/rc.d/init.d/functions
prog=ZoneMinder
ZM_PATH_BIN="<from zmconfig>"
command="$ZM_PATH_BIN/zmpkg.pl"
start() {
echo -n "Starting $prog: "
$command start
RETVAL=$?
[ $RETVAL = 0 ] && echo_success
[ $RETVAL != 0 ] && echo_failure
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/zm
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
$command stop
RETVAL=$?
[ $RETVAL = 0 ] && echo_success
[ $RETVAL != 0 ] && echo_failure
echo
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/zm
}
status() {
result=`$command status`
if [ "$result" = "running" ]; then
echo "ZoneMinder is running"
RETVAL=0
else
echo "ZoneMinder is stopped"
RETVAL=1
fi
}
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart')
stop
start
;;
'status')
status
;;
*)
echo "Usage: $0 { start | stop | restart | status }"
RETVAL=1
;;
esac
exit $RETVAL

View File

@ -1,409 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Audit Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 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.
#
use strict;
use bytes;
use ZoneMinder;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant IMAGE_PATH => ZM_PATH_WEB.'/'.ZM_DIR_IMAGES;
use constant EVENT_PATH => ZM_PATH_WEB.'/'.ZM_DIR_EVENTS;
use constant LOG_FILE => ZM_PATH_LOGS.'/zmaudit.log';
use constant MIN_AGE => 300; # Minimum age when we will delete anything
use constant RECOVER_TAG => "(r)"; # Tag to append to event name when recovered
use constant RECOVER_TEXT => "Recovered."; # Text to append to event notes when recovered
use constant DBG_LEVEL => 1; # 0 is errors, warnings and info only, > 0 for debug
# ==========================================================================
#
# You shouldn't need to change anything from here downwards
#
# ==========================================================================
use DBI;
use POSIX;
use Time::HiRes qw/gettimeofday/;
use Getopt::Long;
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $report = 0;
my $yes = 0;
my $delay = 0;
sub usage
{
print( "
Usage: zmaudit.pl [-r,-report|-y,-yes] [-d <seconds>,-delay=<seconds>]
Parameters are :-
-r, --report - Just report don't actually do anything
-y, --yes - Just do all actions without confirmation
-d <seconds>, --delay=<seconds> - how long to delay between each pass, the default of 0 means run once only.
");
exit( -1 );
}
my $dbg_id = "";
sub dbgInit
{
my $id = shift;
if ( $id )
{
$dbg_id = $id;
my $add_parms = shift;
if ( $add_parms )
{
foreach my $arg ( @ARGV )
{
if ( $arg =~ /^-(.*)$/ )
{
$dbg_id .= "_$1";
}
else
{
$dbg_id .= $arg;
}
}
}
}
}
sub dbgPrint
{
my $code = shift;
my $string = shift;
my $line = shift;
$string =~ s/[\r\n]+$//g;
my ($seconds, $microseconds) = gettimeofday();
if ( $line )
{
my $file = __FILE__;
$file =~ s|^.*/||g;
printf( "%s.%06d %s[%d].%s-%s/%d [%s]\n", strftime( "%x %H:%M:%S", localtime( $seconds ) ), $microseconds, $dbg_id, $$, $file, $line, $code, $string );
}
else
{
printf( "%s.%06d %s[%d].%s [%s]\n", strftime( "%x %H:%M:%S", localtime( $seconds ) ), $microseconds, $dbg_id, $$, $code, $string );
}
}
sub Debug
{
dbgPrint( "DBG", $_[0] ) if ( DBG_LEVEL >= 1 );
}
sub Info
{
dbgPrint( "INF", $_[0] ) if ( DBG_LEVEL >= 0 );
}
sub Warning
{
dbgPrint( "WAR", $_[0] ) if ( DBG_LEVEL >= -1 );
}
sub Error
{
dbgPrint( "ERR", $_[0] ) if ( DBG_LEVEL >= -2 );
}
sub aud_print
{
my $string = shift;
if ( $delay )
{
Info( $string );
}
else
{
print( $string );
}
}
sub confirm
{
my $prompt = shift || "delete";
my $action = shift || "deleting";
my $yesno = $yes?1:0;
if ( $report )
{
if ( !$delay )
{
print( "\n" );
}
}
elsif ( $yes )
{
if ( $delay )
{
Info( "$action\n" );
}
else
{
print( ", $action\n" );
}
}
else
{
print( ", $prompt y/n: " );
my $char = <>;
chomp( $char );
if ( $char eq 'q' )
{
exit( 0 );
}
if ( !$char )
{
$char = 'y';
}
if ( $char eq "a" )
{
$yes = 1;
return( 1 );
}
$yesno = ( $char =~ /[yY]/ );
}
return( $yesno );
}
dbgInit( "zmaudit", 1 );
if ( !GetOptions( 'report'=>\$report, 'yes'=>\$yes, 'delay=i'=>\$delay ) )
{
usage();
}
if ( $report && $yes )
{
print( STDERR "Error, only one of --report and --yes may be specified\n" );
usage();
}
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
chdir( EVENT_PATH );
if ( $delay ) # Background mode
{
open( LOG, ">>".LOG_FILE ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
}
my $max_image_age = 15/(24*60); # 15 Minutes
my $image_path = IMAGE_PATH;
do
{
my $db_monitors;
my $sql1 = "select Id from Monitors order by Id";
my $sth1 = $dbh->prepare_cached( $sql1 ) or die( "Can't prepare '$sql1': ".$dbh->errstr() );
my $sql2 = "select Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age from Events where MonitorId = ? order by Id";
my $sth2 = $dbh->prepare_cached( $sql2 ) or die( "Can't prepare '$sql2': ".$dbh->errstr() );
my $res = $sth1->execute() or die( "Can't execute: ".$sth1->errstr() );
while( my $monitor = $sth1->fetchrow_hashref() )
{
Debug( "Found database monitor '$monitor->{Id}'" );
my $db_events = $db_monitors->{$monitor->{Id}} = {};
my $res = $sth2->execute( $monitor->{Id} ) or die( "Can't execute: ".$sth2->errstr() );
while ( my $event = $sth2->fetchrow_hashref() )
{
$db_events->{$event->{Id}} = $event->{Age};
}
Debug( "Got ".int(keys(%$db_events))." events\n" );
$sth2->finish();
}
$sth1->finish();
my $fs_now = time();
my $fs_monitors;
foreach my $monitor ( <[0-9]*> )
{
Debug( "Found filesystem monitor '$monitor'" );
my $fs_events = $fs_monitors->{$monitor} = {};
( my $monitor_dir ) = ( $monitor =~ /^(.*)$/ ); # De-taint
opendir( DIR, $monitor_dir ) or die( "Can't open directory '$monitor_dir': $!" );
my @temp_events = sort { $b <=> $a } grep { $_ =~ /^\d+$/ } readdir( DIR );
closedir( DIR );
chdir( $monitor_dir );
my $count = 0;
foreach my $event ( @temp_events )
{
if ( $count++ > 25 )
{
$fs_events->{$event} = -1;
}
else
{
$fs_events->{$event} = ($fs_now - ($^T - ((-M $event) * 24*60*60)));
}
}
chdir( EVENT_PATH );
Debug( "Got ".int(keys(%$fs_events))." events\n" );
}
while ( my ( $fs_monitor, $fs_events ) = each(%$fs_monitors) )
{
if ( my $db_events = $db_monitors->{$fs_monitor} )
{
if ( $fs_events )
{
while ( my ( $fs_event, $age ) = each(%$fs_events ) )
{
if ( !defined($db_events->{$fs_event}) && ($age < 0 || ($age > MIN_AGE)) )
{
aud_print( "Filesystem event '$fs_monitor/$fs_event' does not exist in database" );
if ( confirm() )
{
my $command = "/bin/rm -rf ".EVENT_PATH."/$fs_monitor/$fs_event";
qx( $command );
}
}
}
}
}
else
{
aud_print( "Filesystem monitor '$fs_monitor' does not exist in database" );
if ( confirm() )
{
my $command = "rm -rf ".EVENT_PATH."/$fs_monitor";
qx( $command );
}
}
}
my $sql3 = "delete from Monitors where Id = ?";
my $sth3 = $dbh->prepare_cached( $sql3 ) or die( "Can't prepare '$sql3': ".$dbh->errstr() );
my $sql4 = "delete from Events where Id = ?";
my $sth4 = $dbh->prepare_cached( $sql4 ) or die( "Can't prepare '$sql4': ".$dbh->errstr() );
my $sql5 = "delete from Frames where EventId = ?";
my $sth5 = $dbh->prepare_cached( $sql5 ) or die( "Can't prepare '$sql5': ".$dbh->errstr() );
my $sql6 = "delete from Stats where EventId = ?";
my $sth6 = $dbh->prepare_cached( $sql6 ) or die( "Can't prepare '$sql6': ".$dbh->errstr() );
while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) )
{
if ( my $fs_events = $fs_monitors->{$db_monitor} )
{
if ( $db_events )
{
while ( my ( $db_event, $age ) = each(%$db_events ) )
{
if ( !defined($fs_events->{$db_event}) && ($age > MIN_AGE) )
{
aud_print( "Database event '$db_monitor/$db_event' does not exist in filesystem" );
if ( confirm() )
{
my $res = $sth4->execute( $db_event ) or die( "Can't execute: ".$sth4->errstr() );
$res = $sth5->execute( $db_event ) or die( "Can't execute: ".$sth5->errstr() );
$res = $sth6->execute( $db_event ) or die( "Can't execute: ".$sth6->errstr() );
}
}
}
}
}
else
{
#aud_print( "Database monitor '$db_monitor' does not exist in filesystem" );
#if ( confirm() )
#{
# We don't actually do this in case it's new
#my $res = $sth3->execute( $db_monitor ) or die( "Can't execute: ".$sth3->errstr() );
#}
}
}
my $sql7 = "select distinct EventId from Frames left join Events on Frames.EventId = Events.Id where isnull(Events.Id) group by EventId";
my $sth7 = $dbh->prepare_cached( $sql7 ) or die( "Can't prepare '$sql7': ".$dbh->errstr() );
$res = $sth7->execute() or die( "Can't execute: ".$sth7->errstr() );
while( my $frame = $sth7->fetchrow_hashref() )
{
aud_print( "Found orphaned frame records for event '$frame->{EventId}'" );
if ( confirm() )
{
$res = $sth5->execute( $frame->{EventId} ) or die( "Can't execute: ".$sth6->errstr() );
}
}
my $sql8 = "select distinct EventId from Stats left join Events on Stats.EventId = Events.Id where isnull(Events.Id) group by EventId";
my $sth8 = $dbh->prepare_cached( $sql8 ) or die( "Can't prepare '$sql8': ".$dbh->errstr() );
$res = $sth8->execute() or die( "Can't execute: ".$sth8->errstr() );
while( my $stat = $sth8->fetchrow_hashref() )
{
aud_print( "Found orphaned statistic records for event '$stat->{EventId}'" );
if ( confirm() )
{
$res = $sth6->execute( $stat->{EventId} ) or die( "Can't execute: ".$sth6->errstr() );
}
}
# New audit to close any events that were left open for longer than MIN_AGE seconds
my $sql9 = "select E.Id, max(F.TimeStamp) as EndTime, unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length, count(F.Id) as Frames, count(if(F.Score>0,1,NULL)) as AlarmFrames, sum(F.Score) as TotScore, max(F.Score) as MaxScore, M.EventPrefix as Prefix from Events as E left join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where isnull(E.Frames) group by E.Id having EndTime < (now() - interval ".MIN_AGE." second)";
my $sth9 = $dbh->prepare_cached( $sql9 ) or die( "Can't prepare '$sql9': ".$dbh->errstr() );
my $sql10 = "update Events set Name = ?, EndTime = ?, Length = ?, Frames = ?, AlarmFrames = ?, TotScore = ?, AvgScore = ?, MaxScore = ?, Notes = concat_ws( ' ', Notes, ? ) where Id = ?";
my $sth10 = $dbh->prepare_cached( $sql10 ) or die( "Can't prepare '$sql10': ".$dbh->errstr() );
$res = $sth9->execute() or die( "Can't execute: ".$sth9->errstr() );
while( my $event = $sth9->fetchrow_hashref() )
{
aud_print( "Found open event '$event->{Id}'" );
if ( confirm( 'close', 'closing' ) )
{
$res = $sth10->execute( sprintf( "%s%d%s", $event->{Prefix}, $event->{Id}, RECOVER_TAG ), $event->{EndTime}, $event->{Length}, $event->{Frames}, $event->{AlarmFrames}, $event->{TotScore}, $event->{AlarmFrames}?int($event->{TotScore}/$event->{AlarmFrames}):0, $event->{MaxScore}, RECOVER_TEXT, $event->{Id} ) or die( "Can't execute: ".$sth10->errstr() );
}
}
# Now delete any old image files
if ( my @old_files = grep { -M > $max_image_age } <$image_path/*.{jpg,gif,wbmp}> )
{
aud_print( "Deleting ".int(@old_files)." old images\n" );
my $untainted_old_files = join( ";", @old_files );
( $untainted_old_files ) = ( $untainted_old_files =~ /^(.*)$/ );
unlink( split( ";", $untainted_old_files ) );
}
sleep( $delay ) if ( $delay );
} while( $delay );

View File

@ -1,546 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Axis HTTP API v2 Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 continuously monitors the recorded events for the given
# monitor and applies any filters which would delete and/or upload
# matching events
#
use strict;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_VERSION => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*([^=\s]+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use Getopt::Long;
use constant LOG_FILE => ZM_PATH_LOGS.'/zmcontrol-axis-v2.log';
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
sub Usage
{
print( "
Usage: zmcontrol-axis-v2.pl <various options>
");
exit( -1 );
}
my $arg_string = join( " ", @ARGV );
my $address;
my $command;
my ( $speed, $step );
my ( $xcoord, $ycoord );
my ( $width, $height );
my ( $panspeed, $tiltspeed );
my ( $panstep, $tiltstep );
my $preset;
if ( !GetOptions(
'address=s'=>\$address,
'command=s'=>\$command,
'speed=i'=>\$speed,
'step=i'=>\$step,
'xcoord=i'=>\$xcoord,
'ycoord=i'=>\$ycoord,
'width=i'=>\$width,
'height=i'=>\$height,
'panspeed=i'=>\$panspeed,
'tiltspeed=i'=>\$tiltspeed,
'panstep=i'=>\$panstep,
'tiltstep=i'=>\$tiltstep,
'preset=i'=>\$preset
)
)
{
Usage();
}
if ( !$address )
{
Usage();
}
my $log_file = LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( $arg_string."\n" );
srand( time() );
sub printMsg
{
my $msg = shift;
my $msg_len = length($msg);
print( $msg );
print( "[".$msg_len."]\n" );
}
sub sendCmd
{
my $cmd = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
$ua->agent( "ZoneMinder Control Agent/".ZM_VERSION );
#print( "http://$address/$cmd\n" );
my $req = HTTP::Request->new( GET=>"http://$address/$cmd" );
my $res = $ua->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
print( "Error check failed: '".$res->status_line()."'\n" );
}
return( $result );
}
sub cameraReset
{
print( "Camera Reset\n" );
my $cmd = "nphRestart?PAGE=Restart&Restart=OK";
sendCmd( $cmd );
}
sub moveUp
{
print( "Move Up\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=up";
sendCmd( $cmd );
}
sub moveDown
{
print( "Move Down\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=down";
sendCmd( $cmd );
}
sub moveLeft
{
print( "Move Left\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=left";
sendCmd( $cmd );
}
sub moveRight
{
print( "Move Right\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=right";
sendCmd( $cmd );
}
sub moveUpRight
{
print( "Move Up/Right\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=upright";
sendCmd( $cmd );
}
sub moveUpLeft
{
print( "Move Up/Left\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=upleft";
sendCmd( $cmd );
}
sub moveDownRight
{
print( "Move Down/Right\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=downright";
sendCmd( $cmd );
}
sub moveDownLeft
{
print( "Move Down/Left\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=downleft";
sendCmd( $cmd );
}
sub moveMap
{
my ( $xcoord, $ycoord, $width, $height ) = @_;
print( "Move Map to $xcoord,$ycoord\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=$width&imageheight=$height";
sendCmd( $cmd );
}
sub stepUp
{
my $step = shift;
print( "Step Up $step\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=$step";
sendCmd( $cmd );
}
sub stepDown
{
my $step = shift;
print( "Step Down $step\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=-$step";
sendCmd( $cmd );
}
sub stepLeft
{
my $step = shift;
print( "Step Left $step\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$step";
sendCmd( $cmd );
}
sub stepRight
{
my $step = shift;
print( "Step Right $step\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$step";
sendCmd( $cmd );
}
sub stepUpRight
{
my $panstep = shift;
my $tiltstep = shift;
print( "Step Up/Right $tiltstep/$panstep\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=$tiltstep";
sendCmd( $cmd );
}
sub stepUpLeft
{
my $panstep = shift;
my $tiltstep = shift;
print( "Step Up/Left $tiltstep/$panstep\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep";
sendCmd( $cmd );
}
sub stepDownRight
{
my $panstep = shift;
my $tiltstep = shift;
print( "Step Down/Right $tiltstep/$panstep\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=-$tiltstep";
sendCmd( $cmd );
}
sub stepDownLeft
{
my $panstep = shift;
my $tiltstep = shift;
print( "Step Down/Left $tiltstep/$panstep\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=-$tiltstep";
sendCmd( $cmd );
}
sub zoomTele
{
my $step = shift;
print( "Zoom Tele\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=$step";
sendCmd( $cmd );
}
sub zoomWide
{
my $step = shift;
print( "Zoom Wide\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=-$step";
sendCmd( $cmd );
}
sub focusNear
{
my $step = shift;
print( "Focus Near\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=-$step";
sendCmd( $cmd );
}
sub focusFar
{
my $step = shift;
print( "Focus Far\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=$step";
sendCmd( $cmd );
}
sub focusAuto
{
print( "Focus Auto\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=on";
sendCmd( $cmd );
}
sub focusMan
{
print( "Focus Manual\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=off";
sendCmd( $cmd );
}
sub irisOpen
{
my $step = shift;
print( "Iris Open\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?riris=$step";
sendCmd( $cmd );
}
sub irisClose
{
my $step = shift;
print( "Iris Close\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?riris=-$step";
sendCmd( $cmd );
}
sub irisAuto
{
print( "Iris Auto\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=on";
sendCmd( $cmd );
}
sub irisMan
{
print( "Iris Manual\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=off";
sendCmd( $cmd );
}
sub presetClear
{
my $preset = shift || 1;
print( "Clear Preset $preset\n" );
my $cmd = "nphPresetNameCheck?Data=$preset";
sendCmd( $cmd );
}
sub presetSet
{
my $preset = shift || 1;
print( "Set Preset $preset\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?setserverpresetno=$preset";
sendCmd( $cmd );
}
sub presetGoto
{
my $preset = shift || 1;
print( "Goto Preset $preset\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?gotoserverpresetno=$preset";
sendCmd( $cmd );
}
sub presetHome
{
print( "Home Preset\n" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=home";
sendCmd( $cmd );
}
if ( $command eq "move_con_up" )
{
moveUp();
}
elsif ( $command eq "move_con_down" )
{
moveDown();
}
elsif ( $command eq "move_con_left" )
{
moveLeft();
}
elsif ( $command eq "move_con_right" )
{
moveRight();
}
elsif ( $command eq "move_con_upleft" )
{
moveUpLeft();
}
elsif ( $command eq "move_con_upright" )
{
moveUpRight();
}
elsif ( $command eq "move_con_downleft" )
{
moveDownLeft();
}
elsif ( $command eq "move_con_downright" )
{
moveDownLeft();
}
elsif ( $command eq "move_map" )
{
moveMap( $xcoord, $ycoord, $width, $height );
}
elsif ( $command eq "move_rel_up" )
{
stepUp( $tiltstep );
}
elsif ( $command eq "move_rel_down" )
{
stepDown( $tiltstep );
}
elsif ( $command eq "move_rel_left" )
{
stepLeft( $panstep );
}
elsif ( $command eq "move_rel_right" )
{
stepRight( $panstep );
}
elsif ( $command eq "move_rel_upleft" )
{
stepUpLeft( $panstep, $tiltstep );
}
elsif ( $command eq "move_rel_upright" )
{
stepUpRight( $panstep, $tiltstep );
}
elsif ( $command eq "move_rel_downleft" )
{
stepDownLeft( $panstep, $tiltstep );
}
elsif ( $command eq "move_rel_downright" )
{
stepDownRight( $panstep, $tiltstep );
}
elsif ( $command eq "zoom_rel_tele" )
{
zoomTele( $step );
}
elsif ( $command eq "zoom_rel_wide" )
{
zoomWide( $step );
}
elsif ( $command eq "focus_rel_near" )
{
focusNear( $step );
}
elsif ( $command eq "focus_rel_far" )
{
focusFar( $step );
}
elsif ( $command eq "focus_auto" )
{
focusAuto();
}
elsif ( $command eq "focus_man" )
{
focusMan();
}
elsif ( $command eq "iris_rel_open" )
{
irisOpen( $step );
}
elsif ( $command eq "iris_rel_close" )
{
irisClose( $step );
}
elsif ( $command eq "iris_auto" )
{
irisAuto();
}
elsif ( $command eq "iris_man" )
{
irisMan();
}
elsif ( $command eq "preset_home" )
{
presetHome();
}
elsif ( $command eq "preset_set" )
{
presetSet( $preset );
}
elsif ( $command eq "preset_goto" )
{
presetGoto( $preset );
}
else
{
print( "Error, can't handle command $command\n" );
}

View File

@ -1,345 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Panasonic KX-HCM10 Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 continuously monitors the recorded events for the given
# monitor and applies any filters which would delete and/or upload
# matching events
#
use strict;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_VERSION => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*([^=\s]+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use Getopt::Long;
use constant LOG_FILE => ZM_PATH_LOGS.'/zmcontrol-kx-hcm10.log';
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
sub Usage
{
print( "
Usage: zmcontrol-kx-hcm10.pl <various options>
");
exit( -1 );
}
my $arg_string = join( " ", @ARGV );
my $address;
my $command;
my ( $speed, $step );
my ( $xcoord, $ycoord );
my ( $width, $height );
my ( $panspeed, $tiltspeed );
my ( $panstep, $tiltstep );
my $preset;
if ( !GetOptions(
'address=s'=>\$address,
'command=s'=>\$command,
'speed=i'=>\$speed,
'step=i'=>\$step,
'xcoord=i'=>\$xcoord,
'ycoord=i'=>\$ycoord,
'width=i'=>\$width,
'height=i'=>\$height,
'panspeed=i'=>\$panspeed,
'tiltspeed=i'=>\$tiltspeed,
'panstep=i'=>\$panstep,
'tiltstep=i'=>\$tiltstep,
'preset=i'=>\$preset
)
)
{
Usage();
}
if ( !$address )
{
Usage();
}
my $log_file = LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( $arg_string."\n" );
srand( time() );
sub printMsg
{
my $msg = shift;
my $msg_len = length($msg);
print( $msg );
print( "[".$msg_len."]\n" );
}
sub sendCmd
{
my $cmd = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
$ua->agent( "ZoneMinder Control Agent/".ZM_VERSION );
#print( "http://$address/$cmd\n" );
my $req = HTTP::Request->new( GET=>"http://$address/$cmd" );
my $res = $ua->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
print( "Error check failed: '".$res->status_line()."'\n" );
}
return( $result );
}
sub cameraReset
{
print( "Camera Reset\n" );
my $cmd = "nphRestart?PAGE=Restart&Restart=OK";
sendCmd( $cmd );
}
sub moveUp
{
print( "Move Up\n" );
my $cmd = "nphControlCamera?Direction=TiltUp";
sendCmd( $cmd );
}
sub moveDown
{
print( "Move Down\n" );
my $cmd = "nphControlCamera?Direction=TiltDown";
sendCmd( $cmd );
}
sub moveLeft
{
print( "Move Left\n" );
my $cmd = "nphControlCamera?Direction=PanLeft";
sendCmd( $cmd );
}
sub moveRight
{
print( "Move Right\n" );
my $cmd = "nphControlCamera?Direction=PanRight";
sendCmd( $cmd );
}
sub moveMap
{
my ( $xcoord, $ycoord, $width, $height ) = @_;
print( "Move Map to $xcoord,$ycoord\n" );
my $cmd = "nphControlCamera?Direction=Direct&NewPosition.x=$xcoord&NewPosition.y=$ycoord&Width=$width&Height=$height";
sendCmd( $cmd );
}
sub zoomTele
{
print( "Zoom Tele\n" );
my $cmd = "nphControlCamera?Direction=ZoomTele";
sendCmd( $cmd );
}
sub zoomWide
{
print( "Zoom Wide\n" );
my $cmd = "nphControlCamera?Direction=ZoomWide";
sendCmd( $cmd );
}
sub focusNear
{
print( "Focus Near\n" );
my $cmd = "nphControlCamera?Direction=FocusNear";
sendCmd( $cmd );
}
sub focusFar
{
print( "Focus Far\n" );
my $cmd = "nphControlCamera?Direction=FocusFar";
sendCmd( $cmd );
}
sub focusAuto
{
print( "Focus Auto\n" );
my $cmd = "nphControlCamera?Direction=FocusAuto";
sendCmd( $cmd );
}
sub presetClear
{
my $preset = shift || 1;
print( "Clear Preset $preset\n" );
my $cmd = "nphPresetNameCheck?Data=$preset";
sendCmd( $cmd );
}
sub presetSet
{
my $preset = shift || 1;
print( "Set Preset $preset\n" );
my $cmd = "nphPresetNameCheck?PresetName=$preset&Data=$preset";
sendCmd( $cmd );
}
sub presetGoto
{
my $preset = shift || 1;
print( "Goto Preset $preset\n" );
my $cmd = "nphControlCamera?Direction=Preset&PresetOperation=Move&Data=$preset";
sendCmd( $cmd );
}
sub presetHome
{
print( "Home Preset\n" );
my $cmd = "nphControlCamera?Direction=HomePosition";
sendCmd( $cmd );
}
if ( $command eq "move_con_up" )
{
moveUp();
}
elsif ( $command eq "move_con_down" )
{
moveDown();
}
elsif ( $command eq "move_con_left" )
{
moveLeft();
}
elsif ( $command eq "move_con_right" )
{
moveRight();
}
elsif ( $command eq "move_map" )
{
moveMap( $xcoord, $ycoord, $width, $height );
}
elsif ( $command eq "zoom_con_tele" )
{
zoomTele();
}
elsif ( $command eq "zoom_con_wide" )
{
zoomWide();
}
elsif ( $command eq "focus_con_near" )
{
focusNear();
}
elsif ( $command eq "focus_con_far" )
{
focusFar();
}
elsif ( $command eq "focus_auto" )
{
focusAuto();
}
elsif ( $command eq "focus_man" )
{
#focusMan();
}
elsif ( $command eq "preset_home" )
{
presetHome();
}
elsif ( $command eq "preset_set" )
{
presetSet( $preset );
}
elsif ( $command eq "preset_goto" )
{
presetGoto( $preset );
}
else
{
print( "Error, can't handle command $command\n" );
}

View File

@ -1,710 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Pelco-D Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 continuously monitors the recorded events for the given
# monitor and applies any filters which would delete and/or upload
# matching events
#
use strict;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*([^=\s]+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use Getopt::Long;
use Device::SerialPort;
use Time::HiRes qw( usleep );
use constant LOG_FILE => ZM_PATH_LOGS.'/zmcontrol-pelco-d.log';
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
sub Usage
{
print( "
Usage: zmcontrol-pelco-d.pl <various options>
");
exit( -1 );
}
my $arg_string = join( " ", @ARGV );
my $device = "/dev/ttyS0";
my $address = 1;
my $command;
my $autostop;
my ( $speed, $step );
my ( $xcoord, $ycoord );
my ( $panspeed, $tiltspeed );
my ( $panstep, $tiltstep );
my $preset;
if ( !GetOptions(
'device=s'=>\$device,
'address=i'=>\$address,
'command=s'=>\$command,
'autostop=f'=>\$autostop,
'speed=i'=>\$speed,
'step=i'=>\$step,
'xcoord=i'=>\$xcoord,
'ycoord=i'=>\$ycoord,
'panspeed=i'=>\$panspeed,
'tiltspeed=i'=>\$tiltspeed,
'panstep=i'=>\$panstep,
'tiltstep=i'=>\$tiltstep,
'preset=i'=>\$preset
)
)
{
Usage();
}
if ( defined($autostop) )
{
# Convert to microseconds.
$autostop = int(1000000*$autostop);
}
my $log_file = LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( $arg_string."\n" );
srand( time() );
my $serial_port = new Device::SerialPort( $device );
$serial_port->baudrate(2400);
$serial_port->databits(8);
$serial_port->parity('none');
$serial_port->stopbits(1);
$serial_port->handshake('none');
$serial_port->read_const_time(50);
$serial_port->read_char_time(10);
sub printMsg
{
my $msg = shift;
my $prefix = shift || "";
$prefix = $prefix.": " if ( $prefix );
my $line_length = 16;
my $msg_len = int(@$msg);
print( $prefix );
for ( my $i = 0; $i < $msg_len; $i++ )
{
if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) )
{
printf( "\n%*s", length($prefix), "" );
}
printf( "%02x ", $msg->[$i] );
}
print( "[".$msg_len."]\n" );
}
sub sendCmd
{
my $cmd = shift;
my $ack = shift || 0;
my $result = undef;
my $checksum = 0x00;
for ( my $i = 1; $i < int(@$cmd); $i++ )
{
$checksum += $cmd->[$i];
$checksum &= 0xff;
}
push( @$cmd, $checksum );
printMsg( $cmd, "Tx" );
my $id = $cmd->[0] & 0xf;
my $tx_msg = pack( "C*", @$cmd );
#print( "Tx: ".length( $tx_msg )." bytes\n" );
my $n_bytes = $serial_port->write( $tx_msg );
if ( !$n_bytes )
{
print( "Error, write failed: $!" );
}
if ( $n_bytes != length($tx_msg) )
{
print( "Error, incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" );
}
if ( $ack )
{
print( "Waiting for ack\n" );
my $max_wait = 3;
my $now = time();
while( 1 )
{
my ( $count, $rx_msg ) = $serial_port->read(4);
if ( $count )
{
#print( "Rx1: ".$count." bytes\n" );
my @resp = unpack( "C*", $rx_msg );
printMsg( \@resp, "Rx" );
if ( $resp[0] = 0x80 + ($id<<4) )
{
if ( ($resp[1] & 0xf0) == 0x40 )
{
my $socket = $resp[1] & 0x0f;
print( "Got ack for socket $socket\n" );
$result = !undef;
}
else
{
print( "Error, got bogus response\n" );
}
last;
}
else
{
print( "Error, got message for camera ".(($resp[0]-0x80)>>4)."\n" );
}
}
if ( (time() - $now) > $max_wait )
{
print( "Warning, response timeout\n" );
last;
}
}
}
}
my $sync = 0xff;
sub remoteReset
{
print( "Remote Reset\n" );
my @msg = ( $sync, $address, 0x00, 0x0f, 0x00, 0x00 );
sendCmd( \@msg );
}
sub cameraOff
{
print( "Camera Off\n" );
my @msg = ( $sync, $address, 0x08, 0x00, 0x00, 0x00 );
sendCmd( \@msg );
}
sub cameraOn
{
print( "Camera On\n" );
my @msg = ( $sync, $address, 0x88, 0x00, 0x00, 0x00 );
sendCmd( \@msg );
}
sub autoScan
{
print( "Auto Scan\n" );
my @msg = ( $sync, $address, 0x90, 0x00, 0x00, 0x00 );
sendCmd( \@msg );
}
sub manScan
{
print( "Manual Scan\n" );
my @msg = ( $sync, $address, 0x10, 0x00, 0x00, 0x00 );
sendCmd( \@msg );
}
sub stop
{
print( "Stop\n" );
my @msg = ( $sync, $address, 0x00, 0x00, 0x00, 0x00 );
sendCmd( \@msg );
}
sub moveUp
{
print( "Move Up\n" );
my $speed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x08, 0x00, $speed );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveDown
{
print( "Move Down\n" );
my $speed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x10, 0x00, $speed );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveLeft
{
print( "Move Left\n" );
my $speed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x04, $speed, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveRight
{
print( "Move Right\n" );
my $speed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x02, $speed, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveUpLeft
{
print( "Move Up/Left\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x0c, $panspeed, $tiltspeed );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveUpRight
{
print( "Move Up/Right\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x0a, $panspeed, $tiltspeed );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveDownLeft
{
print( "Move Down/Left\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x14, $panspeed, $tiltspeed );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveDownRight
{
print( "Move Down/Right\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $sync, $address, 0x00, 0x12, $panspeed, $tiltspeed );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub flip180
{
print( "Flip 180\n" );
my @msg = ( $sync, $address, 0x00, 0x07, 0x00, 0x21 );
sendCmd( \@msg );
}
sub zeroPan
{
print( "Zero Pan\n" );
my @msg = ( $sync, $address, 0x00, 0x07, 0x00, 0x22 );
sendCmd( \@msg );
}
sub setZoomSpeed
{
my $speed = shift;
my @msg = ( $sync, $address, 0x00, 0x25, 0x00, $speed );
sendCmd( \@msg );
}
sub zoomTele
{
print( "Zoom Tele\n" );
my $speed = shift || 0x01;
setZoomSpeed( $speed );
usleep( 250000 );
my @msg = ( $sync, $address, 0x00, 0x20, 0x00, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setZoomSpeed( 0 );
}
}
sub zoomWide
{
print( "Zoom Wide\n" );
my $speed = shift || 0x01;
setZoomSpeed( $speed );
usleep( 250000 );
my @msg = ( $sync, $address, 0x00, 0x40, 0x00, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setZoomSpeed( 0 );
}
}
sub setFocusSpeed
{
my $speed = shift;
my @msg = ( $sync, $address, 0x00, 0x27, 0x00, $speed );
sendCmd( \@msg );
}
sub focusNear
{
print( "Focus Near\n" );
my $speed = shift || 0x03;
setFocusSpeed( $speed );
usleep( 250000 );
my @msg = ( $sync, $address, 0x01, 0x00, 0x00, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setFocusSpeed( 0 );
}
}
sub focusFar
{
print( "Focus Far\n" );
my $speed = shift || 0x03;
setFocusSpeed( $speed );
usleep( 250000 );
my @msg = ( $sync, $address, 0x00, 0x80, 0x00, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setFocusSpeed( 0 );
}
}
sub focusAuto
{
print( "Focus Auto\n" );
my @msg = ( $sync, $address, 0x00, 0x2b, 0x00, 0x00 );
sendCmd( \@msg );
}
sub focusMan
{
print( "Focus Man\n" );
my @msg = ( $sync, $address, 0x00, 0x2b, 0x00, 0x02 );
sendCmd( \@msg );
}
sub irisClose
{
print( "Iris Close\n" );
my @msg = ( $sync, $address, 0x04, 0x00, 0x00, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setIrisSpeed( 0 );
}
}
sub irisOpen
{
print( "Iris Open\n" );
my @msg = ( $sync, $address, 0x02, 0x80, 0x00, 0x00 );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setIrisSpeed( 0 );
}
}
sub irisAuto
{
print( "Iris Auto\n" );
my @msg = ( $sync, $address, 0x00, 0x2d, 0x00, 0x00 );
sendCmd( \@msg );
}
sub irisMan
{
print( "Iris Man\n" );
my @msg = ( $sync, $address, 0x00, 0x2d, 0x00, 0x02 );
sendCmd( \@msg );
}
sub writeScreen
{
my $string = shift;
print( "Writing '$string' to screen\n" );
my @chars = unpack( "C*", $string );
for ( my $i = 0; $i < length($string); $i++ )
{
printf( "0x%02x\n", $chars[$i] );
my @msg = ( $sync, $address, 0x00, 0x15, $i, $chars[$i] );
sendCmd( \@msg );
}
}
sub clearScreen
{
print( "Clear Screen\n" );
my @msg = ( $sync, $address, 0x00, 0x17, 0x00, 0x00 );
sendCmd( \@msg );
}
sub clearPreset
{
my $preset = shift || 1;
print( "Clear Preset $preset\n" );
my @msg = ( $sync, $address, 0x00, 0x05, 0x00, $preset );
sendCmd( \@msg );
}
sub presetSet
{
my $preset = shift || 1;
print( "Set Preset $preset\n" );
my @msg = ( $sync, $address, 0x00, 0x03, 0x00, $preset );
sendCmd( \@msg );
}
sub presetGoto
{
my $preset = shift || 1;
print( "Goto Preset $preset\n" );
my @msg = ( $sync, $address, 0x00, 0x07, 0x00, $preset );
sendCmd( \@msg );
}
sub presetHome
{
print( "Home Preset\n" );
my @msg = ( $sync, $address, 0x00, 0x07, 0x00, 0x22 );
sendCmd( \@msg );
}
if ( $command eq "reset" )
{
remoteReset();
}
elsif ( $command eq "wake" )
{
cameraOn();
}
elsif ( $command eq "sleep" )
{
cameraOff();
}
elsif ( $command eq "move_con_up" )
{
moveUp( $tiltspeed );
}
elsif ( $command eq "move_con_down" )
{
moveDown( $tiltspeed );
}
elsif ( $command eq "move_con_left" )
{
moveLeft( $panspeed );
}
elsif ( $command eq "move_con_right" )
{
moveRight( $panspeed );
}
elsif ( $command eq "move_con_upleft" )
{
moveUpLeft( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_upright" )
{
moveUpRight( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_downleft" )
{
moveDownLeft( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_downright" )
{
moveDownRight( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_stop" )
{
stop();
}
elsif ( $command eq "zoom_con_tele" )
{
zoomTele( $speed );
}
elsif ( $command eq "zoom_con_wide" )
{
zoomWide( $speed );
}
elsif ( $command eq "zoom_stop" )
{
setZoomSpeed( 0 );
}
elsif ( $command eq "focus_con_near" )
{
focusNear();
}
elsif ( $command eq "focus_con_far" )
{
focusFar();
}
elsif ( $command eq "focus_stop" )
{
stop();
#setFocusSpeed( 0 );
}
elsif ( $command eq "focus_auto" )
{
focusAuto();
}
elsif ( $command eq "focus_man" )
{
focusMan();
}
elsif ( $command eq "iris_con_close" )
{
irisClose();
}
elsif ( $command eq "iris_con_open" )
{
irisOpen();
}
elsif ( $command eq "iris_stop" )
{
stop();
}
elsif ( $command eq "iris_auto" )
{
irisAuto();
}
elsif ( $command eq "iris_man" )
{
irisMan();
}
elsif ( $command eq "preset_home" )
{
presetHome();
}
elsif ( $command eq "preset_set" )
{
presetSet( $preset );
}
elsif ( $command eq "preset_goto" )
{
presetGoto( $preset );
}
else
{
print( "Error, can't handle command $command\n" );
}
$serial_port->close();

View File

@ -1,640 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Pelco-P Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 continuously monitors the recorded events for the given
# monitor and applies any filters which would delete and/or upload
# matching events
#
use strict;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*([^=\s]+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
#use Data::Dumper;
use Getopt::Long;
use Device::SerialPort;
use Time::HiRes qw( usleep );
use constant LOG_FILE => ZM_PATH_LOGS.'/zmcontrol-pelco-p.log';
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
sub Usage
{
print( "
Usage: zmcontrol-pelco-d.pl <various options>
");
exit( -1 );
}
my $arg_string = join( " ", @ARGV );
my $device = "/dev/ttyS0";
my $address = 1;
my $command;
my $autostop;
my ( $speed, $step );
my ( $xcoord, $ycoord );
my ( $panspeed, $tiltspeed );
my ( $panstep, $tiltstep );
my $preset;
if ( !GetOptions(
'device=s'=>\$device,
'address=i'=>\$address,
'command=s'=>\$command,
'autostop=f'=>\$autostop,
'speed=i'=>\$speed,
'step=i'=>\$step,
'xcoord=i'=>\$xcoord,
'ycoord=i'=>\$ycoord,
'panspeed=i'=>\$panspeed,
'tiltspeed=i'=>\$tiltspeed,
'panstep=i'=>\$panstep,
'tiltstep=i'=>\$tiltstep,
'preset=i'=>\$preset
)
)
{
Usage();
}
if ( defined($autostop) )
{
# Convert to microseconds.
$autostop = int(1000000*$autostop);
}
my $log_file = LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( $arg_string."\n" );
srand( time() );
my $serial_port = new Device::SerialPort( $device );
$serial_port->baudrate(2400);
$serial_port->databits(8);
$serial_port->parity('none');
$serial_port->stopbits(1);
$serial_port->handshake('none');
$serial_port->read_const_time(50);
$serial_port->read_char_time(10);
sub printMsg
{
my $msg = shift;
my $prefix = shift || "";
$prefix = $prefix.": " if ( $prefix );
my $line_length = 16;
my $msg_len = int(@$msg);
print( $prefix );
for ( my $i = 0; $i < $msg_len; $i++ )
{
if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) )
{
printf( "\n%*s", length($prefix), "" );
}
printf( "%02x ", $msg->[$i] );
}
print( "[".$msg_len."]\n" );
}
sub sendCmd
{
my $cmd = shift;
my $ack = shift || 0;
my $result = undef;
#print( Dumper( @$cmd ) );
my $checksum = 0x00;
for ( my $i = 0; $i < int(@$cmd)-1; $i++ )
{
$checksum ^= $cmd->[$i];
$checksum &= 0xff;
#printf( "%02x - %02x\n", $cmd->[$i], $checksum );
}
push( @$cmd, $checksum );
printMsg( $cmd, "Tx" );
my $id = $cmd->[0] & 0xf;
my $tx_msg = pack( "C*", @$cmd );
#print( "Tx: ".length( $tx_msg )." bytes\n" );
my $n_bytes = $serial_port->write( $tx_msg );
if ( !$n_bytes )
{
print( "Error, write failed: $!" );
}
if ( $n_bytes != length($tx_msg) )
{
print( "Error, incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" );
}
if ( $ack )
{
print( "Waiting for ack\n" );
my $max_wait = 3;
my $now = time();
while( 1 )
{
my ( $count, $rx_msg ) = $serial_port->read(4);
if ( $count )
{
#print( "Rx1: ".$count." bytes\n" );
my @resp = unpack( "C*", $rx_msg );
printMsg( \@resp, "Rx" );
if ( $resp[0] = 0x80 + ($id<<4) )
{
if ( ($resp[1] & 0xf0) == 0x40 )
{
my $socket = $resp[1] & 0x0f;
print( "Got ack for socket $socket\n" );
$result = !undef;
}
else
{
print( "Error, got bogus response\n" );
}
last;
}
else
{
print( "Error, got message for camera ".(($resp[0]-0x80)>>4)."\n" );
}
}
if ( (time() - $now) > $max_wait )
{
print( "Warning, response timeout\n" );
last;
}
}
}
}
my $stx = 0xa0;
my $etx = 0xaf;
sub cameraOff
{
print( "Camera Off\n" );
my @msg = ( $stx, $address, 0x10, 0x00, 0x00, 0x00, $etx );
sendCmd( \@msg );
}
sub cameraOn
{
print( "Camera On\n" );
my @msg = ( $stx, $address, 0x40, 0x00, 0x00, 0x00, $etx );
sendCmd( \@msg );
}
sub autoScan
{
print( "Auto Scan\n" );
my @msg = ( $stx, $address, 0x90, 0x00, 0x00, 0x00, $etx );
sendCmd( \@msg );
}
sub manScan
{
print( "Manual Scan\n" );
my @msg = ( $stx, $address, 0x10, 0x00, 0x00, 0x00, $etx );
sendCmd( \@msg );
}
sub stop
{
print( "Stop\n" );
my @msg = ( $stx, $address, 0x00, 0x00, 0x00, 0x00, $etx );
sendCmd( \@msg );
}
sub moveUp
{
print( "Move Up\n" );
my $speed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x08, 0x00, $speed, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveDown
{
print( "Move Down\n" );
my $speed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x10, 0x00, $speed, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveLeft
{
print( "Move Left\n" );
my $speed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x04, $speed, 0x00, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveRight
{
print( "Move Right\n" );
my $speed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x02, $speed, 0x00 , $etx);
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveUpLeft
{
print( "Move Up/Left\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x0c, $panspeed, $tiltspeed, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveUpRight
{
print( "Move Up/Right\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x0a, $panspeed, $tiltspeed, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveDownLeft
{
print( "Move Down/Left\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x14, $panspeed, $tiltspeed, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub moveDownRight
{
print( "Move Down/Right\n" );
my $panspeed = shift || 0x3f;
my $tiltspeed = shift || 0x3f;
my @msg = ( $stx, $address, 0x00, 0x12, $panspeed, $tiltspeed, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
stop();
}
}
sub flip180
{
print( "Flip 180\n" );
my @msg = ( $stx, $address, 0x00, 0x07, 0x00, 0x21, $etx );
sendCmd( \@msg );
}
sub zeroPan
{
print( "Zero Pan\n" );
my @msg = ( $stx, $address, 0x00, 0x07, 0x00, 0x22, $etx );
sendCmd( \@msg );
}
sub setZoomSpeed
{
my $speed = shift;
my @msg = ( $stx, $address, 0x00, 0x25, 0x00, $speed, $etx );
sendCmd( \@msg );
}
sub zoomTele
{
print( "Zoom Tele\n" );
my $speed = shift || 0x01;
setZoomSpeed( $speed );
my @msg = ( $stx, $address, 0x00, 0x20, 0x00, 0x00, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setZoomSpeed( 0 );
}
}
sub zoomWide
{
print( "Zoom Wide\n" );
my $speed = shift || 0x01;
setZoomSpeed( $speed );
my @msg = ( $stx, $address, 0x00, 0x40, 0x00, 0x00, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setZoomSpeed( 0 );
}
}
sub setFocusSpeed
{
my $speed = shift;
my @msg = ( $stx, $address, 0x00, 0x27, 0x00, $speed, $etx );
sendCmd( \@msg );
}
sub focusNear
{
print( "Focus Near\n" );
my $speed = shift || 0x03;
setFocusSpeed( $speed );
my @msg = ( $stx, $address, 0x02, 0x00, 0x00, 0x00, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setFocusSpeed( 0 );
}
}
sub focusFar
{
print( "Focus Far\n" );
my $speed = shift || 0x03;
setFocusSpeed( $speed );
my @msg = ( $stx, $address, 0x01, 0x80, 0x00, 0x00, $etx );
sendCmd( \@msg );
if ( $autostop )
{
usleep( $autostop );
setFocusSpeed( 0 );
}
}
sub focusAuto
{
print( "Focus Auto\n" );
my @msg = ( $stx, $address, 0x00, 0x2b, 0x00, 0x01, $etx );
sendCmd( \@msg );
}
sub focusMan
{
print( "Focus Man\n" );
my @msg = ( $stx, $address, 0x00, 0x2b, 0x00, 0x02, $etx );
sendCmd( \@msg );
}
sub writeScreen
{
my $string = shift;
print( "Writing '$string' to screen\n" );
my @chars = unpack( "C*", $string );
for ( my $i = 0; $i < length($string); $i++ )
{
printf( "0x%02x\n", $chars[$i] );
my @msg = ( $stx, $address, 0x00, 0x15, $i, $chars[$i], $etx );
sendCmd( \@msg );
}
}
sub clearScreen
{
print( "Clear Screen\n" );
my @msg = ( $stx, $address, 0x00, 0x17, 0x00, 0x00, $etx );
sendCmd( \@msg );
}
sub clearPreset
{
my $preset = shift || 1;
print( "Clear Preset $preset\n" );
my @msg = ( $stx, $address, 0x00, 0x05, 0x00, $preset, $etx );
sendCmd( \@msg );
}
sub presetSet
{
my $preset = shift || 1;
print( "Set Preset $preset\n" );
my @msg = ( $stx, $address, 0x00, 0x03, 0x00, $preset, $etx );
sendCmd( \@msg );
}
sub presetGoto
{
my $preset = shift || 1;
print( "Goto Preset $preset\n" );
my @msg = ( $stx, $address, 0x00, 0x07, 0x00, $preset, $etx );
sendCmd( \@msg );
}
sub presetHome
{
print( "Home Preset\n" );
my @msg = ( $stx, $address, 0x00, 0x07, 0x00, 0x22, $etx );
sendCmd( \@msg );
}
if ( $command eq "wake" )
{
cameraOn();
}
elsif ( $command eq "sleep" )
{
cameraOff();
}
elsif ( $command eq "move_con_up" )
{
moveUp( $tiltspeed );
}
elsif ( $command eq "move_con_down" )
{
moveDown( $tiltspeed );
}
elsif ( $command eq "move_con_left" )
{
moveLeft( $panspeed );
}
elsif ( $command eq "move_con_right" )
{
moveRight( $panspeed );
}
elsif ( $command eq "move_con_upleft" )
{
moveUpLeft( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_upright" )
{
moveUpRight( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_downleft" )
{
moveDownLeft( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_downright" )
{
moveDownRight( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_stop" )
{
stop();
}
elsif ( $command eq "zoom_con_tele" )
{
zoomTele( $speed );
}
elsif ( $command eq "zoom_con_wide" )
{
zoomWide( $speed );
}
elsif ( $command eq "zoom_stop" )
{
setZoomSpeed( 0 );
}
elsif ( $command eq "focus_con_near" )
{
focusNear();
}
elsif ( $command eq "focus_con_far" )
{
focusFar();
}
elsif ( $command eq "focus_stop" )
{
setFocusSpeed( 0 );
}
elsif ( $command eq "focus_auto" )
{
focusAuto();
}
elsif ( $command eq "focus_man" )
{
focusMan();
}
elsif ( $command eq "preset_home" )
{
presetHome();
}
elsif ( $command eq "preset_set" )
{
presetSet( $preset );
}
elsif ( $command eq "preset_goto" )
{
presetGoto( $preset );
}
else
{
print( "Error, can't handle command $command\n" );
}
$serial_port->close();

View File

@ -1,659 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder VISCA Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 continuously monitors the recorded events for the given
# monitor and applies any filters which would delete and/or upload
# matching events
#
use strict;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*([^=\s]+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use Getopt::Long;
use Device::SerialPort;
use constant LOG_FILE => ZM_PATH_LOGS.'/zmcontrol-visca.log';
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
sub Usage
{
print( "
Usage: zmcontrol-visca.pl <various options>
");
exit( -1 );
}
my $arg_string = join( " ", @ARGV );
my $device = "/dev/ttyS0";
my $address = 1;
my $command;
my ( $speed, $step );
my ( $xcoord, $ycoord );
my ( $panspeed, $tiltspeed );
my ( $panstep, $tiltstep );
my $preset;
if ( !GetOptions(
'device=s'=>\$device,
'address=i'=>\$address,
'command=s'=>\$command,
'speed=i'=>\$speed,
'step=i'=>\$step,
'xcoord=i'=>\$xcoord,
'ycoord=i'=>\$ycoord,
'panspeed=i'=>\$panspeed,
'tiltspeed=i'=>\$tiltspeed,
'panstep=i'=>\$panstep,
'tiltstep=i'=>\$tiltstep,
'preset=i'=>\$preset
)
)
{
Usage();
}
my $log_file = LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( $arg_string."\n" );
srand( time() );
my $serial_port = new Device::SerialPort( $device );
$serial_port->baudrate(9600);
$serial_port->databits(8);
$serial_port->parity('none');
$serial_port->stopbits(1);
$serial_port->handshake('rts');
$serial_port->stty_echo(0);
#$serial_port->read_const_time(250);
$serial_port->read_char_time(2);
sub printMsg
{
my $msg = shift;
my $prefix = shift || "";
$prefix = $prefix.": " if ( $prefix );
my $line_length = 16;
my $msg_len = int(@$msg);
print( $prefix );
for ( my $i = 0; $i < $msg_len; $i++ )
{
if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) )
{
printf( "\n%*s", length($prefix), "" );
}
printf( "%02x ", $msg->[$i] );
}
print( "[".$msg_len."]\n" );
}
sub sendCmd
{
my $cmd = shift;
my $ack = shift || 0;
my $cmp = shift || 0;
my $result = undef;
printMsg( $cmd, "Tx" );
my $id = $cmd->[0] & 0xf;
my $tx_msg = pack( "C*", @$cmd );
#print( "Tx: ".length( $tx_msg )." bytes\n" );
my $n_bytes = $serial_port->write( $tx_msg );
if ( !$n_bytes )
{
print( "Error, write failed: $!" );
}
if ( $n_bytes != length($tx_msg) )
{
print( "Error, incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" );
}
if ( $ack )
{
print( "Waiting for ack\n" );
my $max_wait = 3;
my $now = time();
while( 1 )
{
my ( $count, $rx_msg ) = $serial_port->read(4);
if ( $count )
{
#print( "Rx1: ".$count." bytes\n" );
my @resp = unpack( "C*", $rx_msg );
printMsg( \@resp, "Rx" );
if ( $resp[0] = 0x80 + ($id<<4) )
{
if ( ($resp[1] & 0xf0) == 0x40 )
{
my $socket = $resp[1] & 0x0f;
print( "Got ack for socket $socket\n" );
$result = !undef;
}
else
{
printf( "Error, got bogus response\n" );
}
last;
}
else
{
print( "Error, got message for camera ".(($resp[0]-0x80)>>4)."\n" );
}
}
if ( (time() - $now) > $max_wait )
{
last;
}
}
}
if ( $cmp )
{
print( "Waiting for command complete\n" );
my $max_wait = 10;
my $now = time();
while( 1 )
{
#print( "Waiting\n" );
my ( $count, $rx_msg ) = $serial_port->read(16);
if ( $count )
{
#print( "Rx1: ".$count." bytes\n" );
my @resp = unpack( "C*", $rx_msg );
printMsg( \@resp, "Rx" );
if ( $resp[0] = 0x80 + ($id<<4) )
{
if ( ($resp[1] & 0xf0) == 0x50 )
{
printf( "Got command complete\n" );
$result = !undef;
}
else
{
printf( "Error, got bogus response\n" );
}
last;
}
else
{
print( "Error, got message for camera ".(($resp[0]-0x80)>>4)."\n" );
}
}
if ( (time() - $now) > $max_wait )
{
last;
}
}
}
return( $result );
}
my $sync = 0xff;
sub cameraOff
{
print( "Camera Off\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x00, 0x03, $sync );
sendCmd( \@msg );
}
sub cameraOn
{
print( "Camera On\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x00, 0x02, $sync );
sendCmd( \@msg );
}
sub stop
{
print( "Stop\n" );
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, 0x00, 0x00, 0x03, 0x03, $sync );
sendCmd( \@msg );
}
sub moveUp
{
print( "Move Up\n" );
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, 0x00, $speed, 0x03, 0x01, $sync );
sendCmd( \@msg );
}
sub moveDown
{
print( "Move Down\n" );
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, 0x00, $speed, 0x03, 0x02, $sync );
sendCmd( \@msg );
}
sub moveLeft
{
print( "Move Left\n" );
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, $speed, 0x00, 0x01, 0x03, $sync );
sendCmd( \@msg );
}
sub moveRight
{
print( "Move Right\n" );
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, $speed, 0x00, 0x02, 0x03, $sync );
sendCmd( \@msg );
}
sub moveUpLeft
{
print( "Move Up/Left\n" );
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x01, 0x01, $sync );
sendCmd( \@msg );
}
sub moveUpRight
{
print( "Move Up/Right\n" );
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x02, 0x01, $sync );
sendCmd( \@msg );
}
sub moveDownLeft
{
print( "Move Down/Left\n" );
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x01, 0x02, $sync );
sendCmd( \@msg );
}
sub moveDownRight
{
print( "Move Down/Right\n" );
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x02, 0x02, $sync );
sendCmd( \@msg );
}
sub stepUp
{
print( "Step Up\n" );
my $step = shift;
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, 0x00, $speed, 0x00, 0x00, 0x00, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, $sync );
sendCmd( \@msg );
}
sub stepDown
{
print( "Step Down\n" );
my $step = shift;
$step = -$step;
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, 0x00, $speed, 0x00, 0x00, 0x00, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, $sync );
sendCmd( \@msg );
}
sub stepLeft
{
print( "Step Left\n" );
my $step = shift;
$step = -$step;
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, $speed, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, 0x00, 0x00, 0x00, 0x00, $sync );
sendCmd( \@msg );
}
sub stepRight
{
print( "Step Right\n" );
my $step = shift;
my $speed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, $speed, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, 0x00, 0x00, 0x00, 0x00, $sync );
sendCmd( \@msg );
}
sub stepUpLeft
{
print( "Step Up/Left\n" );
my $panstep = shift;
$panstep = -$panstep;
my $tiltstep = shift;
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, $sync );
sendCmd( \@msg );
}
sub stepUpRight
{
print( "Step Up/Right\n" );
my $panstep = shift;
my $tiltstep = shift;
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, $sync );
sendCmd( \@msg );
}
sub stepDownLeft
{
print( "Step Down/Left\n" );
my $panstep = shift;
$panstep = -$panstep;
my $tiltstep = shift;
$tiltstep = -$tiltstep;
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, $sync );
sendCmd( \@msg );
}
sub stepDownRight
{
print( "Step Down/Right\n" );
my $panstep = shift;
my $tiltstep = shift;
$tiltstep = -$tiltstep;
my $panspeed = shift || 0x40;
my $tiltspeed = shift || 0x40;
my @msg = ( 0x80|$address, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, $sync );
sendCmd( \@msg );
}
sub zoomTele
{
print( "Zoom Tele\n" );
my $speed = shift || 0x06;
my @msg = ( 0x80|$address, 0x01, 0x04, 0x07, 0x20|$speed, $sync );
sendCmd( \@msg );
}
sub zoomWide
{
print( "Zoom Wide\n" );
my $speed = shift || 0x06;
my @msg = ( 0x80|$address, 0x01, 0x04, 0x07, 0x30|$speed, $sync );
sendCmd( \@msg );
}
sub zoomStop
{
print( "Zoom Stop\n" );
my $speed = shift || 0x06;
my @msg = ( 0x80|$address, 0x01, 0x04, 0x07, 0x00, $sync );
sendCmd( \@msg );
}
sub focusNear
{
print( "Focus Near\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x08, 0x03, $sync );
sendCmd( \@msg );
}
sub focusFar
{
print( "Focus Far\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x08, 0x02, $sync );
sendCmd( \@msg );
}
sub focusStop
{
print( "Focus Far\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x08, 0x00, $sync );
sendCmd( \@msg );
}
sub focusAuto
{
print( "Focus Auto\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x38, 0x02, $sync );
sendCmd( \@msg );
}
sub focusMan
{
print( "Focus Man\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x38, 0x03, $sync );
sendCmd( \@msg );
}
sub presetClear
{
my $preset = shift || 1;
print( "Clear Preset $preset\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x3f, 0x00, $preset, $sync );
sendCmd( \@msg );
}
sub presetSet
{
my $preset = shift || 1;
print( "Set Preset $preset\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x3f, 0x01, $preset, $sync );
sendCmd( \@msg );
}
sub presetGoto
{
my $preset = shift || 1;
print( "Goto Preset $preset\n" );
my @msg = ( 0x80|$address, 0x01, 0x04, 0x3f, 0x02, $preset, $sync );
sendCmd( \@msg );
}
sub presetHome
{
print( "Home Preset\n" );
my @msg = ( 0x80|$address, 0x01, 0x06, 0x04, $sync );
sendCmd( \@msg );
}
if ( $command eq "move_con_up" )
{
moveUp( $tiltspeed );
}
elsif ( $command eq "move_con_down" )
{
moveDown( $tiltspeed );
}
elsif ( $command eq "move_con_left" )
{
moveLeft( $panspeed );
}
elsif ( $command eq "move_con_right" )
{
moveRight( $panspeed );
}
elsif ( $command eq "move_con_upleft" )
{
moveUpLeft( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_upright" )
{
moveUpRight( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_downleft" )
{
moveDownLeft( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_con_downright" )
{
moveDownLeft( $panspeed, $tiltspeed );
}
elsif ( $command eq "move_stop" )
{
stop();
}
elsif ( $command eq "move_rel_up" )
{
stepUp( $tiltstep, $tiltspeed );
}
elsif ( $command eq "move_rel_down" )
{
stepDown( $tiltstep, $tiltspeed );
}
elsif ( $command eq "move_rel_left" )
{
stepLeft( $panstep, $panspeed );
}
elsif ( $command eq "move_rel_right" )
{
stepRight( $panstep, $panspeed );
}
elsif ( $command eq "move_rel_upleft" )
{
stepUpLeft( $panstep, $tiltstep, $panspeed, $tiltspeed );
}
elsif ( $command eq "move_rel_upright" )
{
stepUpRight( $panstep, $tiltstep, $panspeed, $tiltspeed );
}
elsif ( $command eq "move_rel_downleft" )
{
stepDownLeft( $panstep, $tiltstep, $panspeed, $tiltspeed );
}
elsif ( $command eq "move_rel_downright" )
{
stepDownRight( $panstep, $tiltstep, $panspeed, $tiltspeed );
}
elsif ( $command eq "zoom_con_tele" )
{
zoomTele( $speed );
}
elsif ( $command eq "zoom_con_wide" )
{
zoomWide( $speed );
}
elsif ( $command eq "zoom_stop" )
{
zoomStop();
}
elsif ( $command eq "focus_con_near" )
{
focusNear();
}
elsif ( $command eq "focus_con_far" )
{
focusFar();
}
elsif ( $command eq "focus_stop" )
{
focusStop();
}
elsif ( $command eq "focus_auto" )
{
focusAuto();
}
elsif ( $command eq "focus_man" )
{
focusMan();
}
elsif ( $command eq "preset_home" )
{
presetHome();
}
elsif ( $command eq "preset_set" )
{
presetSet( $preset );
}
elsif ( $command eq "preset_goto" )
{
presetGoto( $preset );
}
else
{
print( "Error, can't handle command $command\n" );
}
$serial_port->close();

View File

@ -1,634 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Daemon Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 is the gateway for controlling the various ZoneMinder
# daemons. All starting, stopping and restarting goes through here.
# On the first invocation it starts up a server which subsequently
# records what's running and what's not. Other invocations just
# connect to the server and pass instructions to it.
#
use strict;
use bytes;
# ==========================================================================
#
# User config
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
use constant ZM_PATH_WEB => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\\s]+)\s*=\s*(\S+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
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() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use constant DC_SOCK_FILE => ZM_PATH_SOCKS.'/zmdc.sock';
use constant DC_LOG_FILE => ZM_PATH_LOGS.'/zmdc.log';
use constant MAX_CONNECT_DELAY => 10;
use constant VERBOSE => 0; # Whether to output more verbose debug
# ==========================================================================
#
# Don't change anything from here on down
#
# ==========================================================================
use POSIX;
use Socket;
use IO::Handle;
use Data::Dumper;
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my @daemons = ( 'zmc', 'zma', 'zmf', 'zmfilter.pl', 'zmaudit.pl', 'zmtrigger.pl', 'zmx10.pl', 'zmwatch.pl', 'zmupdate.pl', 'zmtrack.pl' );
my $command = shift @ARGV;
die( "No command given" ) unless( $command );
my $needs_daemon = $command !~ /(?:shutdown|status|check)/;
my $daemon = shift( @ARGV );
die( "No daemon given" ) unless( !$needs_daemon || $daemon );
my @args;
my $daemon_patt = '('.join( '|', @daemons ).')';
if ( $needs_daemon )
{
if ( $daemon =~ /^${daemon_patt}$/ )
{
$daemon = $1;
}
else
{
die( "Invalid daemon '$daemon' specified" );
}
}
foreach my $arg ( @ARGV )
{
# Detaint arguments, if they look ok
#if ( $arg =~ /^(-{0,2}[\w]+)/ )
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ )
{
push( @args, $1 );
}
else
{
die( "Bogus argument '$arg' found" );
}
}
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" );
my $saddr = sockaddr_un( DC_SOCK_FILE );
if ( !connect( CLIENT, $saddr ) )
{
if ( $command eq "check" )
{
print( "stopped\n" );
exit();
}
# The server isn't there
print( "Unable to connect, starting server\n" );
close( CLIENT );
if ( my $cpid = fork() )
{
# Parent process just sleep and fall through
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" );
my $attempts = 0;
while (!connect( CLIENT, $saddr ))
{
$attempts++;
die( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY);
sleep(1);
}
}
elsif ( defined($cpid) )
{
setpgrp();
open( LOG, ">>".DC_LOG_FILE ) or die( "Can't open log file: $!" );
open(STDOUT, ">&LOG") || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open(STDERR, ">&LOG") || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
dprint( "Server starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
kill_all( 1 );
socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" );
unlink( DC_SOCK_FILE );
bind( SERVER, $saddr ) or die( "Can't bind: $!" );
listen( SERVER, SOMAXCONN ) or die( "Can't listen: $!" );
$SIG{CHLD} = \&reaper;
$SIG{INT} = \&shutdown_all;
$SIG{TERM} = \&shutdown_all;
$SIG{ABRT} = \&shutdown_all;
$SIG{HUP} = \&status;
my %cmd_hash;
my %pid_hash;
sub cprint
{
if ( fileno(CLIENT) )
{
print CLIENT @_
}
}
sub dprint
{
if ( fileno(CLIENT) )
{
print CLIENT @_
}
print @_;
}
sub start
{
my $daemon = shift;
my @args = @_;
my $command = $daemon;
$command .= ' '.join( ' ', ( @args ) ) if ( @args );
my $process = $cmd_hash{$command};
if ( !$process )
{
# It's not running, or at least it's not been started by us
$process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef };
}
elsif ( $process->{pid} && $pid_hash{$process->{pid}} )
{
dprint( "'$process->{command}' already running at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}\n" );
return();
}
if ( my $cpid = fork() )
{
my $sigset = POSIX::SigSet->new;
my $blockset = POSIX::SigSet->new( SIGCHLD );
sigprocmask( SIG_BLOCK, $blockset, $sigset ) or die( "Can't block SIGCHLD: $!" );
$process->{pid} = $cpid;
$process->{started} = time();
delete( $process->{pending} );
dprint( "'$command' starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}\n" );
$cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process;
sigprocmask( SIG_SETMASK, $sigset ) or die( "Can't restore SIGCHLD: $!" );
}
elsif ( defined($cpid ) )
{
# Child process
$SIG{CHLD} = 'DEFAULT';
$SIG{INT} = 'DEFAULT';
$SIG{TERM} = 'DEFAULT';
$SIG{ABRT} = 'DEFAULT';
$SIG{HUP} = 'DEFAULT';
dprint( "'".join( ' ', ( $daemon, @args ) )."' started at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
if ( $daemon =~ /^${daemon_patt}$/ )
{
$daemon = ZM_PATH_BIN.'/'.$1;
}
else
{
die( "Invalid daemon '$daemon' specified" );
}
my @good_args;
foreach my $arg ( @args )
{
# Detaint arguments, if they look ok
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ )
{
push( @good_args, $1 );
}
else
{
die( "Bogus argument '$arg' found" );
}
}
exec( $daemon, @good_args ) or die( "Can't exec: $!" );
}
else
{
die( "Can't fork: $!" );
}
}
sub _stop
{
my $final = shift;
my $daemon = shift;
my @args = @_;
my $command = $daemon;
$command .= ' '.join( ' ', ( @args ) ) if ( @args );
my $process = $cmd_hash{$command};
if ( !$process )
{
dprint( "Can't find process with command of '$command'\n" );
return();
}
elsif ( $process->{pending} )
{
delete( $cmd_hash{$command} );
dprint( "Command '$command' removed from pending list at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
return();
}
my $cpid = $process->{pid};
if ( !$pid_hash{$cpid} )
{
dprint( "No process with command of '$command' is running\n" );
return();
}
print( "'$daemon ".join( ' ', @args )."' stopping at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
$process->{keepalive} = !$final;
kill( 'TERM', $cpid );
delete( $cmd_hash{$command} );
# Now check it has actually gone away, if not kill -9 it
my $count = 0;
while( $cpid && kill( 0, $cpid ) )
{
if ( $count++ > 5 )
{
kill( 'KILL', $cpid );
}
sleep( 1 );
}
}
sub stop
{
_stop( 1, @_ );
}
sub restart
{
my $daemon = shift;
my @args = @_;
my $command = $daemon;
$command .= ' '.join( ' ', ( @args ) ) if ( @args );
my $process = $cmd_hash{$command};
if ( $process )
{
if ( $process->{pid} )
{
my $cpid = $process->{pid};
if ( defined($pid_hash{$cpid}) )
{
_stop( 0, $daemon, @args );
return;
}
}
}
start( $daemon, @args );
}
sub reaper
{
while ( (my $cpid = waitpid( -1, WNOHANG )) > 0 )
{
my $status = $?;
my $process = $pid_hash{$cpid};
delete( $pid_hash{$cpid} );
if ( !$process )
{
dprint( "Can't find child with pid of '$cpid'\n" );
next;
}
$process->{stopped} = time();
$process->{runtime} = ($process->{stopped}-$process->{started});
delete( $process->{pid} );
my $exit_status = $status>>8;
my $exit_signal = $status&0xfe;
my $core_dumped = $status&0x01;
if ( $exit_status == 0 )
{
print( "'$process->{daemon} ".join( ' ', @{$process->{args}} )."' died at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{stopped} ) ) );
}
else
{
print( "'$process->{daemon} ".join( ' ', @{$process->{args}} )."' crashed at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{stopped} ) ) );
}
print( ", exit status $exit_status" ) if ( $exit_status );
print( ", signal $exit_signal" ) if ( $exit_signal );
#print( ", core dumped" ) if ( $core_dumped );
print( "\n" );
if ( $process->{keepalive} )
{
if ( !$process->{delay} || ($process->{runtime} > (10*$process->{delay})) )
{
start( $process->{daemon}, @{$process->{args}} );
$process->{delay} = 5;
}
else
{
$cmd_hash{$process->{command}} = $process;
$process->{pending} = $process->{stopped}+$process->{delay};
$process->{delay} *= 2;
# Limit the start delay to 15 minutes max
if ( $process->{delay} > ZM_MAX_RESTART_DELAY )
{
$process->{delay} = ZM_MAX_RESTART_DELAY;
}
}
}
}
$SIG{CHLD} = \&reaper;
}
sub kill_all
{
my $delay = shift;
sleep( $delay );
foreach my $daemon ( @daemons )
{
qx( killall --quiet --signal TERM $daemon );
}
sleep( $delay );
foreach my $daemon ( @daemons )
{
qx( killall --quiet --signal KILL $daemon );
}
}
sub shutdown_all()
{
foreach my $process ( values( %pid_hash ) )
{
stop( $process->{daemon}, @{$process->{args}} );
}
kill_all( 5 );
dprint( "Server shutdown at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
unlink( DC_SOCK_FILE );
close( CLIENT );
close( SERVER );
exit();
}
sub check
{
my $daemon = shift;
my @args = @_;
my $command = $daemon;
$command .= ' '.join( ' ', ( @args ) ) if ( @args );
my $process = $cmd_hash{$command};
if ( !$process )
{
cprint( "unknown\n" );
}
elsif ( $process->{pending} )
{
cprint( "pending\n" );
}
else
{
my $cpid = $process->{pid};
if ( !$pid_hash{$cpid} )
{
cprint( "stopped\n" );
}
else
{
cprint( "running\n" );
}
}
}
sub status
{
my $daemon = shift;
my @args = @_;
if ( defined($daemon) )
{
my $command = $daemon;
$command .= ' '.join( ' ', ( @args ) ) if ( @args );
my $process = $cmd_hash{$command};
if ( !$process )
{
dprint( "'$command' not running\n" );
return();
}
if ( $process->{pending} )
{
dprint( "'$process->{command}' pending at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )."\n" );
}
else
{
my $cpid = $process->{pid};
if ( !$pid_hash{$cpid} )
{
dprint( "'$command' not running\n" );
return();
}
}
dprint( "'$process->{command}' running at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}" );
}
else
{
foreach my $process ( values(%pid_hash) )
{
dprint( "'$process->{command}' running at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}" );
dprint( ", valid" ) if ( kill( 0, $process->{pid} ) );
dprint( "\n" );
}
foreach my $process ( values( %cmd_hash ) )
{
if ( $process->{pending} )
{
dprint( "'$process->{command}' pending at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )."\n" );
}
}
}
}
my $rin = '';
vec( $rin, fileno(SERVER),1) = 1;
my $win = $rin;
my $ein = $win;
my $timeout = 1;
#my ( $nfound, $timeleft) = select( $rin, $win, $ein, $timeout );
#print( "F:".fileno(SERVER)."\n" );
while( 1 )
{
my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout );
#print( "Off select, NF:$nfound, ER:$!\n" );
#print( vec( $rout, fileno(SERVER),1)."\n" );
#print( vec( $eout, fileno(SERVER),1)."\n" );
#print( "C:".fileno(CLIENT)."S:".fileno(SERVER)."\n" );
if ( $nfound > 0 )
{
if ( vec( $rout, fileno(SERVER),1) )
{
my $paddr = accept( CLIENT, SERVER );
my $message = <CLIENT>;
next if ( !$message );
my ( $command, $daemon, @args ) = split( ';', $message );
if ( $command eq 'start' )
{
start( $daemon, @args );
}
elsif ( $command eq 'stop' )
{
stop( $daemon, @args );
}
elsif ( $command eq 'restart' )
{
restart( $daemon, @args );
}
elsif ( $command eq 'shutdown' )
{
shutdown_all();
}
elsif ( $command eq 'check' )
{
check( $daemon, @args );
}
elsif ( $command eq 'status' )
{
if ( $daemon )
{
status( $daemon, @args );
}
else
{
status();
}
}
else
{
dprint( "Invalid command '$command'\n" );
}
close( CLIENT );
}
else
{
die( "Bogus descriptor" );
}
}
elsif ( $nfound < 0 )
{
if ( $! == EINTR )
{
# Dead child, will be reaped
#print( "Probable dead child\n" );
}
else
{
die( "Can't select: $!" );
}
}
else
{
#print( "Select timed out\n" );
foreach my $process ( values( %cmd_hash ) )
{
if ( $process->{pending} && $process->{pending} <= time() )
{
dprint( "Starting pending process, $process->{command}\n" );
start( $process->{daemon}, @{$process->{args}} );
}
}
}
}
dprint( "Server exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
close( LOG );
exit();
}
else
{
die( "Can't fork: $!" );
}
}
if ( $command eq "check" && !$daemon )
{
print( "running\n" );
exit();
}
# The server is there, connect to it
#print( "Writing commands\n" );
CLIENT->autoflush();
my $message = "$command";
$message .= ";$daemon" if ( $daemon );
$message .= ";".join( ';', @args ) if ( @args );
print( CLIENT $message );
shutdown( CLIENT, 1 );
while ( my $line = <CLIENT> )
{
chomp( $line );
print( "$line\n" );
}
close( CLIENT );
#print( "Finished writing, bye\n" );

File diff suppressed because it is too large Load Diff

View File

@ -1,414 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Package Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 is used to start and stop the ZoneMinder package primarily to
# allow command line control for automatic restart on reboot (see zm script)
#
use strict;
use bytes;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
use constant ZM_PATH_WEB => "<from zmconfig>";
use constant ZM_PATH_CGI => "<from zmconfig>";
use constant ZM_WEB_USER => "<from zmconfig>";
use constant ZM_WEB_GROUP => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\\s]+)\s*=\s*(\S+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
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() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use constant LOG_FILE => ZM_PATH_LOGS.'/zmpkg.log';
use constant DBG_LEVEL => 0; # 0 is errors, warnings and info only, > 0 for debug
# ==========================================================================
#
# Don't change anything below here
#
# ==========================================================================
use DBI;
use POSIX;
use Time::HiRes qw/gettimeofday/;
# Detaint our environment
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $command = $ARGV[0];
my $state;
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
if ( !$command || $command !~ /^(?:start|stop|restart|status)$/ )
{
if ( $command )
{
# Check to see if it's a valid run state
my $sql = "select * from States where Name = '$command'";
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() );
if ( $state = $sth->fetchrow_hashref() )
{
$state->{Name} = $command;
$state->{Definitions} = [];
foreach( split( ',', $state->{Definition} ) )
{
my ( $id, $function ) = split( ':', $_ );
push( @{$state->{Definitions}}, { Id=>$id, Function=>$function } );
}
$command = 'state';
}
else
{
$command = undef;
}
}
if ( !$command )
{
print( "Usage: zmpkg.pl <start|stop|restart|status|'state'>\n" );
exit( -1 );
}
}
# Move to the right place
chdir( ZM_PATH_WEB ) or die( "Can't chdir to '".ZM_PATH_WEB."': $!" );
my $dbg_id = "";
my $log_file = LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
Info( "Command: $command\n" );
my $web_uid = (getpwnam( ZM_WEB_USER ))[2];
my $web_gid = (getgrnam( ZM_WEB_GROUP ))[2];
if ( $> != $web_uid )
{
chown( $web_uid, $web_gid, $log_file ) or die( "Can't change permissions on log file: $!" )
}
my $retval = 0;
# Determine the appropriate syntax for the su command
my $cmd_prefix = getCmdPrefix();
if ( $command eq "state" )
{
Info( "Updating DB: $state->{Name}\n" );
my $sql = "select * from Monitors order by Id asc";
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() );
while( my $monitor = $sth->fetchrow_hashref() )
{
foreach my $definition ( @{$state->{Definitions}} )
{
if ( $monitor->{Id} =~ /^$definition->{Id}$/ )
{
$monitor->{NewFunction} = $definition->{Function};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None' if ( !$monitor->{NewFunction} );
if ( $monitor->{Function} ne $monitor->{NewFunction} )
{
my $sql = "update Monitors set Function = ? where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() );
}
}
$sth->finish();
$command = "restart";
}
if ( $command =~ /^(?:stop|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $status eq "running" )
{
runCommand( "zmdc.pl shutdown" );
removeShm();
}
else
{
$retval = 1;
}
}
if ( $command =~ /^(?:start|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $status eq "stopped" )
{
removeShm();
runCommand( "zmfix" );
runCommand( "zmdc.pl status" );
my $sql = "select * from Monitors";
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() );
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' )
{
if ( ZM_OPT_FRAME_SERVER )
{
runCommand( "zmdc.pl start zmf -m $monitor->{Id}" );
}
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
}
if ( 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();
# This is now started unconditionally
runCommand( "zmdc.pl start zmfilter.pl" );
runCommand( "zmdc.pl start zmaudit.pl -d 900 -y" );
if ( ZM_OPT_TRIGGERS )
{
runCommand( "zmdc.pl start zmtrigger.pl" );
}
if ( ZM_OPT_X10 )
{
runCommand( "zmdc.pl start zmx10.pl -c start" );
}
runCommand( "zmdc.pl start zmwatch.pl" );
if ( ZM_CHECK_FOR_UPDATES )
{
runCommand( "zmdc.pl start zmupdate.pl -c" );
}
}
else
{
$retval = 1;
}
}
if ( $command eq "status" )
{
my $status = runCommand( "zmdc.pl check" );
print( STDOUT $status."\n" );
}
exit( $retval );
sub getCmdPrefix
{
Debug( "Testing valid shell syntax\n" );
my ( $name ) = getpwuid( $> );
if ( $name eq ZM_WEB_USER )
{
Debug( "Running as '$name', su commands not needed\n" );
return( "" );
}
my $null_command = "true";
my $prefix = "su ".ZM_WEB_USER." -c ";
my $command = $prefix."'".$null_command."'";
Debug( "Testing '$command'\n" );
my $output = qx($command);
my $status = $? >> 8;
if ( !$status )
{
Debug( "Test ok, using prefix '$prefix'\n" );
return( $prefix );
}
else
{
chomp( $output );
Debug( "Test failed, '$output'\n" );
$prefix = "su ".ZM_WEB_USER." --shell=/bin/sh --command=";
$command = $prefix."'true'";
Debug( "Testing '$command'\n" );
$output = qx($command);
$status = $? >> 8;
if ( !$status )
{
Debug( "Test ok, using prefix '$prefix'\n" );
return( $prefix );
}
else
{
chomp( $output );
Debug( "Test failed, '$output'\n" );
}
}
Error( "Unable to find valid 'su' syntax\n" );
exit( -1 );
}
sub removeShm
{
Debug( "Removing shared memory\n" );
# Find ZoneMinder shared memory
my $command = "ipcs -m | grep '^".substr( sprintf( "0x%x", hex(ZM_SHM_KEY) ), 0, -2 )."'";
Debug( "Checking for shared memory with '$command'\n" );
open( CMD, "$command |" ) or die( "Can't execute '$command': $!" );
while( <CMD> )
{
chomp;
my ( $key, $id ) = split( /\s+/ );
if ( $id =~ /^(\d+)/ )
{
$id = $1;
$command = "ipcrm shm $id";
Debug( "Removing shared memory with '$command'\n" );
qx( $command );
}
}
close( CMD );
}
sub runCommand
{
my $command = shift;
$command = $cmd_prefix."'".ZM_PATH_BIN."/".$command."'";
Debug( "Command: $command\n" );
my $output = qx($command);
my $status = $? >> 8;
chomp( $output );
if ( $status || DBG_LEVEL > 0 )
{
if ( $status )
{
Error( "Unable to run '$command', output is '$output'\n" );
exit( -1 );
}
else
{
Debug( "Output: $output\n" );
}
}
return( $output );
}
sub dbgPrint
{
my $code = shift;
my $string = shift;
my $line = shift;
$string =~ s/[\r\n]+$//g;
my ($seconds, $microseconds) = gettimeofday();
if ( $line )
{
my $file = __FILE__;
$file =~ s|^.*/||g;
printf( STDERR "%s.%06d %s[%d].%s-%s/%d [%s]\n", strftime( "%x %H:%M:%S", localtime( $seconds ) ), $microseconds, $dbg_id, $$, $file, $line, $code, $string );
}
else
{
printf( STDERR "%s.%06d %s[%d].%s [%s]\n", strftime( "%x %H:%M:%S", localtime( $seconds ) ), $microseconds, $dbg_id, $$, $code, $string );
}
}
sub Debug
{
dbgPrint( "DBG", $_[0] ) if ( DBG_LEVEL >= 1 );
}
sub Info
{
dbgPrint( "INF", $_[0] ) if ( DBG_LEVEL >= 0 );
}
sub Warning
{
dbgPrint( "WAR", $_[0] ) if ( DBG_LEVEL >= -1 );
}
sub Error
{
dbgPrint( "ERR", $_[0] ) if ( DBG_LEVEL >= -2 );
}

View File

@ -1,282 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Experimental PTZ Tracking Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 is used to trigger and cancel alarms from external sources
# using an arbitrary text based format
#
use strict;
use bytes;
# ==========================================================================
#
# User config
#
# ==========================================================================
use constant ZM_CONFIG => "/usr/local/etc/zm.conf"; # Path to the ZoneMinder config file, autogenerated do not change (from zmconfig)
use constant ZM_VERSION => "1.20.2"; # ZoneMinder version number, autogenerated do not change (from zmconfig)
use constant ZM_PATH_BIN => "/usr/local/bin"; # Path to the ZoneMinder executables, autogenerated do not change (from zmconfig)
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*([^=\s]+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use constant LOG_FILE => ZM_PATH_LOGS.'/zmtrack-%s.log';
use constant SLEEP_TIME => 10000; # In microseconds
use constant VERBOSE => 1; # Whether to output more verbose debug
# ==========================================================================
#
# Don't change anything from here on down
#
# ==========================================================================
use DBI;
use POSIX;
use Data::Dumper;
use Getopt::Long;
use Time::HiRes qw( usleep );
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $mid = 0;
sub Usage
{
print( "
Usage: zmtrack.pl -m <monitor>,--monitor=<monitor>]
Parameters are :-
-m<monitor>, --monitor=<monitor> - Id of the monitor to track
");
exit( -1 );
}
if ( !GetOptions( 'monitor=s'=>\$mid ) )
{
Usage();
}
my ( $detaint_mid ) = $mid =~ /^(\d+)$/;
$mid = $detaint_mid;
my $log_file = sprintf( LOG_FILE, $mid );
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( "Tracker daemon $mid (experimental) starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my $sql = "select C.*,M.* from Monitors as M left join Controls as C on M.ControlId = C.Id where M.Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $mid ) or die( "Can't execute '$sql': ".$sth->errstr() );
my $monitor = $sth->fetchrow_hashref();
if ( !$monitor )
{
print( "Can't find monitor '$mid'\n" );
exit( -1 );
}
if ( !$monitor->{Controllable} )
{
print( "Monitor '$mid' is not controllable\n" );
exit( -1 );
}
if ( !$monitor->{TrackMotion} )
{
print( "Monitor '$mid' is not configured to track motion\n" );
exit( -1 );
}
if ( !$monitor->{CanMoveMap} )
{
print( "Monitor '$mid' cannot move in map mode" );
if ( $monitor->{CanMoveRel} )
{
print( ", falling back to pseudo map mode\n" );
}
else
{
print( "\n" );
exit( -1 );
}
}
my $shm_dets = {
"Size" => 56, # Size of segment to read, must be big enough for all fields below
"state"=>{ "Offset"=>8, "Size"=>4 },
"alarm_post"=>{ "Offset"=>48, "Size"=>8 },
};
sub ShmRead
{
my $monitor = shift;
my $detail = shift;
my $shm_detail = $shm_dets->{$detail} or die( "Can't find shared memory detail for '$detail'" );
my $shm_data;
if ( !shmread( $monitor->{ShmId}, $shm_data, $shm_detail->{Offset}, $shm_detail->{Size} ) )
{
print( "Can't read ".$shm_detail->{Size}." bytes at offset ".$shm_detail->{Offset}." from shared memory '$monitor->{ShmKey}/$monitor->{ShmId}': $!\n" );
return( undef );
}
return( $shm_data );
}
print( "Found monitor for id '".$monitor->{Id}."'\n" ) if ( VERBOSE );
$monitor->{ShmKey} = hex(ZM_SHM_KEY)|$monitor->{Id};
$monitor->{ShmId} = shmget( $monitor->{ShmKey}, $shm_dets->{Size}, 0 );
if ( !defined($monitor->{ShmId}) )
{
printf( "Can't get shared memory id '%x': $!\n", $monitor->{ShmKey}, $! );
exit( -1 );
}
sub Suspend
{
my $monitor = shift;
my $suspend_cmd = ZM_PATH_BIN."/zmu -m ".$monitor->{Id}." -u -U admin -P pc00zm";
qx( $suspend_cmd );
}
sub Resume
{
my $monitor = shift;
sleep( $monitor->{TrackDelay} );
my $resume_cmd = ZM_PATH_BIN."/zmu -m ".$monitor->{Id}." -r -U admin -P pc00zm";
qx( $resume_cmd );
}
sub Track
{
my $monitor = shift;
my ( $x, $y ) = @_;
my ( $detaint_x ) = $x =~ /^(\d+)$/; $x = $detaint_x;
my ( $detaint_y ) = $y =~ /^(\d+)$/; $y = $detaint_y;
my $move_cmd = $monitor->{Command};
$move_cmd = ZM_PATH_BIN.'/'.$move_cmd if ( $move_cmd !~ m|^/| );
$move_cmd .= " --device=".$monitor->{ControlDevice} if ( $monitor->{ControlDevice} );
$move_cmd .= " --address=".$monitor->{ControlAddress} if ( $monitor->{ControlAddress} );
$move_cmd .= " --command=".($monitor->{CanMoveMap}?"move_map":"move_pseudo_map")." --xcoord=$x --ycoord=$y --width=".$monitor->{Width}." --height=".$monitor->{Height};
qx( $move_cmd );
}
sub Return
{
my $monitor = shift;
my $move_cmd = $monitor->{Command};
$move_cmd = ZM_PATH_BIN.'/'.$move_cmd if ( $move_cmd !~ m|^/| );
$move_cmd .= " --device=".$monitor->{ControlDevice} if ( $monitor->{ControlDevice} );
$move_cmd .= " --address=".$monitor->{ControlAddress} if ( $monitor->{ControlAddress} );
$move_cmd .= " --command=".($monitor->{ReturnLocation}?"preset1":"preset_home");
qx( $move_cmd );
}
my $last_alarm = 0;
if ( ($monitor->{ReturnLocation} >= 0) )
{
Suspend( $monitor );
Return( $monitor );
Resume( $monitor );
}
my $alarmed = undef;
while( 1 )
{
my $state = ShmRead( $monitor, "state" );
next if ( !defined($state) );
$state = unpack( "l", $state );
if ( $state == 2 ) # Alarmed
{
my $alarm_pos = ShmRead( $monitor, "alarm_pos" );
next if ( !defined($alarm_pos) );
my ( $alarm_x, $alarm_y ) = unpack( "ll", $alarm_pos );
if ( $alarm_x > 0 && $alarm_y > 0 )
{
print( "Got alarm at $alarm_x, $alarm_y\n" ) if ( VERBOSE );
Suspend( $monitor );
Track( $monitor, $alarm_x, $alarm_y );
Resume( $monitor );
$last_alarm = time();
$alarmed = !undef;
}
}
else
{
if ( VERBOSE && $alarmed )
{
print( "Left alarm state\n" );
$alarmed = undef;
}
if ( ($monitor->{ReturnLocation} >= 0) && ($last_alarm > 0) && ((time()-$last_alarm) > $monitor->{ReturnDelay}) )
{
print( "Returning to location ".$monitor->{ReturnLocation}."\n" ) if ( VERBOSE );
Suspend( $monitor );
Return( $monitor );
Resume( $monitor );
$last_alarm = 0;
}
}
usleep( SLEEP_TIME );
}

View File

@ -1,377 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder External Trigger Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 is used to trigger and cancel alarms from external sources
# using an arbitrary text based format
#
use strict;
use bytes;
# ==========================================================================
#
# User config
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_VERSION => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
use constant ZM_PATH_WEB => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\\s]+)\s*=\s*(\S+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute '$sql': ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use constant LOG_FILE => ZM_PATH_LOGS.'/zmtrigger.log';
use constant MAX_CONNECT_DELAY => 10;
use constant VERBOSE => 0; # Whether to output more verbose debug
# Now define the trigger sources, can be inet socket, unix socket or file based
# Ignore parser field for now.
my @sources = (
{ name=>"S1", type=>"inet", port=>"6802", parser=>"", },
{ name=>"S2", type=>"unix", path=>"/tmp/test.sock", parser=>"", },
{ name=>"S3", type=>"file", path=>"/dev/ttyS0", parser=>"", },
);
# Need to make sure each parser function is defined
sub parseTrigger1
{
}
# ==========================================================================
#
# Don't change anything from here on down
#
# ==========================================================================
use DBI;
use POSIX;
use Fcntl;
use Socket;
use IO::Handle;
use Data::Dumper;
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
open( LOG, ">>".LOG_FILE ) or die( "Can't open log file: $!" );
open(STDOUT, ">&LOG") || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open(STDERR, ">&LOG") || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( "Trigger daemon starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my $sql = "select * from Monitors where Id = ? or Name = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
$SIG{HUP} = \&status;
my $base_rin = '';
foreach my $source ( @sources )
{
print( "Opening source '$source->{name}'\n" );
if ( $source->{type} eq "inet" )
{
local *sfh;
my $saddr = sockaddr_in( $source->{port}, INADDR_ANY );
socket( *sfh, PF_INET, SOCK_STREAM, getprotobyname('tcp') ) or die( "Can't open socket: $!" );
setsockopt( *sfh, SOL_SOCKET, SO_REUSEADDR, 1 );
bind( *sfh, $saddr ) or die( "Can't bind: $!" );
listen( *sfh, SOMAXCONN ) or die( "Can't listen: $!" );
$source->{handle} = *sfh;
vec( $base_rin, fileno($source->{handle}),1) = 1;
}
elsif ( $source->{type} eq "unix" )
{
local *sfh;
unlink( $source->{path} );
my $saddr = sockaddr_un( $source->{path} );
socket( *sfh, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" );
bind( *sfh, $saddr ) or die( "Can't bind: $!" );
listen( *sfh, SOMAXCONN ) or die( "Can't listen: $!" );
$source->{handle} = *sfh;
vec( $base_rin, fileno($source->{handle}),1) = 1;
}
elsif ( $source->{type} eq "file" )
{
local *sfh;
#sysopen( *sfh, $source->{path}, O_NONBLOCK|O_RDONLY ) or die( "Can't sysopen: $!" );
#open( *sfh, "<".$source->{path} ) or die( "Can't open: $!" );
open( *sfh, "+<".$source->{path} ) or die( "Can't open: $!" );
$source->{handle} = *sfh;
vec( $base_rin, fileno($source->{handle}),1) = 1;
}
else
{
die( "Bogus source type '$source->{type}' found for '$source->{name}'" );
}
}
my $sigset = POSIX::SigSet->new;
my $blockset = POSIX::SigSet->new( SIGCHLD );
sigprocmask( SIG_BLOCK, $blockset, $sigset ) or die( "Can't block SIGCHLD: $!" );
my %connections;
$! = undef;
my $rin = '';
my $win = $rin;
my $ein = $win;
my $timeout = 1;
my %actions;
while( 1 )
{
$rin = $base_rin;
foreach my $fileno ( keys(%connections) )
{
vec( $rin, $fileno,1) = 1;
}
my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout );
if ( $nfound > 0 )
{
print( "Got input from $nfound sources\n" ) if ( VERBOSE );
foreach my $source ( @sources )
{
if ( vec( $rout, fileno($source->{handle}),1) )
{
print( "Got input from source $source->{name} (".fileno($source->{handle}).")\n" ) if ( VERBOSE );
if ( $source->{type} eq "inet" || $source->{type} eq "unix" )
{
local *cfh;
my $paddr = accept( *cfh, $source->{handle} );
$connections{fileno(*cfh)} = { source=>$source, handle=>*cfh };
print( "Added new connection (".fileno(*cfh)."), ".int(keys(%connections))." connections\n" ) if ( VERBOSE );
}
else
{
my $buffer;
my $nbytes = sysread( $source->{handle}, $buffer, POSIX::BUFSIZ );
if ( !$nbytes )
{
die( "Got unexpected close on source $source->{name}" );
}
else
{
print( "Got '$buffer' ($nbytes bytes)\n" ) if ( VERBOSE );
handleMessage( $buffer );
}
}
}
}
foreach my $connection ( values(%connections) )
{
print( "Got input from connection on ".$connection->{source}->{name}." (".fileno($connection->{handle}).")\n" ) if ( VERBOSE );
if ( vec( $rout, fileno($connection->{handle}),1) )
{
my $buffer;
my $nbytes = sysread( $connection->{handle}, $buffer, POSIX::BUFSIZ );
if ( !$nbytes )
{
delete( $connections{fileno($connection->{handle})} );
print( "Removed connection (".fileno($connection->{handle})."), ".int(keys(%connections))." connections\n" ) if ( VERBOSE );
close( $connection->{handle} );
}
else
{
print( "Got '$buffer' ($nbytes bytes)\n" ) if ( VERBOSE );
handleMessage( $buffer );
}
}
}
}
elsif ( $nfound < 0 )
{
if ( $! == EINTR )
{
# Dead child, will be reaped
#print( "Probable dead child\n" );
}
else
{
die( "Can't select: $!" );
}
}
else
{
print( "Checking for timed actions at ".time()."\n" ) if ( VERBOSE && int(keys(%actions)) );
my $now = time();
foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) )
{
print( "Found actions expiring at $action_time\n" );
foreach my $action ( @{$actions{$action_time}} )
{
print( "Found action '$action'\n" );
handleMessage( $action );
}
delete( $actions{$action_time} );
}
}
}
print( "Trigger daemon exiting\n" );
sub handleMessage
{
my $buffer = shift;
#chomp( $buffer );
print( "Processing buffer '$buffer'\n" ) if ( VERBOSE );
foreach my $message ( split( /\r?\n/, $buffer ) )
{
next if ( !$message );
print( "Processing message '$message'\n" ) if ( VERBOSE );
my ( $id, $action, $score, $cause, $text, $showtext ) = split( /\|/, $message );
$score = 0 if ( !defined($score) );
$cause = 0 if ( !defined($cause) );
$text = 0 if ( !defined($text) );
my $res = $sth->execute( $id, $id ) or die( "Can't execute '$sql': ".$sth->errstr() );
my $monitor = $sth->fetchrow_hashref();
if ( !$monitor )
{
print( "Can't find monitor '$id' for message '$message'\n" );
next;
}
print( "Found monitor for id '$id'\n" ) if ( VERBOSE );
my $size = 512; # We only need the first 512 bytes really for the shared data and trigger section
$monitor->{ShmKey} = hex(ZM_SHM_KEY)|$monitor->{Id};
$monitor->{ShmId} = shmget( $monitor->{ShmKey}, $size, 0 );
if ( !defined($monitor->{ShmId}) )
{
printf( "Can't get shared memory id '%x': $!\n", $monitor->{ShmKey}, $! );
next;
}
my $shm_data_size;
if ( !shmread( $monitor->{ShmId}, $shm_data_size, 0, 4 ) )
{
print( "Can't read from shared memory: $!\n" );
exit( -1 );
}
$shm_data_size = unpack( "l", $shm_data_size );
my $trigger_data_offset = $shm_data_size+4; # Allow for 'size' member of trigger data
print( "Handling action '$action'\n" ) if ( VERBOSE );
if ( $action =~ /^(on|off)(?:\+(\d+))?$/ )
{
my $trigger = $1;
my $delay = $2;
my $trigger_data;
if ( defined($showtext) )
{
$trigger_data = pack( "llZ32Z256Z32", $trigger eq "on"?1:2, $trigger eq "on"?$score:0, $cause, $text, $showtext );
}
else
{
$trigger_data = pack( "llZ32Z256", $trigger eq "on"?1:2, $trigger eq "on"?$score:0, $cause, $text );
}
if ( !shmwrite( $monitor->{ShmId}, $trigger_data, $trigger_data_offset, length($trigger_data) ) )
{
print( "Can't write to shared memory: $!\n" );
}
print( "Triggered event $trigger '$cause'\n" );
if ( $delay )
{
my $action_time = time()+$delay;
my $action_text = $id."|cancel|0|".$cause."|".$text;
my $action_array = $actions{$action_time};
if ( !$action_array )
{
$action_array = $actions{$action_time} = [];
}
push( @$action_array, $action_text );
print( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ) if ( VERBOSE );
}
}
elsif( $action eq "cancel" )
{
my $trigger_data;
if ( defined($showtext) )
{
$trigger_data = pack( "llZ32Z256Z32", 0, 0, "", "", $showtext );
}
else
{
$trigger_data = pack( "llZ32Z256", 0, 0, "", "" );
}
if ( !shmwrite( $monitor->{ShmId}, $trigger_data, $trigger_data_offset, length($trigger_data) ) )
{
print( "Can't write to shared memory: $!\n" );
}
print( "Cancelled event '$cause'\n" );
}
elsif( $action eq "show" )
{
my $trigger_data = pack( "Z32", $showtext );
if ( !shmwrite( $monitor->{ShmId}, $trigger_data, $trigger_data_offset, length($trigger_data) ) )
{
print( "Can't write to shared memory: $!\n" );
}
print( "Updated show text to '$showtext'\n" );
}
else
{
print( "Unrecognised action '$action' in message '$message'\n" );
}
}
}

View File

@ -1,588 +0,0 @@
#!/usr/bin/perl -w
#
# ==========================================================================
#
# ZoneMinder Update Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 just checks what the most recent release of ZoneMinder is
# at the the moment. It will eventually be responsible for applying and
# configuring upgrades etc, including on the fly upgrades.
#
use strict;
use bytes;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_VERSION => "<from zmconfig>";
use constant ZM_PATH_BUILD => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
use constant ZM_PATH_WEB => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
if ( open( CONFIG, "<".ZM_CONFIG ) )
{
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\\s]+)\s*=\s*(\S+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
}
else
{
warn( "Can't open config file: $!" );
}
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
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() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use constant UPDATE_LOG_FILE => ZM_PATH_LOGS.'/zmupdate.log';
use constant CHECK_INTERVAL => (1*24*60*60); # Interval between version checks
use constant EVENT_PATH => ZM_PATH_WEB.'/'.ZM_DIR_EVENTS;
use constant VERBOSE => 0; # Whether to output more verbose debug
# ==========================================================================
#
# Don't change anything below here
#
# ==========================================================================
use POSIX;
use DBI;
use Getopt::Long;
use Data::Dumper;
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $check = 0;
my $rename = 0;
my $zone_fix = 0;
my $version = '';
my $db_user = ZM_DB_USER;
my $db_pass = ZM_DB_PASS;
sub Usage
{
print( "
Usage: zmupdate.pl <-c,--check|-r,--rename|-z,--zone-fix|-v<version>,--version=<version> [-u<dbuser> -p<dbpass>]>
Parameters are :-
-c, --check - Check for updated versions of ZoneMinder
-r, --rename - Rename images from old 'capture-nnn.jpg' format to new 'nnn-capture.jpg' style from v1.17.2
-z, --zone-fix - Update zone percentage sizes from %ge of image to %ge of zone from 1.18.2 onwards
-v<version>, --version=<version> - Upgrade to the current version from <version>
-u<dbuser>, --user=<dbuser> - Alternate DB user with privileges to alter DB
-p<dbpass>, --pass=<dbpass> - Password of alternate DB user with privileges to alter DB
");
exit( -1 );
}
if ( !GetOptions( 'check'=>\$check, 'rename'=>\$rename, 'zone-fix'=>\$zone_fix, 'version=s'=>\$version, 'user:s'=>\$db_user, 'pass:s'=>\$db_pass ) )
{
Usage();
}
if ( ! ($check || $rename || $zone_fix || $version) )
{
print( STDERR "Please give a valid option\n" );
Usage();
}
if ( ($check + $rename + $zone_fix + ($version?1:0)) > 1 )
{
print( STDERR "Please give only one option\n" );
Usage();
}
if ( $check )
{
open( LOG, '>>'.UPDATE_LOG_FILE ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
}
print( "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
if ( $check && ZM_CHECK_FOR_UPDATES )
{
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my $curr_version = ZM_DYN_CURR_VERSION;
my $last_version = ZM_DYN_LAST_VERSION;
my $last_check = ZM_DYN_LAST_CHECK;
if ( !$curr_version )
{
$curr_version = ZM_VERSION;
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_CURR_VERSION'";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $curr_version ) or die( "Can't execute: ".$sth->errstr() );
}
$dbh->disconnect();
while( 1 )
{
my $now = time();
if ( !$last_version || !$last_check || (($now-$last_check) > CHECK_INTERVAL) )
{
print( "Checking for updates at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
$ua->agent( "ZoneMinder Update Agent/".ZM_VERSION );
my $req = HTTP::Request->new( GET=>'http://www.zoneminder.com/version' );
my $res = $ua->request($req);
if ( $res->is_success )
{
$last_version = $res->content;
chomp($last_version);
$last_check = $now;
print( "Got version: '".$last_version."'\n" );
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my $lv_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_VERSION'";
my $lv_sth = $dbh->prepare_cached( $lv_sql ) or die( "Can't prepare '$lv_sql': ".$dbh->errstr() );
my $lv_res = $lv_sth->execute( $last_version ) or die( "Can't execute: ".$lv_sth->errstr() );
my $lc_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_CHECK'";
my $lc_sth = $dbh->prepare_cached( $lc_sql ) or die( "Can't prepare '$lc_sql': ".$dbh->errstr() );
my $lc_res = $lc_sth->execute( $last_check ) or die( "Can't execute: ".$lc_sth->errstr() );
$dbh->disconnect();
}
else
{
print( "Error check failed: '".$res->status_line()."'\n" );
}
}
sleep( 3600 );
}
}
if ( $rename )
{
require File::Find;
chdir( EVENT_PATH );
sub renameImage
{
my $file = $_;
# Ignore directories
if ( -d $file )
{
print( "Checking directory '$file'\n" );
return;
}
if ( $file !~ /(capture|analyse)-(\d+)(\.jpg)/ )
{
return;
}
my $new_file = "$2-$1$3";
print( "Renaming '$file' to '$new_file'\n" );
rename( $file, $new_file ) or warn( "Can't rename '$file' to '$new_file'" );
}
File::Find::find( \&renameImage, '.' );
}
if ( $zone_fix )
{
require DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my $sql = "select Z.*, M.Width as MonitorWidth, M.Height as MonitorHeight from Zones as Z inner join Monitors as M on Z.MonitorId = M.Id where Z.Units = 'Percent'";
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 @zones;
while( my $zone = $sth->fetchrow_hashref() )
{
push( @zones, $zone );
}
$sth->finish();
foreach my $zone ( @zones )
{
my $zone_width = (($zone->{HiX}*$zone->{MonitorWidth})-($zone->{LoX}*$zone->{MonitorWidth}))/100;
my $zone_height = (($zone->{HiY}*$zone->{MonitorHeight})-($zone->{LoY}*$zone->{MonitorHeight}))/100;
my $zone_area = $zone_width * $zone_height;
my $monitor_area = $zone->{MonitorWidth} * $zone->{MonitorHeight};
my $sql = "update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute(
($zone->{MinAlarmPixels}*$monitor_area)/$zone_area,
($zone->{MaxAlarmPixels}*$monitor_area)/$zone_area,
($zone->{MinFilterPixels}*$monitor_area)/$zone_area,
($zone->{MaxFilterPixels}*$monitor_area)/$zone_area,
($zone->{MinBlobPixels}*$monitor_area)/$zone_area,
($zone->{MaxBlobPixels}*$monitor_area)/$zone_area,
$zone->{Id}
) or die( "Can't execute: ".$sth->errstr() );
}
}
if ( $version )
{
my ( $detaint_version ) = $version =~ /^([\w.]+)$/;
$version = $detaint_version;
print( "\nInitiating database upgrade to version ".ZM_VERSION."\n" );
print( "Please ensure that ZoneMinder is stopped on your system prior to upgrading the database.\nPress enter to continue or ctrl-C to stop : " );
my $response = <STDIN>;
if ( 0 )
{
print( "\nDo you wish to take a backup of your database prior to upgrading?\nThis may result in a large file if you have a lot of events.\nPress 'y' for a backup or 'n' to continue : " );
$response = <STDIN>;
chomp( $response );
while ( $response !~ /^[yYnN]$/ )
{
print( "Please press 'y' for a backup or 'n' to continue only : " );
$response = <STDIN>;
chomp( $response );
}
if ( $response =~ /^[yY]$/ )
{
my $command = "mysqldump -h".ZM_DB_SERVER;
if ( $db_user )
{
$command .= " -u".$db_user;
if ( $db_pass )
{
$command .= " -p".$db_pass;
}
}
my $backup = ZM_DB_NAME."-".$version.".dump";
$command .= " --add-drop-table --databases ".ZM_DB_NAME." > ".$backup;
print( "Creating backup to $backup. This may take several minutes.\n" );
print( "Executing '$command'\n" ) if ( VERBOSE );
my $output = qx($command);
my $status = $? >> 8;
if ( $status || VERBOSE )
{
chomp( $output );
print( "Output: $output\n" );
}
if ( $status )
{
die( "Command '$command' exited with status: $status\n" );
}
else
{
print( "Database successfully backed up to $backup, proceeding to upgrade.\n" );
}
}
elsif ( $response !~ /^[nN]$/ )
{
die( "Unexpected response '$response'" );
}
}
sub patchDB
{
my $dbh = shift;
my $version = shift;
my $command = "mysql -h".ZM_DB_SERVER;
if ( $db_user )
{
$command .= " -u".$db_user;
if ( $db_pass )
{
$command .= " -p".$db_pass;
}
}
$command .= " ".ZM_DB_NAME." < ".ZM_PATH_BUILD."/db/zmalter-".$version.".sql";
print( "Executing '$command'\n" ) if ( VERBOSE );
my $output = qx($command);
my $status = $? >> 8;
if ( $status || VERBOSE )
{
chomp( $output );
print( "Output: $output\n" );
}
if ( $status )
{
die( "Command '$command' exited with status: $status\n" );
}
else
{
print( "\nDatabase successfully upgraded to version $version.\n" );
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() );
}
}
if ( ZM_DYN_DB_VERSION && ZM_DYN_DB_VERSION ne $version )
{
# Nothing yet
}
print( "\nUpgrading database to version ".ZM_VERSION."\n" );
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my $cascade = undef;
if ( $cascade || $version eq "1.19.0" )
{
# Patch the database
patchDB( $dbh, "1.19.0" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.19.1" )
{
# Patch the database
patchDB( $dbh, "1.19.1");
$cascade = !undef;
}
if ( $cascade || $version eq "1.19.2" )
{
# Patch the database
patchDB( $dbh, "1.19.2" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.19.3" )
{
# Patch the database
patchDB( $dbh, "1.19.3" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.19.4" )
{
require DBI;
# Rename the event directories and create a new symlink for the names
chdir( EVENT_PATH );
my $sql = "select * from Monitors order by Id";
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() );
while( my $monitor = $sth->fetchrow_hashref() )
{
if ( -d $monitor->{Name} )
{
rename( $monitor->{Name}, $monitor->{Id} ) or warn( "Can't rename existing monitor directory '$monitor->{Name}' to '$monitor->{Id}': $!" );
symlink( $monitor->{Id}, $monitor->{Name} ) or warn( "Can't symlink monitor directory '$monitor->{Id}' to '$monitor->{Name}': $!" );
}
}
$sth->finish();
# Patch the database
patchDB( $dbh, "1.19.4" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.19.5" )
{
print( "\nThis version now only uses one database user.\nPlease ensure you have run zmconfig.pl and re-entered your database username and password prior to upgrading, or the upgrade will fail.\nPress enter to continue or ctrl-C to stop : " );
# Patch the database
my $dummy = <STDIN>;
patchDB( $dbh, "1.19.5" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.20.0" )
{
# Patch the database
patchDB( $dbh, "1.20.0" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.20.1" )
{
# Patch the database
patchDB( $dbh, "1.20.1" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.21.0" )
{
# Patch the database
patchDB( $dbh, "1.21.0" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.21.1" )
{
# Patch the database
patchDB( $dbh, "1.21.1" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.21.2" )
{
# Patch the database
patchDB( $dbh, "1.21.2" );
$cascade = !undef;
}
if ( $cascade || $version eq "1.21.3" )
{
# Patch the database
patchDB( $dbh, "1.21.3" );
# Add appropriate widths and heights to events
{
print( "Updating events. This may take a few minutes. Please wait.\n" );
my $sql = "select * from Monitors order by Id";
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() );
while( my $monitor = $sth->fetchrow_hashref() )
{
my $sql = "update Events set Width = ?, Height = ? where MonitorId = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{Width}, $monitor->{Height}, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() );
}
$sth->finish();
}
# Add sequence numbers
{
print( "Updating monitor sequences. Please wait.\n" );
my $sql = "select * from Monitors order by Id";
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 $sequence = 1;
while( my $monitor = $sth->fetchrow_hashref() )
{
my $sql = "update Monitors set Sequence = ? where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $sequence++, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() );
}
$sth->finish();
}
# Update saved filters
{
print( "Updating saved filters. Please wait.\n" );
my $sql = "select * from Filters";
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 @filters;
while( my $filter = $sth->fetchrow_hashref() )
{
push( @filters, $filter );
}
$sth->finish();
$sql = "update Filters set Query = ? where Name = ?";
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
foreach my $filter ( @filters )
{
if ( $filter->{Query} =~ /op\d=&/ )
{
( my $new_query = $filter->{Query} ) =~ s/(op\d=)&/$1=&/g;
$res = $sth->execute( $new_query, $filter->{Name} ) or die( "Can't execute: ".$sth->errstr() );
}
}
}
$cascade = !undef;
}
if ( $cascade || $version eq "1.21.4" )
{
# Patch the database
patchDB( $dbh, "1.21.4" );
# Convert zones to new format
{
print( "Updating zones. Please wait.\n" );
# Get the existing zones from the DB
my $sql = "select Z.*,M.Width,M.Height from Zones as Z inner join Monitors as M on (Z.MonitorId = M.Id)";
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 @zones;
while( my $zone = $sth->fetchrow_hashref() )
{
push( @zones, $zone );
}
$sth->finish();
no strict 'refs';
foreach my $zone ( @zones )
{
# Create the coordinate strings
if ( $zone->{Units} eq "Pixels" )
{
my $sql = "update Zones set NumCoords = 4, Coords = concat( LoX,',',LoY,' ',HiX,',',LoY,' ',HiX,',',HiY,' ',LoX,',',HiY ), Area = round( ((HiX-LoX)+1)*((HiY-LoY)+1) ) where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() );
}
else
{
my $lo_x = ($zone->{LoX} * ($zone->{Width}-1) ) / 100;
my $hi_x = ($zone->{HiX} * ($zone->{Width}-1) ) / 100;
my $lo_y = ($zone->{LoY} * ($zone->{Height}-1) ) / 100;
my $hi_y = ($zone->{HiY} * ($zone->{Height}-1) ) / 100;
my $area = (($hi_x-$lo_x)+1)*(($hi_y-$lo_y)+1);
my $sql = "update Zones set NumCoords = 4, Coords = concat( round(?),',',round(?),' ',round(?),',',round(?),' ',round(?),',',round(?),' ',round(?),',',round(?) ), Area = round(?), MinAlarmPixels = round(?), MaxAlarmPixels = round(?), MinFilterPixels = round(?), MaxFilterPixels = round(?), MinBlobPixels = round(?), MaxBlobPixels = round(?) where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $lo_x, $lo_y, $hi_x, $lo_y, $hi_x, $hi_y, $lo_x, $hi_y, $area, ($zone->{MinAlarmPixels}*$area)/100, ($zone->{MaxAlarmPixels}*$area)/100, ($zone->{MinFilterPixels}*$area)/100, ($zone->{MaxFilterPixels}*$area)/100, ($zone->{MinBlobPixels}*$area)/100, ($zone->{MaxBlobPixels}*$area)/100, $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() );
}
}
}
$cascade = !undef;
}
if ( !$cascade )
{
die( "Can't find upgrade from version '$version'" );
}
$dbh->disconnect();
print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n" );
}
print( "Update agent exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
exit();

View File

@ -1,383 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder Video Creation Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 is used to create MPEG videos of events for the web pages
# or as email attachments.
#
use strict;
use bytes;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
use constant ZM_PATH_WEB => "<from zmconfig>";
use constant ZM_PATH_CGI => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\\s]+)\s*=\s*(\S+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
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() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use constant LOG_FILE => ZM_PATH_LOGS.'/zmvideo.log';
use constant VERBOSE => 0; # Whether to output more verbose debug
# ==========================================================================
#
# You shouldn't need to change anything from here downwards
#
# ==========================================================================
use DBI;
use Data::Dumper;
use Getopt::Long qw(:config no_ignore_case );
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $event_id;
my $format = 'mpg';
my $rate = '';
my $scale = '';
my $fps = '';
my $size = '';
my $overwrite = 0;
my @formats = split( '/\s+/', ZM_FFMPEG_FORMATS );
for ( my $i = 0; $i < @formats; $i++ )
{
if ( $i =~ /^(.+)\*$/ )
{
$format = $formats[$i] = $1;
}
}
sub Usage
{
print( "
Usage: zmvideo.pl -e <event_id>,--event=<event_id> [--format <format>] [--rate=<rate>] [--scale=<scale>] [--fps=<fps>] [--size=<size>] [--overwrite]
Parameters are :-
-e<event_id>, --event=<event_id> - What event to create the video for
-f<format>, --format=<format> - What format to create the video in, default is mpg. For ffmpeg only.
-r<rate>, --rate=<rate> - Relative rate , 1 = realtime, 2 = double speed , 0.5 = half speed etc
-s<scale>, --scale=<scale> - Scale, 1 = normal, 2 = double size, 0.5 = half size etc
-F<fps>, --fps=<fps> - Absolute frame rate, in frames per second
-S<size>, --size=<size> - Absolute video size, WxH or other specification supported by ffmpeg
-o, --overwrite - Whether to overwrite an existing file, off by default.
");
exit( -1 );
}
if ( !GetOptions( 'event=i'=>\$event_id, 'format|f=s'=>\$format, 'rate|r=f'=>\$rate, 'scale|s=f'=>\$scale, 'fps|F=f'=>\$fps, 'size|S=s'=>\$size, 'overwrite'=>\$overwrite ) )
{
Usage();
}
if ( !$event_id || $event_id < 0 )
{
print( STDERR "Please give a valid event id\n" );
Usage();
}
if ( ZM_OPT_MPEG eq "no" )
{
print( STDERR "Mpeg encoding is not currently enabled\n" );
exit(-1);
}
if ( ZM_OPT_MPEG eq "mpeg_encode" && $rate != 1.0 )
{
print( STDERR "Variable rate not supported with mpeg_encode\n" );
exit(-1);
}
if ( $format ne 'mpg' && ZM_OPT_MPEG eq "mpeg_encode" )
{
print( STDERR "Format not supported for mpeg_encode\n" );
Usage();
}
if ( !$rate && !$fps )
{
$rate = 1;
}
if ( !$scale && !$size )
{
$scale = 1;
}
if ( $rate && ($rate < 0.25 || $rate > 100) )
{
print( STDERR "Rate is out of range, 0.25 >= rate <= 100\n" );
Usage();
}
if ( $scale && ($scale < 0.25 || $scale > 4) )
{
print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" );
Usage();
}
if ( $fps && ($fps > 30) )
{
print( STDERR "FPS is out of range, <= 30\n" );
Usage();
}
my ( $detaint_format ) = $format =~ /^(\w+)$/;
my ( $detaint_rate ) = $rate =~ /^(-?\d+(?:\.\d+)?)$/;
my ( $detaint_scale ) = $scale =~ /^(-?\d+(?:\.\d+)?)$/;
my ( $detaint_fps ) = $fps =~ /^(-?\d+(?:\.\d+)?)$/;
my ( $detaint_size ) = $size =~ /^(\w+)$/;
$format = $detaint_format;
$rate = $detaint_rate;
$scale = $detaint_scale;
$fps = $detaint_fps;
$size = $detaint_size;
my $log_file = LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
#open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
#select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my @filters;
my $sql = "select max(F.Delta)-min(F.Delta) as FullLength, E.*, M.Name as MonitorName, M.Width as MonitorWidth, M.Height as MonitorHeight, M.Palette from Frames as F inner join Events as E on F.EventId = E.Id inner join Monitors as M on E.MonitorId = M.Id where EventId = '$event_id' group by F.EventId";
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 $event = $sth->fetchrow_hashref();
$sth->finish();
chdir( ZM_PATH_WEB.'/'.ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.$event->{Id} );
( my $video_name = $event->{Name} ) =~ s/\s/_/g;
my @file_parts;
if ( $rate )
{
my $file_rate = $rate;
$file_rate =~ s/\./_/;
$file_rate =~ s/_00//;
$file_rate =~ s/(_\d+)0+$/$1/;
$file_rate = 'r'.$file_rate;
push( @file_parts, $file_rate );
}
elsif ( $fps )
{
my $file_fps = $fps;
$file_fps =~ s/\./_/;
$file_fps =~ s/_00//;
$file_fps =~ s/(_\d+)0+$/$1/;
$file_fps = 'R'.$file_fps;
push( @file_parts, $file_fps );
}
if ( $scale )
{
my $file_scale = $scale;
$file_scale =~ s/\./_/;
$file_scale =~ s/_00//;
$file_scale =~ s/(_\d+)0+$/$1/;
$file_scale = 's'.$file_scale;
push( @file_parts, $file_scale );
}
elsif ( $size )
{
my $file_size = 'S'.$size;
push( @file_parts, $file_size );
}
my $video_file = "$video_name-".$file_parts[0]."-".$file_parts[1].".$format";
if ( $overwrite || !-s $video_file )
{
print( LOG "Creating video file $video_file for event $event->{Id}\n" );
if ( ZM_OPT_MPEG eq "mpeg_encode" )
{
my $param_file = "$video_name.mpe";
open( PARAMS, ">$param_file" ) or die( "Can't open '$param_file': $!" );
print( PARAMS "PATTERN IBBPBBPBBPBBPBB\n" );
print( PARAMS "FORCE_ENCODE_LAST_FRAME\n" );
print( PARAMS "OUTPUT $video_file\n" );
print( PARAMS "BASE_FILE_FORMAT JPEG\n" );
print( PARAMS "GOP_SIZE 30\n" );
print( PARAMS "SLICES_PER_FRAME 1\n" );
print( PARAMS "PIXEL HALF\n" );
print( PARAMS "RANGE 10\n" );
print( PARAMS "PSEARCH_ALG LOGARITHMIC\n" );
print( PARAMS "BSEARCH_ALG CROSS2\n" );
print( PARAMS "IQSCALE 8\n" );
print( PARAMS "PQSCALE 10\n" );
print( PARAMS "BQSCALE 25\n" );
print( PARAMS "REFERENCE_FRAME ORIGINAL\n" );
print( PARAMS "FRAME_RATE 24\n" );
my $scale_conversion = "";
if ( $scale != 1 )
{
if ( $scale > 1 )
{
$scale_conversion = ZM_PATH_NETPBM."/pnmscale $scale";
}
else
{
$scale_conversion = ZM_PATH_NETPBM."/pnmscale ".(1/$scale);
}
if ( $event->{Palette} == 1 && !ZM_COLOUR_JPEG_FILES )
{
print( PARAMS "INPUT_CONVERT ".ZM_PATH_NETPBM."/jpegtopnm * | ".$scale_conversion." | ".ZM_PATH_NETPBM."/pgmtoppm white | ".ZM_PATH_NETPBM."/ppmtojpeg\n" );
}
else
{
print( PARAMS "INPUT_CONVERT ".ZM_PATH_NETPBM."/jpegtopnm * | ".$scale_conversion." | ".ZM_PATH_NETPBM."/ppmtojpeg\n" );
}
}
else
{
if ( $event->{Palette} == 1 && !ZM_COLOUR_JPEG_FILES )
{
print( PARAMS "INPUT_CONVERT ".ZM_PATH_NETPBM."/jpegtopnm * | ".ZM_PATH_NETPBM."/pgmtoppm white | ".ZM_PATH_NETPBM."/ppmtojpeg\n" );
}
else
{
print( PARAMS "INPUT_CONVERT *\n" );
}
}
print( PARAMS "INPUT_DIR .\n" );
print( PARAMS "INPUT\n" );
for ( my $i = 1; $i <= $event->{Frames}; $i++ )
{
printf( PARAMS "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg\n", $i );
}
print( PARAMS "END_INPUT\n" );
close( PARAMS );
my $command = ZM_PATH_MPEG_ENCODE." $param_file >mpeg_encode.log";
print( LOG $command."\n" );
my $output = qx($command);
print( LOG $output."\n" );
}
elsif ( ZM_OPT_MPEG eq "ffmpeg" )
{
my $frame_rate = sprintf( "%.2f", $event->{Frames}/$event->{FullLength} );
if ( $rate )
{
if ( $rate != 1.0 )
{
$frame_rate *= $rate;
}
}
elsif ( $fps )
{
$frame_rate = $fps;
}
my $width = $event->{MonitorWidth};
my $height = $event->{MonitorHeight};
my $video_size = " ${width}x${height}";
if ( $scale )
{
if ( $scale != 1.0 )
{
$width = int($width*$scale);
$height = int($height*$scale);
$video_size = " ${width}x${height}";
}
}
elsif ( $size )
{
$video_size = $size;
}
my $command = ZM_PATH_FFMPEG." -y -r $frame_rate ".ZM_FFMPEG_INPUT_OPTIONS." -i %0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg -s $video_size ".ZM_FFMPEG_OUTPUT_OPTIONS." $video_file > ffmpeg.log";
print( LOG $command."\n" );
my $output = qx($command);
print( LOG $output."\n" );
}
else
{
die( "Bogus mpeg option ".ZM_OPT_MPEG."\n" );
}
my $status = $? >> 8;
if ( $status )
{
die( "Error: $status" );
}
print( LOG "Finished $video_file\n" );
}
else
{
print( LOG "Video file $video_file already exists for event $event->{Id}\n" );
}
#print( STDOUT $event->{MonitorId}.'/'.$event->{Id}.'/'.$video_file."\n" );
print( STDOUT $video_file."\n" );
exit( 0 );

View File

@ -1,180 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder WatchDog Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 does some basic setup for ZoneMinder to run and then periodically
# checks the fps output of the active daemons to check they haven't
# locked up. If they have then they are killed and restarted
#
use strict;
use bytes;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant ZM_CONFIG => "<from zmconfig>";
use constant ZM_PATH_BIN => "<from zmconfig>";
# Load the config from the database into the symbol table
BEGIN
{
no strict 'refs';
open( CONFIG, "<".ZM_CONFIG ) or die( "Can't open config file: $!" );
foreach my $str ( <CONFIG> )
{
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\\s]+)\s*=\s*(\S+)\s*$/;
$name =~ tr/a-z/A-Z/;
if (( $name eq 'ZM_DB_SERVER' ) ||
( $name eq 'ZM_DB_NAME' ) ||
( $name eq 'ZM_DB_USER' ) ||
( $name eq 'ZM_DB_PASS' ))
{
*{$name} = sub { $value };
}
}
close( CONFIG );
use DBI;
my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_SERVER, &ZM_DB_USER, &ZM_DB_PASS );
my $sql = "select * from Config";
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() );
while( my $config = $sth->fetchrow_hashref() )
{
*{$config->{Name}} = sub { $config->{Value} };
}
$sth->finish();
$dbh->disconnect();
}
use constant WATCH_LOG_FILE => ZM_PATH_LOGS.'/zmwatch.log';
use constant START_DELAY => 30; # To give everything else time to start
use constant VERBOSE => 0; # Whether to output more verbose debug
# ==========================================================================
#
# Don't change anything below here
#
# ==========================================================================
use POSIX;
use DBI;
use Data::Dumper;
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
sub Usage
{
print( "
Usage: zmwatch.pl
");
exit( -1 );
}
open( LOG, '>>'.WATCH_LOG_FILE ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( "Watchdog starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
print( "Watchdog pausing for ".START_DELAY." seconds\n" );
sleep( START_DELAY );
my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_SERVER, ZM_DB_USER, ZM_DB_PASS );
my $sql = "select * from Monitors";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
while( 1 )
{
my $now = time();
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
my $shm_size = 24; # We only need the first 24 bytes really for the last event time
while( my $monitor = $sth->fetchrow_hashref() )
{
if ( $monitor->{Function} ne 'None' )
{
# Check we have got an image recently
$monitor->{ShmKey} = hex(ZM_SHM_KEY)|$monitor->{Id};
$monitor->{ShmId} = shmget( $monitor->{ShmKey}, $shm_size, 0 );
if ( !defined($monitor->{ShmId}) )
{
print( "Can't get shared memory id '$monitor->{ShmKey}': $!\n" );
next;
}
my $image_time;
if ( !shmread( $monitor->{ShmId}, $image_time, 20, 4 ) )
{
print( "Can't read from shared memory '$monitor->{ShmKey}/$monitor->{ShmId}': $!\n" );
next;
}
$image_time = unpack( "l", $image_time );
#my $command = ZM_PATH_BIN."/zmu -m ".$monitor->{Id}." -t";
#print( "Getting last image time for monitor $monitor->{Id} ('$command')\n" ) if ( VERBOSE );
#my $image_time = qx( $command );
#chomp($image_time);
if ( !$image_time )
{
# We can't get the last capture time so can't be sure it's died.
next;
}
my $max_image_delay = (($monitor->{MaxFPS}>0)&&($monitor->{MaxFPS}<1))?(3/$monitor->{MaxFPS}):ZM_WATCH_MAX_DELAY;
my $image_delay = $now-$image_time;
print( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" ) if ( VERBOSE );
if ( $image_delay <= $max_image_delay )
{
# Yes, so continue
next;
}
my $command;
# If we are here then something bad has happened
if ( $monitor->{Type} eq 'Local' )
{
$command = ZM_PATH_BIN."/zmdc.pl restart zmc -d $monitor->{Device}";
}
else
{
$command = ZM_PATH_BIN."/zmdc.pl restart zmc -m $monitor->{Id}";
}
print( "Restarting capture daemon ('$command'), time since last capture $image_delay seconds ($now-$image_time)\n" );
print( qx( $command ) );
}
}
sleep( ZM_WATCH_CHECK_INTERVAL );
}
print( "Watchdog exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
exit();

View File

@ -1,685 +0,0 @@
#!/usr/bin/perl -wT
#
# ==========================================================================
#
# ZoneMinder X10 Control Script, $Date$, $Revision$
# Copyright (C) 2003, 2004, 2005 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 controls the monitoring of the X10 interface and the consequent
# management of the ZM daemons based on the receipt of X10 signals.
#
use strict;
use bytes;
use ZoneMinder;
# ==========================================================================
#
# These are the elements you need to edit to suit your installation
#
# ==========================================================================
use constant X10_SOCK_FILE => ZM_PATH_SOCKS.'/zmx10.sock';
use constant X10_LOG_FILE => ZM_PATH_LOGS.'/zmx10.log';
use constant VERBOSE => 0; # Whether to output more verbose debug
# ==========================================================================
#
# Don't change anything below here
#
# ==========================================================================
use POSIX;
use Socket;
use Getopt::Long;
use Data::Dumper;
$| = 1;
$ENV{PATH} = '/bin:/usr/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
sub Usage
{
print( "
Usage: zmx10.pl -c <command>,--command=<command> [-u <unit code>,--unit-code=<unit code>]
Parameters are :-
-c <command>, --command=<command> - Command to issue, one of 'on','off','dim','bright','status','shutdown'
-u <unit code>, --unit-code=<unit code> - Unit code to act on required for all commands except 'status' (optional) and 'shutdown'
");
exit( -1 );
}
my $command;
my $unit_code;
if ( !GetOptions( 'command=s'=>\$command, 'unit-code=i'=>\$unit_code ) )
{
Usage();
}
die( "No command given" ) unless( $command );
die( "No unit code given" ) unless( $unit_code || ($command =~ /(?:start|status|shutdown)/) );
if ( $command eq "start" )
{
X10Server::runServer();
exit();
}
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" );
my $saddr = sockaddr_un( X10_SOCK_FILE );
if ( !connect( CLIENT, $saddr ) )
{
# The server isn't there
print( "Unable to connect, starting server\n" );
close( CLIENT );
if ( my $cpid = fork() )
{
# Parent process just sleep and fall through
sleep( 2 );
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" );
connect( CLIENT, $saddr ) or die( "Can't connect: $!" );
}
elsif ( defined($cpid) )
{
setpgrp();
X10Server::runServer();
}
else
{
die( "Can't fork: $!" );
}
}
# The server is there, connect to it
#print( "Writing commands\n" );
CLIENT->autoflush();
my $message = "$command";
$message .= ";$unit_code" if ( $unit_code );
print( CLIENT $message );
shutdown( CLIENT, 1 );
while ( my $line = <CLIENT> )
{
chomp( $line );
print( "$line\n" );
}
close( CLIENT );
#print( "Finished writing, bye\n" );
exit;
#
# ==========================================================================
#
# This is the X10 Server package
#
# ==========================================================================
#
package X10Server;
use strict;
use bytes;
use POSIX;
use DBI;
use Socket;
use X10::ActiveHome;
use Data::Dumper;
our $dbh;
our $x10;
our %monitor_hash;
our %device_hash;
our %pending_tasks;
sub runServer
{
my $log_file = main::X10_LOG_FILE;
open( LOG, ">>$log_file" ) or die( "Can't open log file: $!" );
open( STDOUT, ">&LOG" ) || die( "Can't dup stdout: $!" );
select( STDOUT ); $| = 1;
open( STDERR, ">&LOG" ) || die( "Can't dup stderr: $!" );
select( STDERR ); $| = 1;
select( LOG ); $| = 1;
print( "X10 server starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" );
unlink( main::X10_SOCK_FILE );
my $saddr = sockaddr_un( main::X10_SOCK_FILE );
bind( SERVER, $saddr ) or die( "Can't bind: $!" );
listen( SERVER, SOMAXCONN ) or die( "Can't listen: $!" );
$dbh = DBI->connect( "DBI:mysql:database=".main::ZM_DB_NAME.";host=".main::ZM_DB_SERVER, main::ZM_DB_USER, main::ZM_DB_PASS );
$x10 = new X10::ActiveHome( port=>main::ZM_X10_DEVICE, house_code=>main::ZM_X10_HOUSE_CODE, debug=>1 );
loadTasks();
$x10->register_listener( \&x10listen );
my $rin = '';
vec( $rin, fileno(SERVER),1) = 1;
vec( $rin, $x10->select_fds(),1) = 1;
my $timeout = 0.2;
#print( "F:".fileno(SERVER)."\n" );
my $reload = undef;
my $reload_count = 0;
my $reload_limit = (main::ZM_X10_DB_RELOAD_INTERVAL)/$timeout;
while( 1 )
{
my $nfound = select( my $rout = $rin, undef, undef, $timeout );
#print( "Off select, NF:$nfound, ER:$!\n" );
#print( vec( $rout, fileno(SERVER),1)."\n" );
#print( vec( $rout, $x10->select_fds(),1)."\n" );
if ( $nfound > 0 )
{
if ( vec( $rout, fileno(SERVER),1) )
{
my $paddr = accept( CLIENT, SERVER );
my $message = <CLIENT>;
my ( $command, $unit_code ) = split( ';', $message );
my $device;
if ( defined($unit_code) )
{
if ( $unit_code < 1 || $unit_code > 16 )
{
dprint( "Error, invalid unit code '$unit_code'\n" );
next;
}
$device = $device_hash{$unit_code};
if ( !$device )
{
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
}
}
my $result;
if ( $command eq 'on' )
{
$result = $device->{appliance}->on();
}
elsif ( $command eq 'off' )
{
$result = $device->{appliance}->off();
}
#elsif ( $command eq 'dim' )
#{
#$result = $device->{appliance}->dim();
#}
#elsif ( $command eq 'bright' )
#{
#$result = $device->{appliance}->bright();
#}
elsif ( $command eq 'status' )
{
if ( $device )
{
dprint( $unit_code." ".$device->{status}."\n" );
}
else
{
foreach my $unit_code ( sort( keys(%device_hash) ) )
{
my $device = $device_hash{$unit_code};
dprint( $unit_code." ".$device->{status}."\n" );
}
}
}
elsif ( $command eq 'shutdown' )
{
last;
}
else
{
dprint( "Error, invalid command '$command'\n" );
}
if ( defined($result) )
{
if ( 1 || $result )
{
$device->{status} = uc($command);
dprint( $device->{appliance}->address()." $command, ok\n" );
#x10listen( new X10::Event( sprintf("%s %s", $device->{appliance}->address, uc($command) ) ) );
}
else
{
dprint( $device->{appliance}->address()." $command, failed\n" );
}
}
close( CLIENT );
}
elsif ( vec( $rout, $x10->select_fds(),1) )
{
$x10->handle_input();
}
else
{
die( "Bogus descriptor" );
}
}
elsif ( $nfound < 0 )
{
die( "Can't select: $!" );
}
else
{
#print( "Select timed out\n" );
# Check for state changes
foreach my $monitor_id ( sort(keys(%monitor_hash) ) )
{
my $monitor = $monitor_hash{$monitor_id};
my $state;
if ( !shmread( $monitor->{ShmId}, $state, 8, 4 ) )
{
print( "Can't read from shared memory: $!\n" );
$reload = !undef;
next;
}
$state = unpack( "l", $state );
if ( defined( $monitor->{LastState} ) )
{
my $task_list;
if ( $state == 2 && $monitor->{LastState} == 0 ) # Gone into alarm state
{
print( "Applying ON_list for $monitor_id\n" ) if ( main::VERBOSE );
$task_list = $monitor->{"ON_list"};
}
elsif ( $state == 0 && $monitor->{LastState} > 0 ) # Come out of alarm state
{
print( "Applying OFF_list for $monitor_id\n" ) if ( main::VERBOSE );
$task_list = $monitor->{"OFF_list"};
}
if ( $task_list )
{
foreach my $task ( @$task_list )
{
processTask( $task );
}
}
}
$monitor->{LastState} = $state;
}
# Check for pending tasks
my $now = time();
foreach my $activation_time ( sort(keys(%pending_tasks) ) )
{
last if ( $activation_time > $now );
my $pending_list = $pending_tasks{$activation_time};
foreach my $task ( @$pending_list )
{
processTask( $task );
}
delete( $pending_tasks{$activation_time} );
}
if ( $reload || ++$reload_count >= $reload_limit )
{
loadTasks();
$reload = undef;
$reload_count = 0;
}
}
}
print( "X10 server exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
close( LOG );
close( SERVER );
exit();
}
sub addToDeviceList
{
my $unit_code = shift;
my $event = shift;
my $monitor = shift;
my $function = shift;
my $limit = shift;
print( "Adding to device list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" ) if ( main::VERBOSE );
my $device = $device_hash{$unit_code};
if ( !$device )
{
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
}
my $task = { type=>"device", monitor=>$monitor, function=>$function };
if ( $limit )
{
$task->{limit} = $limit
}
my $task_list = $device->{$event."_list"};
if ( !$task_list )
{
$task_list = $device->{$event."_list"} = [];
}
push( @$task_list, $task );
}
sub addToMonitorList
{
my $monitor = shift;
my $event = shift;
my $unit_code = shift;
my $function = shift;
my $limit = shift;
print( "Adding to monitor list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" ) if ( main::VERBOSE );
my $device = $device_hash{$unit_code};
if ( !$device )
{
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
}
my $task = { type=>"monitor", device=>$device, function=>$function };
if ( $limit )
{
$task->{limit} = $limit;
}
my $task_list = $monitor->{$event."_list"};
if ( !$task_list )
{
$task_list = $monitor->{$event."_list"} = [];
}
push( @$task_list, $task );
}
sub loadTasks
{
%monitor_hash = ();
print( "Loading tasks\n" ) if ( main::VERBOSE );
# Clear out all old device task lists
foreach my $unit_code ( sort( keys(%device_hash) ) )
{
my $device = $device_hash{$unit_code};
$device->{ON_list} = [];
$device->{OFF_list} = [];
}
my $sql = "select M.*,T.* from Monitors as M inner join TriggersX10 as T on (M.Id = T.MonitorId) where find_in_set( M.Function, 'Modect,Record,Mocord' ) and M.RunMode = 'Triggered' and find_in_set( 'X10', M.Triggers )";
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() );
while( my $monitor = $sth->fetchrow_hashref() )
{
my $size = 512; # We only need the first 512 bytes really for the alarm state and forced alarm
$monitor->{ShmKey} = hex(main::ZM_SHM_KEY)|$monitor->{Id};
$monitor->{ShmId} = shmget( $monitor->{ShmKey}, $size, 0 );
if ( !defined($monitor->{ShmId}) )
{
print( "Can't get shared memory id '$monitor->{ShmKey}': $!\n" );
next;
}
$monitor_hash{$monitor->{Id}} = $monitor;
if ( $monitor->{Activation} )
{
print( "$monitor->{Name} has active string '$monitor->{Activation}'\n" ) if ( main::VERBOSE );
foreach my $code_string ( split( ',', $monitor->{Activation} ) )
{
#print( "Code string: $code_string\n" );
my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
$limit = 0 if ( !$limit );
if ( $unit_code )
{
if ( !$modifier || $modifier eq '+' )
{
addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_active":"stop_active", $limit );
}
if ( !$modifier || $modifier eq '-' )
{
addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_active":"start_active", $limit );
}
}
}
}
if ( $monitor->{AlarmInput} )
{
print( "$monitor->{Name} has alarm input string '$monitor->{AlarmInput}'\n" ) if ( main::VERBOSE );
foreach my $code_string ( split( ',', $monitor->{AlarmInput} ) )
{
#print( "Code string: $code_string\n" );
my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
$limit = 0 if ( !$limit );
if ( $unit_code )
{
if ( !$modifier || $modifier eq '+' )
{
addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_alarm":"stop_alarm", $limit );
}
if ( !$modifier || $modifier eq '-' )
{
addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_alarm":"start_alarm", $limit );
}
}
}
}
if ( $monitor->{AlarmOutput} )
{
print( "$monitor->{Name} has alarm output string '$monitor->{AlarmOutput}'\n" ) if ( main::VERBOSE );
foreach my $code_string ( split( ',', $monitor->{AlarmOutput} ) )
{
#print( "Code string: $code_string\n" );
my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
$limit = 0 if ( !$limit );
if ( $unit_code )
{
if ( !$modifier || $modifier eq '+' )
{
addToMonitorList( $monitor, "ON", $unit_code, !$invert?"on":"off", $limit );
}
if ( !$modifier || $modifier eq '-' )
{
addToMonitorList( $monitor, "OFF", $unit_code, !$invert?"off":"on", $limit );
}
}
}
}
}
}
sub addPendingTask
{
my $task = shift;
# Check whether we are just extending a previous pending task
# and remove it if it's there
foreach my $activation_time ( sort(keys(%pending_tasks) ) )
{
my $pending_list = $pending_tasks{$activation_time};
my $new_pending_list = [];
foreach my $pending_task ( @$pending_list )
{
if ( $task->{type} ne $pending_task->{type} )
{
push( @$new_pending_list, $pending_task )
}
elsif ( $task->{type} eq "device" )
{
if (( $task->{monitor}->{Id} != $pending_task->{monitor}->{Id} )
|| ( $task->{function} ne $pending_task->{function} ))
{
push( @$new_pending_list, $pending_task )
}
}
elsif ( $task->{type} eq "monitor" )
{
if (( $task->{device}->{appliance}->unit_code() != $pending_task->{device}->{appliance}->unit_code() )
|| ( $task->{function} ne $pending_task->{function} ))
{
push( @$new_pending_list, $pending_task )
}
}
}
if ( @$new_pending_list )
{
$pending_tasks{$activation_time} = $new_pending_list;
}
else
{
delete( $pending_tasks{$activation_time} );
}
}
my $end_time = time() + $task->{limit};
my $pending_list = $pending_tasks{$end_time};
if ( !$pending_list )
{
$pending_list = $pending_tasks{$end_time} = [];
}
my $pending_task;
if ( $task->{type} eq "device" )
{
$pending_task = { type=>$task->{type}, monitor=>$task->{monitor}, function=>$task->{function} };
$pending_task->{function} =~ s/start/stop/;
}
elsif ( $task->{type} eq "monitor" )
{
$pending_task = { type=>$task->{type}, device=>$task->{device}, function=>$task->{function} };
$pending_task->{function} =~ s/on/off/;
}
push( @$pending_list, $pending_task );
}
sub processTask
{
my $task = shift;
if ( $task->{type} eq "device" )
{
my ( $instruction, $class ) = ( $task->{function} =~ /^(.+)_(.+)$/ );
my @commands;
if ( $class eq "active" )
{
if ( $instruction eq "start" )
{
push( @commands, main::ZM_PATH_BIN."/zmdc.pl start zma -m ".$task->{monitor}->{Id} );
push( @commands, main::ZM_PATH_BIN."/zmdc.pl start zmf -m ".$task->{monitor}->{Id} );
if ( main::ZM_OPT_FRAME_SERVER )
{
}
if ( $task->{limit} )
{
addPendingTask( $task );
}
}
elsif( $instruction eq "stop" )
{
$command = main::ZM_PATH_BIN."/zmdc.pl stop zma -m ".$task->{monitor}->{Id};
push( @commands, main::ZM_PATH_BIN."/zmdc.pl stop zma -m ".$task->{monitor}->{Id} );
push( @commands, main::ZM_PATH_BIN."/zmdc.pl stop zmf -m ".$task->{monitor}->{Id} );
}
}
elsif( $class eq "alarm" )
{
if ( $instruction eq "start" )
{
#$command = main::ZM_PATH_BIN."/zmu --monitor ".$task->{monitor}->{Id}." --alarm";
my $force_data = pack( "llZ*", 1, 0, "X10" );
if ( !shmwrite( $task->{monitor}->{ShmId}, $force_data, 52, 12 ) )
{
print( "Can't write to shared memory: $!\n" );
}
if ( $task->{limit} )
{
addPendingTask( $task );
}
}
elsif( $instruction eq "stop" )
{
#$command = main::ZM_PATH_BIN."/zmu --monitor ".$task->{monitor}->{Id}." --cancel";
my $force_data = pack( "llZ*", 0, 0, "" );
if ( !shmwrite( $task->{monitor}->{ShmId}, $force_data, 52, 12 ) )
{
print( "Can't write to shared memory: $!\n" );
}
}
}
foreach my $command ( @commands )
{
print( "Executing command '$command'\n" );
qx( $command );
}
}
elsif( $task->{type} eq "monitor" )
{
if ( $task->{function} eq "on" )
{
$task->{device}->{appliance}->on();
if ( $task->{limit} )
{
addPendingTask( $task );
}
}
elsif ( $task->{function} eq "off" )
{
$task->{device}->{appliance}->off();
}
}
}
sub dprint
{
if ( fileno(CLIENT) )
{
print CLIENT @_
}
print @_;
}
sub x10listen
{
foreach my $event ( @_ )
{
#print( Data::Dumper( $_ )."\n" );
if ( $event->house_code() eq main::ZM_X10_HOUSE_CODE )
{
my $unit_code = $event->unit_code();
my $device = $device_hash{$unit_code};
if ( !$device )
{
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
}
next if ( $event->func() !~ /(?:ON|OFF)/ );
$device->{status} = $event->func();
my $task_list = $device->{$event->func()."_list"};
if ( $task_list )
{
foreach my $task ( @$task_list )
{
processTask( $task );
}
}
}
print( strftime( "%y/%m/%d %H:%M:%S", localtime() )." - ".$event->as_string()."\n" );
}
}
1;

View File

@ -1,107 +0,0 @@
//
// ZoneMinder Configuration, $Date$, $Revision$
// Copyright (C) 2003, 2004, 2005 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.
//
#include "config.h"
#include "zm_config_defines.h"
#define ZM_VERSION "<from zmconfig>" // ZoneMinder verson number
#define ZM_CONFIG "<from zmconfig>" // Path to config file
#define ZM_PATH_BIN "<from zmconfig>"; // Path to binaries
#define ZM_PATH_WEB "<from zmconfig>"; // Path to web files
#define ZM_PATH_CGI "<from zmconfig>"; // Path to cgi files
#define ZM_MAX_IMAGE_WIDTH 2048 // The largest image we imagine ever handling
#define ZM_MAX_IMAGE_HEIGHT 1536 // The largest image we imagine ever handling
#define ZM_MAX_IMAGE_COLOURS 3 // The largest image we imagine ever handling
#define ZM_MAX_IMAGE_DIM (ZM_MAX_IMAGE_WIDTH*ZM_MAX_IMAGE_HEIGHT)
#define ZM_MAX_IMAGE_SIZE (ZM_MAX_IMAGE_DIM*ZM_MAX_IMAGE_COLOURS)
#define ZM_SCALE_SCALE 100 // The factor by which we bump up 'scale' to simulate FP
#define ZM_RATE_SCALE 100 // The factor by which we bump up 'rate' to simulate FP
#define ZM_MAX_FPS 30 // The maximum frame rate we expect to handle
#define ZM_SAMPLE_RATE int(1000000/ZM_MAX_FPS) // A general nyquist sample frequency for delays etc
extern char *ZM_DB_SERVER, *ZM_DB_NAME, *ZM_DB_USER, *ZM_DB_PASS;
extern void zmLoadConfig();
class ConfigItem
{
private:
char *name;
char *value;
char *type;
mutable enum { CFG_BOOLEAN, CFG_INTEGER, CFG_DECIMAL, CFG_STRING } cfg_type;
mutable union
{
bool boolean_value;
int integer_value;
double decimal_value;
char *string_value;
} cfg_value;
mutable bool accessed;
public:
ConfigItem( const char *p_name, const char *p_value, const char *const p_type );
~ConfigItem();
void ConvertValue() const;
bool BooleanValue() const;
int IntegerValue() const;
double DecimalValue() const;
const char *StringValue() const;
inline operator bool() const
{
return( BooleanValue() );
}
inline operator int() const
{
return( IntegerValue() );
}
inline operator double() const
{
return( DecimalValue() );
}
inline operator const char *() const
{
return( StringValue() );
}
};
class Config
{
public:
ZM_CFG_DECLARE_LIST
private:
int n_items;
ConfigItem **items;
public:
Config();
~Config();
void Load();
void Assign();
const ConfigItem &Item( int id );
};
extern Config config;

View File

@ -1,197 +0,0 @@
<?php
//
// ZoneMinder web configuration file, $Date$, $Revision$
// Copyright (C) 2003, 2004, 2005 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 section contains options substituted by the zmconfig.pl utility, do not edit these directly
//
define( "ZM_VERSION", "<from zmconfig>" ); // Version Number
define( "ZM_CONFIG", "<from zmconfig>" ); // Path to config file
define( "ZM_PATH_BIN", "<from zmconfig>" ); // Path to binaries
define( "ZM_PATH_WEB", "<from zmconfig>" ); // Path to web files
define( "ZM_PATH_CGI", "<from zmconfig>" ); // Path to cgi files
$cfg = fopen( ZM_CONFIG, "r") or die("Could not open config file.");
while ( !feof($cfg) )
{
$str = fgets( $cfg, 256 );
if ( preg_match( '/^\s*$/', $str )) { continue; }
elseif ( preg_match( '/^\s*#/', $str )) { continue; }
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*([^=\s]+)\s*$/', $str, $matches ))
{
if (( $matches[1] == "ZM_DB_SERVER") ||
( $matches[1] == "ZM_DB_NAME") ||
( $matches[1] == "ZM_DB_USER") ||
( $matches[1] == "ZM_DB_PASS"))
{
define( $matches[1], $matches[2] );
}
}
}
fclose( $cfg );
// This section is options normally derived from other options or configuration
//
define( "ZMU_PATH", ZM_PATH_BIN."/zmu" ); // Local path to the ZoneMinder Utility
// Alarm states
//
define( "STATE_IDLE", 0 );
define( "STATE_PREALARM", 1 );
define( "STATE_ALARM", 2 );
define( "STATE_ALERT", 3 );
define( "STATE_TAPE", 4 );
// These are miscellaneous options you won't normally need to change
//
define( "MAX_EVENTS", 10 ); // The maximum number of events to show in the monitor event listing
define( "RATE_SCALE", 100 ); // The additional scaling factor used to help get fractional rates in integer format
define( "SCALE_SCALE", 100 ); // The additional scaling factor used to help get fractional scales in integer format
define( "LEARN_MODE", false ); // Currently unimplemented, do not change
define( 'DEVICE_WIDTH', 150 ); // Default device width for phones and handhelds
define( 'DEVICE_HEIGHT', 150 ); // Default device height for phones and handhelds
define( 'DEVICE_LINES', 10 ); // Default device lines for phones and handhelds
require_once( 'zm_db.php' );
loadConfig();
switch ( $bandwidth )
{
case "high" :
{
define( "ZM_WEB_REFRESH_MAIN", ZM_WEB_H_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
define( "ZM_WEB_REFRESH_CYCLE", ZM_WEB_H_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
define( "ZM_WEB_REFRESH_IMAGE", ZM_WEB_H_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
define( "ZM_WEB_REFRESH_STATUS", ZM_WEB_H_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
define( "ZM_WEB_REFRESH_EVENTS", ZM_WEB_H_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
define( "ZM_WEB_DEFAULT_SCALE", ZM_WEB_H_DEFAULT_SCALE ); // What the default scaling factor applied to 'live' or 'event' views is (%)
define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_H_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%)
define( "ZM_WEB_VIDEO_BITRATE", ZM_WEB_H_VIDEO_BITRATE ); // What the bitrate of any streamed video should be
define( "ZM_WEB_VIDEO_MAXFPS", ZM_WEB_H_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be
define( "ZM_WEB_IMAGE_SCALING", ZM_WEB_H_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
define( "ZM_WEB_USE_STREAMS", ZM_WEB_H_USE_STREAMS ); // Whether to use streaming or stills for live and events views
define( "ZM_WEB_EVENTS_VIEW", ZM_WEB_H_EVENTS_VIEW ); // What the default view of multiple events should be.
break;
}
case "medium" :
{
define( "ZM_WEB_REFRESH_MAIN", ZM_WEB_M_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
define( "ZM_WEB_REFRESH_CYCLE", ZM_WEB_M_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
define( "ZM_WEB_REFRESH_IMAGE", ZM_WEB_M_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
define( "ZM_WEB_REFRESH_STATUS", ZM_WEB_M_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
define( "ZM_WEB_REFRESH_EVENTS", ZM_WEB_M_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
define( "ZM_WEB_DEFAULT_SCALE", ZM_WEB_M_DEFAULT_SCALE ); // What the default scaling factor applied to 'live' or 'event' views is (%)
define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_M_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%)
define( "ZM_WEB_VIDEO_BITRATE", ZM_WEB_M_VIDEO_BITRATE ); // What the bitrate of any streamed video should be
define( "ZM_WEB_VIDEO_MAXFPS", ZM_WEB_M_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be
define( "ZM_WEB_IMAGE_SCALING", ZM_WEB_M_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
define( "ZM_WEB_USE_STREAMS", ZM_WEB_M_USE_STREAMS ); // Whether to use streaming or stills for live and events views
define( "ZM_WEB_EVENTS_VIEW", ZM_WEB_M_EVENTS_VIEW ); // What the default view of multiple events should be.
break;
}
case "low" :
{
define( "ZM_WEB_REFRESH_MAIN", ZM_WEB_L_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
define( "ZM_WEB_REFRESH_CYCLE", ZM_WEB_L_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
define( "ZM_WEB_REFRESH_IMAGE", ZM_WEB_L_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
define( "ZM_WEB_REFRESH_STATUS", ZM_WEB_L_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
define( "ZM_WEB_REFRESH_EVENTS", ZM_WEB_L_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events
define( "ZM_WEB_DEFAULT_SCALE", ZM_WEB_L_DEFAULT_SCALE ); // What the default scaling factor applied to 'live' or 'event' views is (%)
define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_L_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%)
define( "ZM_WEB_VIDEO_BITRATE", ZM_WEB_L_VIDEO_BITRATE ); // What the bitrate of any streamed video should be
define( "ZM_WEB_VIDEO_MAXFPS", ZM_WEB_L_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be
define( "ZM_WEB_IMAGE_SCALING", ZM_WEB_L_IMAGE_SCALING ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling
define( "ZM_WEB_USE_STREAMS", ZM_WEB_L_USE_STREAMS ); // Whether to use streaming or stills for live and events views
define( "ZM_WEB_EVENTS_VIEW", ZM_WEB_L_EVENTS_VIEW ); // What the default view of multiple events should be.
break;
}
case "mobile" : // Very incomplete at present
{
define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_P_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%)
break;
}
}
function loadConfig()
{
global $config;
global $config_cats;
$config = array();
$config_cat = array();
$sql = "select * from Config order by Id asc";
$result = mysql_query( $sql );
if ( !$result )
echo mysql_error();
$monitors = array();
while( $row = mysql_fetch_assoc( $result ) )
{
define( $row['Name'], $row['Value'] );
$config[$row['Name']] = $row;
if ( !($config_cat = &$config_cats[$row['Category']]) )
{
$config_cats[$row['Category']] = array();
$config_cat = &$config_cats[$row['Category']];
}
$config_cat[$row['Name']] = $row;
}
//print_r( $config );
//print_r( $config_cats );
}
// Javascript window sizes
$jws = array(
'bandwidth' => array( 'w'=>200, 'h'=>90 ),
'console' => array( 'w'=>750, 'h'=>312 ),
'control' => array( 'w'=>380, 'h'=>480 ),
'controlcaps' => array( 'w'=>700, 'h'=>320 ),
'controlcap' => array( 'w'=>360, 'h'=>440 ),
'cycle' => array( 'w'=>16, 'h'=>32 ),
'device' => array( 'w'=>196, 'h'=>164 ),
'donate' => array( 'w'=>500, 'h'=>280 ),
'event' => array( 'w'=>96, 'h'=>168 ),
'eventdetail' => array( 'w'=>400, 'h'=>220 ),
'events' => array( 'w'=>720, 'h'=>480 ),
'export' => array( 'w'=>400, 'h'=>340 ),
'filter' => array( 'w'=>620, 'h'=>250 ),
'filtersave' => array( 'w'=>560, 'h'=>220 ),
'frames' => array( 'w'=>500, 'h'=>300 ),
'function' => array( 'w'=>248, 'h'=>92 ),
'groups' => array( 'w'=>400, 'h'=>220 ),
'image' => array( 'w'=>48, 'h'=>80 ),
'login' => array( 'w'=>720, 'h'=>480 ),
'logout' => array( 'w'=>200, 'h'=>100 ),
'monitor' => array( 'w'=>360, 'h'=>324 ),
'montage' => array( 'w'=>10, 'h'=>20 ),
'optionhelp' => array( 'w'=>320, 'h'=>284 ),
'options' => array( 'w'=>780, 'h'=>540 ),
'preset' => array( 'w'=>240, 'h'=>90 ),
'restarting' => array( 'w'=>250, 'h'=>150 ),
'settings' => array( 'w'=>200, 'h'=>225 ),
'state' => array( 'w'=>300, 'h'=>120 ),
'stats' => array( 'w'=>680, 'h'=>200 ),
'timeline' => array( 'w'=>760, 'h'=>500 ),
'user' => array( 'w'=>280, 'h'=>372 ),
'version' => array( 'w'=>320, 'h'=>140 ),
'video' => array( 'w'=>100, 'h'=>80 ),
'watch' => array( 'w'=>96, 'h'=>384 ),
'zone' => array( 'w'=>400, 'h'=>450 ),
'zones' => array( 'w'=>72, 'h'=>232 ),
);
?>

View File

@ -1,5 +0,0 @@
# ZoneMinder config
ZM_DB_SERVER=<from zmconfig>
ZM_DB_NAME=<from zmconfig>
ZM_DB_USER=<from zmconfig>
ZM_DB_PASS=<from zmconfig>