Merge pull request #815 from onlyjob/PBP
last batch of POD and readability conversions for *.pl scripts
This commit is contained in:
commit
e69fee1c94
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
#
|
||||||
# ZoneMinder Update Script, $Date$, $Revision$
|
# ZoneMinder systemctl wrapper, $Date$, $Revision$
|
||||||
# Copyright (C) 2001-2008 Philip Coombes
|
# Copyright (C) 2001-2008 Philip Coombes
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
|
@ -20,25 +20,39 @@
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
|
||||||
# This is a wrapper script that allows zoneminder to start and stop itself
|
=head1 NAME
|
||||||
# in a manner that keeps it in-sync with systemd. This script is intended
|
|
||||||
# to be called internally by zoneminder and may not give the desired results
|
zmsystemctl.pl - ZoneMinder systemctl wrapper
|
||||||
# if run from the command line.
|
|
||||||
#
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
zmsystemctl.pl {start|stop|restart|version}
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This is a wrapper script that allows zoneminder to start and stop itself
|
||||||
|
in a manner that keeps it in-sync with systemd. This script is intended
|
||||||
|
to be called internally by zoneminder and may not give the desired results
|
||||||
|
if run from the command line.
|
||||||
|
|
||||||
|
=cut
|
||||||
use warnings;
|
use warnings;
|
||||||
use strict;
|
use strict;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
use autouse 'Pod::Usage'=>qw(pod2usage);
|
||||||
|
|
||||||
@EXTRA_PERL_LIB@
|
@EXTRA_PERL_LIB@
|
||||||
use ZoneMinder::Logger qw(:all);
|
use ZoneMinder::Logger qw(:all);
|
||||||
|
|
||||||
my $command = $ARGV[0];
|
my $command = $ARGV[0];
|
||||||
|
|
||||||
if ( (scalar(@ARGV) == 1) && ($command =~ /^(start|stop|restart|version)$/ )) {
|
if ( (scalar(@ARGV) == 1)
|
||||||
|
&& ($command =~ /^(start|stop|restart|version)$/ )
|
||||||
|
){
|
||||||
$command = $1;
|
$command = $1;
|
||||||
} else {
|
} else {
|
||||||
die(" USAGE: zmsystemctl.pl <start|stop|restart|version>\n");
|
pod2usage(-exitstatus => -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
my $path = qx(which systemctl);
|
my $path = qx(which systemctl);
|
||||||
|
|
|
@ -20,10 +20,26 @@
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
|
||||||
# This script is used to trigger and cancel alarms from external sources
|
=head1 NAME
|
||||||
# using an arbitrary text based format
|
|
||||||
#
|
zmtrack.pl - ZoneMinder Experimental PTZ Tracking Script
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
zmtrack.pl -m <monitor>
|
||||||
|
zmtrack.pl --monitor=<monitor>
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
-m<monitor>, --monitor=<monitor> - Id of the monitor to track
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This script is used to trigger and cancel alarms from external sources
|
||||||
|
using an arbitrary text based format.
|
||||||
|
|
||||||
|
=cut
|
||||||
use strict;
|
use strict;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
|
@ -45,8 +61,9 @@ use constant SLEEP_TIME => 10000; # In microseconds
|
||||||
use ZoneMinder;
|
use ZoneMinder;
|
||||||
use DBI;
|
use DBI;
|
||||||
use POSIX;
|
use POSIX;
|
||||||
use Data::Dumper;
|
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
|
use autouse 'Pod::Usage'=>qw(pod2usage);
|
||||||
use Time::HiRes qw( usleep );
|
use Time::HiRes qw( usleep );
|
||||||
|
|
||||||
$| = 1;
|
$| = 1;
|
||||||
|
@ -57,20 +74,8 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
||||||
|
|
||||||
my $mid = 0;
|
my $mid = 0;
|
||||||
|
|
||||||
sub Usage
|
GetOptions( 'monitor=s'=>\$mid )
|
||||||
{
|
or pod2usage(-exitstatus => -1);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
logInit();
|
logInit();
|
||||||
logSetSignal();
|
logSetSignal();
|
||||||
|
@ -78,14 +83,22 @@ logSetSignal();
|
||||||
my ( $detaint_mid ) = $mid =~ /^(\d+)$/;
|
my ( $detaint_mid ) = $mid =~ /^(\d+)$/;
|
||||||
$mid = $detaint_mid;
|
$mid = $detaint_mid;
|
||||||
|
|
||||||
print( "Tracker daemon $mid (experimental) starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
|
print( "Tracker daemon $mid (experimental) starting at "
|
||||||
|
.strftime( '%y/%m/%d %H:%M:%S', localtime() )
|
||||||
|
."\n"
|
||||||
|
);
|
||||||
|
|
||||||
my $dbh = zmDbConnect();
|
my $dbh = zmDbConnect();
|
||||||
|
|
||||||
my $sql = "select C.*,M.* from Monitors as M left join Controls as C on M.ControlId = C.Id where M.Id = ?";
|
my $sql = "SELECT C.*,M.* FROM Monitors as M
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
LEFT JOIN Controls as C on M.ControlId = C.Id
|
||||||
|
WHERE M.Id = ?"
|
||||||
|
;
|
||||||
|
my $sth = $dbh->prepare_cached( $sql )
|
||||||
|
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
|
|
||||||
my $res = $sth->execute( $mid ) or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
my $res = $sth->execute( $mid )
|
||||||
|
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||||
my $monitor = $sth->fetchrow_hashref();
|
my $monitor = $sth->fetchrow_hashref();
|
||||||
|
|
||||||
if ( !$monitor )
|
if ( !$monitor )
|
||||||
|
@ -141,8 +154,16 @@ sub Track
|
||||||
my ( $detaint_x ) = $x =~ /^(\d+)$/; $x = $detaint_x;
|
my ( $detaint_x ) = $x =~ /^(\d+)$/; $x = $detaint_x;
|
||||||
my ( $detaint_y ) = $y =~ /^(\d+)$/; $y = $detaint_y;
|
my ( $detaint_y ) = $y =~ /^(\d+)$/; $y = $detaint_y;
|
||||||
|
|
||||||
my $ctrlCommand = $Config{ZM_PATH_BIN}."/zmcontrol.pl -i ".$monitor->{Id};
|
my $ctrlCommand = $Config{ZM_PATH_BIN}
|
||||||
$ctrlCommand .= " --command=".($monitor->{CanMoveMap}?"moveMap":"movePseudoMap")." --xcoord=$x --ycoord=$y";
|
."/zmcontrol.pl -i "
|
||||||
|
.$monitor->{Id}
|
||||||
|
;
|
||||||
|
$ctrlCommand .= " --command="
|
||||||
|
.( $monitor->{CanMoveMap} ? "moveMap"
|
||||||
|
: "movePseudoMap"
|
||||||
|
)
|
||||||
|
." --xcoord=$x --ycoord=$y"
|
||||||
|
;
|
||||||
executeShellCommand( $ctrlCommand );
|
executeShellCommand( $ctrlCommand );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,10 +171,15 @@ sub Return
|
||||||
{
|
{
|
||||||
my $monitor = shift;
|
my $monitor = shift;
|
||||||
|
|
||||||
my $ctrlCommand = $Config{ZM_PATH_BIN}."/zmcontrol.pl -i ".$monitor->{Id};
|
my $ctrlCommand = $Config{ZM_PATH_BIN}
|
||||||
|
."/zmcontrol.pl -i "
|
||||||
|
.$monitor->{Id}
|
||||||
|
;
|
||||||
if ( $monitor->{ReturnLocation} > 0 )
|
if ( $monitor->{ReturnLocation} > 0 )
|
||||||
{
|
{
|
||||||
$ctrlCommand .= " --command=presetGoto --preset=".$monitor->{ReturnLocation};
|
$ctrlCommand .= " --command=presetGoto --preset="
|
||||||
|
.$monitor->{ReturnLocation}
|
||||||
|
;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -193,7 +219,10 @@ while( 1 )
|
||||||
print( "Left alarm state\n" );
|
print( "Left alarm state\n" );
|
||||||
$alarmed = undef;
|
$alarmed = undef;
|
||||||
}
|
}
|
||||||
if ( ($monitor->{ReturnLocation} >= 0) && ($last_alarm > 0) && ((time()-$last_alarm) > $monitor->{ReturnDelay}) )
|
if ( ($monitor->{ReturnLocation} >= 0)
|
||||||
|
&& ($last_alarm > 0)
|
||||||
|
&& ((time()-$last_alarm) > $monitor->{ReturnDelay})
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Debug( "Returning to location ".$monitor->{ReturnLocation}."\n" );
|
Debug( "Returning to location ".$monitor->{ReturnLocation}."\n" );
|
||||||
Suspend( $monitor );
|
Suspend( $monitor );
|
||||||
|
|
|
@ -20,11 +20,17 @@
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
|
||||||
# This script is used to trigger and cancel alarms from external connections
|
=head1 NAME
|
||||||
# using an arbitrary text based format
|
|
||||||
#
|
zmtrigger.pl - ZoneMinder External Trigger Script
|
||||||
# ==========================================================================
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This script is used to trigger and cancel alarms from external connections
|
||||||
|
using an arbitrary text based format
|
||||||
|
|
||||||
|
=cut
|
||||||
use strict;
|
use strict;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
|
@ -52,8 +58,22 @@ use ZoneMinder::Trigger::Channel::Serial;
|
||||||
use ZoneMinder::Trigger::Connection;
|
use ZoneMinder::Trigger::Connection;
|
||||||
|
|
||||||
my @connections;
|
my @connections;
|
||||||
push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan1", channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ), mode=>"rw" ) );
|
push( @connections,
|
||||||
push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan2", channel=>ZoneMinder::Trigger::Channel::Unix->new( path=>$Config{ZM_PATH_SOCKS}.'/zmtrigger.sock' ), mode=>"rw" ) );
|
ZoneMinder::Trigger::Connection->new(
|
||||||
|
name=>"Chan1",
|
||||||
|
channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ),
|
||||||
|
mode=>"rw"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
push( @connections,
|
||||||
|
ZoneMinder::Trigger::Connection->new(
|
||||||
|
name=>"Chan2",
|
||||||
|
channel=>ZoneMinder::Trigger::Channel::Unix->new(
|
||||||
|
path=>$Config{ZM_PATH_SOCKS}.'/zmtrigger.sock'
|
||||||
|
),
|
||||||
|
mode=>"rw"
|
||||||
|
)
|
||||||
|
);
|
||||||
#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan3", channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>"w" ) );
|
#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan3", channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>"w" ) );
|
||||||
#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan4", channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>"rw" ) );
|
#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan4", channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>"rw" ) );
|
||||||
|
|
||||||
|
@ -65,7 +85,7 @@ push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan2", channel
|
||||||
|
|
||||||
use DBI;
|
use DBI;
|
||||||
#use Socket;
|
#use Socket;
|
||||||
use Data::Dumper;
|
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||||
use POSIX qw( EINTR );
|
use POSIX qw( EINTR );
|
||||||
use Time::HiRes qw( usleep );
|
use Time::HiRes qw( usleep );
|
||||||
|
|
||||||
|
@ -126,12 +146,22 @@ while( 1 )
|
||||||
{
|
{
|
||||||
if ( vec( $rout, $connection->fileno(), 1 ) )
|
if ( vec( $rout, $connection->fileno(), 1 ) )
|
||||||
{
|
{
|
||||||
Debug( "Got input from connection ".$connection->name()." (".$connection->fileno().")\n" );
|
Debug( "Got input from connection "
|
||||||
|
.$connection->name()
|
||||||
|
." ("
|
||||||
|
.$connection->fileno()
|
||||||
|
.")\n"
|
||||||
|
);
|
||||||
if ( $connection->spawns() )
|
if ( $connection->spawns() )
|
||||||
{
|
{
|
||||||
my $new_connection = $connection->accept();
|
my $new_connection = $connection->accept();
|
||||||
$spawned_connections{$new_connection->fileno()} = $new_connection;
|
$spawned_connections{$new_connection->fileno()} = $new_connection;
|
||||||
Debug( "Added new spawned connection (".$new_connection->fileno()."), ".int(keys(%spawned_connections))." spawned connections\n" );
|
Debug( "Added new spawned connection ("
|
||||||
|
.$new_connection->fileno()
|
||||||
|
."), "
|
||||||
|
.int(keys(%spawned_connections))
|
||||||
|
." spawned connections\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -150,7 +180,12 @@ while( 1 )
|
||||||
{
|
{
|
||||||
if ( vec( $rout, $connection->fileno(), 1 ) )
|
if ( vec( $rout, $connection->fileno(), 1 ) )
|
||||||
{
|
{
|
||||||
Debug( "Got input from spawned connection ".$connection->name()." (".$connection->fileno().")\n" );
|
Debug( "Got input from spawned connection "
|
||||||
|
.$connection->name()
|
||||||
|
." ("
|
||||||
|
.$connection->fileno()
|
||||||
|
.")\n"
|
||||||
|
);
|
||||||
my $messages = $connection->getMessages();
|
my $messages = $connection->getMessages();
|
||||||
if ( defined($messages) )
|
if ( defined($messages) )
|
||||||
{
|
{
|
||||||
|
@ -162,7 +197,12 @@ while( 1 )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete( $spawned_connections{$connection->fileno()} );
|
delete( $spawned_connections{$connection->fileno()} );
|
||||||
Debug( "Removed spawned connection (".$connection->fileno()."), ".int(keys(%spawned_connections))." spawned connections\n" );
|
Debug( "Removed spawned connection ("
|
||||||
|
.$connection->fileno()
|
||||||
|
."), "
|
||||||
|
.int(keys(%spawned_connections))
|
||||||
|
." spawned connections\n"
|
||||||
|
);
|
||||||
$connection->close();
|
$connection->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,13 +237,22 @@ while( 1 )
|
||||||
my @out_messages;
|
my @out_messages;
|
||||||
foreach my $monitor ( values(%monitors) )
|
foreach my $monitor ( values(%monitors) )
|
||||||
{
|
{
|
||||||
my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state", "shared_data:last_event" ] );
|
my ( $state, $last_event )
|
||||||
|
= zmMemRead( $monitor,
|
||||||
|
[ "shared_data:state",
|
||||||
|
"shared_data:last_event"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
#print( "$monitor->{Id}: S:$state, LE:$last_event\n" );
|
#print( "$monitor->{Id}: S:$state, LE:$last_event\n" );
|
||||||
#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" );
|
#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" );
|
||||||
if ( $state == STATE_ALARM || $state == STATE_ALERT ) # In alarm state
|
if ( $state == STATE_ALARM
|
||||||
|
|| $state == STATE_ALERT
|
||||||
|
) # In alarm state
|
||||||
{
|
{
|
||||||
if ( !defined($monitor->{LastEvent}) || ($last_event != $monitor->{LastEvent}) ) # A new event
|
if ( !defined($monitor->{LastEvent})
|
||||||
|
|| ($last_event != $monitor->{LastEvent})
|
||||||
|
) # A new event
|
||||||
{
|
{
|
||||||
push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event );
|
push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event );
|
||||||
}
|
}
|
||||||
|
@ -212,11 +261,19 @@ while( 1 )
|
||||||
# Do nothing
|
# Do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) || ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) ) # Out of alarm state
|
elsif ( ($state == STATE_IDLE
|
||||||
|
&& $monitor->{LastState} != STATE_IDLE
|
||||||
|
)
|
||||||
|
|| ($state == STATE_TAPE
|
||||||
|
&& $monitor->{LastState} != STATE_TAPE
|
||||||
|
)
|
||||||
|
) # Out of alarm state
|
||||||
{
|
{
|
||||||
push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event );
|
push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event );
|
||||||
}
|
}
|
||||||
elsif ( defined($monitor->{LastEvent}) && ($last_event != $monitor->{LastEvent}) ) # We've missed a whole event
|
elsif ( defined($monitor->{LastEvent})
|
||||||
|
&& ($last_event != $monitor->{LastEvent})
|
||||||
|
) # We've missed a whole event
|
||||||
{
|
{
|
||||||
push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event );
|
push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event );
|
||||||
push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event );
|
push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event );
|
||||||
|
@ -239,7 +296,8 @@ while( 1 )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug( "Checking for timed actions\n" ) if ( int(keys(%actions)) );
|
Debug( "Checking for timed actions\n" )
|
||||||
|
if ( int(keys(%actions)) );
|
||||||
my $now = time();
|
my $now = time();
|
||||||
foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) )
|
foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) )
|
||||||
{
|
{
|
||||||
|
@ -299,9 +357,13 @@ sub loadMonitors
|
||||||
|
|
||||||
my %new_monitors = ();
|
my %new_monitors = ();
|
||||||
|
|
||||||
my $sql = "select * from Monitors where find_in_set( Function, 'Modect,Mocord,Nodect' )";
|
my $sql = "SELECT * FROM Monitors
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )"
|
||||||
my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() );
|
;
|
||||||
|
my $sth = $dbh->prepare_cached( $sql )
|
||||||
|
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
|
my $res = $sth->execute()
|
||||||
|
or Fatal( "Can't execute: ".$sth->errstr() );
|
||||||
while( my $monitor = $sth->fetchrow_hashref() )
|
while( my $monitor = $sth->fetchrow_hashref() )
|
||||||
{
|
{
|
||||||
next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok
|
next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok
|
||||||
|
@ -332,7 +394,8 @@ sub handleMessage
|
||||||
my $connection = shift;
|
my $connection = shift;
|
||||||
my $message = shift;
|
my $message = shift;
|
||||||
|
|
||||||
my ( $id, $action, $score, $cause, $text, $showtext ) = split( /\|/, $message );
|
my ( $id, $action, $score, $cause, $text, $showtext )
|
||||||
|
= split( /\|/, $message );
|
||||||
$score = 0 if ( !defined($score) );
|
$score = 0 if ( !defined($score) );
|
||||||
$cause = "" if ( !defined($cause) );
|
$cause = "" if ( !defined($cause) );
|
||||||
$text = "" if ( !defined($text) );
|
$text = "" if ( !defined($text) );
|
||||||
|
@ -366,13 +429,20 @@ sub handleMessage
|
||||||
if ( $delay )
|
if ( $delay )
|
||||||
{
|
{
|
||||||
my $action_time = time()+$delay;
|
my $action_time = time()+$delay;
|
||||||
my $action_text = $id."|".(($state eq "enable")?"disable":"enable");
|
my $action_text = $id."|".( ($state eq "enable")
|
||||||
|
? "disable"
|
||||||
|
: "enable"
|
||||||
|
)
|
||||||
|
;
|
||||||
my $action_array = $actions{$action_time};
|
my $action_array = $actions{$action_time};
|
||||||
if ( !$action_array )
|
if ( !$action_array )
|
||||||
{
|
{
|
||||||
$action_array = $actions{$action_time} = [];
|
$action_array = $actions{$action_time} = [];
|
||||||
}
|
}
|
||||||
push( @$action_array, { connection=>$connection, message=>$action_text } );
|
push( @$action_array, { connection=>$connection,
|
||||||
|
message=>$action_text
|
||||||
|
}
|
||||||
|
);
|
||||||
Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" );
|
Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,7 +466,9 @@ sub handleMessage
|
||||||
zmTriggerShowtext( $monitor, $showtext ) if defined($showtext);
|
zmTriggerShowtext( $monitor, $showtext ) if defined($showtext);
|
||||||
Info( "Trigger '$trigger'\n" );
|
Info( "Trigger '$trigger'\n" );
|
||||||
# Wait til it's finished
|
# Wait til it's finished
|
||||||
while( zmInAlarm( $monitor ) && ($last_event == zmGetLastEvent( $monitor )) )
|
while( zmInAlarm( $monitor )
|
||||||
|
&& ($last_event == zmGetLastEvent( $monitor ))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
# Tenth of a second
|
# Tenth of a second
|
||||||
usleep( 100000 );
|
usleep( 100000 );
|
||||||
|
@ -418,7 +490,10 @@ sub handleMessage
|
||||||
{
|
{
|
||||||
$action_array = $actions{$action_time} = [];
|
$action_array = $actions{$action_time} = [];
|
||||||
}
|
}
|
||||||
push( @$action_array, { connection=>$connection, message=>$action_text } );
|
push( @$action_array, { connection=>$connection,
|
||||||
|
message=>$action_text
|
||||||
|
}
|
||||||
|
);
|
||||||
Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" );
|
Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ use POSIX;
|
||||||
use DBI;
|
use DBI;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use autouse 'Pod::Usage'=>qw(pod2usage);
|
use autouse 'Pod::Usage'=>qw(pod2usage);
|
||||||
use Data::Dumper;
|
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||||
|
|
||||||
use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)?$Config{ZM_DIR_EVENTS}:($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS});
|
use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)?$Config{ZM_DIR_EVENTS}:($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS});
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,37 @@
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# 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
|
=head1 NAME
|
||||||
# or as email attachments.
|
|
||||||
#
|
zmvideo.pl - ZoneMinder Video Creation Script
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
zmvideo.pl -e <event_id>,--event=<event_id> [--format <format>]
|
||||||
|
[--rate=<rate>]
|
||||||
|
[--scale=<scale>]
|
||||||
|
[--fps=<fps>]
|
||||||
|
[--size=<size>]
|
||||||
|
[--overwrite]
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This script is used to create MPEG videos of events for the web pages
|
||||||
|
or as email attachments.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
-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.
|
||||||
|
-v, --version - Outputs the currently installed version of ZoneMinder
|
||||||
|
|
||||||
|
=cut
|
||||||
use strict;
|
use strict;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
|
@ -36,9 +63,10 @@ use bytes;
|
||||||
@EXTRA_PERL_LIB@
|
@EXTRA_PERL_LIB@
|
||||||
use ZoneMinder;
|
use ZoneMinder;
|
||||||
use DBI;
|
use DBI;
|
||||||
use Data::Dumper;
|
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||||
use POSIX qw(strftime);
|
use POSIX qw(strftime);
|
||||||
use Getopt::Long qw(:config no_ignore_case );
|
use Getopt::Long qw(:config no_ignore_case );
|
||||||
|
use autouse 'Pod::Usage'=>qw(pod2usage);
|
||||||
|
|
||||||
$| = 1;
|
$| = 1;
|
||||||
|
|
||||||
|
@ -66,27 +94,16 @@ for ( my $i = 0; $i < @formats; $i++ )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub Usage
|
GetOptions(
|
||||||
{
|
'event=i' =>\$event_id,
|
||||||
print( "
|
'format|f=s' =>\$format,
|
||||||
Usage: zmvideo.pl -e <event_id>,--event=<event_id> [--format <format>] [--rate=<rate>] [--scale=<scale>] [--fps=<fps>] [--size=<size>] [--overwrite]
|
'rate|r=f' =>\$rate,
|
||||||
Parameters are :-
|
'scale|s=f' =>\$scale,
|
||||||
-e<event_id>, --event=<event_id> - What event to create the video for
|
'fps|F=f' =>\$fps,
|
||||||
-f<format>, --format=<format> - What format to create the video in, default is mpg. For ffmpeg only.
|
'size|S=s' =>\$size,
|
||||||
-r<rate>, --rate=<rate> - Relative rate , 1 = realtime, 2 = double speed , 0.5 = half speed etc
|
'overwrite' =>\$overwrite,
|
||||||
-s<scale>, --scale=<scale> - Scale, 1 = normal, 2 = double size, 0.5 = half size etc
|
'version' =>\$version
|
||||||
-F<fps>, --fps=<fps> - Absolute frame rate, in frames per second
|
) or pod2usage(-exitstatus => -1);
|
||||||
-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.
|
|
||||||
-v, --version - Outputs the currently installed version of ZoneMinder
|
|
||||||
");
|
|
||||||
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, version=>\$version ) )
|
|
||||||
{
|
|
||||||
Usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $version ) {
|
if ( $version ) {
|
||||||
print ZoneMinder::Base::ZM_VERSION . "\n";
|
print ZoneMinder::Base::ZM_VERSION . "\n";
|
||||||
|
@ -96,7 +113,7 @@ if ( $version ) {
|
||||||
if ( !$event_id || $event_id < 0 )
|
if ( !$event_id || $event_id < 0 )
|
||||||
{
|
{
|
||||||
print( STDERR "Please give a valid event id\n" );
|
print( STDERR "Please give a valid event id\n" );
|
||||||
Usage();
|
pod2usage(-exitstatus => -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $Config{ZM_OPT_FFMPEG} )
|
if ( ! $Config{ZM_OPT_FFMPEG} )
|
||||||
|
@ -118,19 +135,19 @@ if ( !$scale && !$size )
|
||||||
if ( $rate && ($rate < 0.25 || $rate > 100) )
|
if ( $rate && ($rate < 0.25 || $rate > 100) )
|
||||||
{
|
{
|
||||||
print( STDERR "Rate is out of range, 0.25 >= rate <= 100\n" );
|
print( STDERR "Rate is out of range, 0.25 >= rate <= 100\n" );
|
||||||
Usage();
|
pod2usage(-exitstatus => -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $scale && ($scale < 0.25 || $scale > 4) )
|
if ( $scale && ($scale < 0.25 || $scale > 4) )
|
||||||
{
|
{
|
||||||
print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" );
|
print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" );
|
||||||
Usage();
|
pod2usage(-exitstatus => -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $fps && ($fps > 30) )
|
if ( $fps && ($fps > 30) )
|
||||||
{
|
{
|
||||||
print( STDERR "FPS is out of range, <= 30\n" );
|
print( STDERR "FPS is out of range, <= 30\n" );
|
||||||
Usage();
|
pod2usage(-exitstatus => -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
my ( $detaint_format ) = $format =~ /^(\w+)$/;
|
my ( $detaint_format ) = $format =~ /^(\w+)$/;
|
||||||
|
@ -148,9 +165,23 @@ $size = $detaint_size;
|
||||||
my $dbh = zmDbConnect();
|
my $dbh = zmDbConnect();
|
||||||
|
|
||||||
my @filters;
|
my @filters;
|
||||||
my $sql = "select max(F.Delta)-min(F.Delta) as FullLength, E.*, unix_timestamp(E.StartTime) as Time, 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 $sql = " SELECT max(F.Delta)-min(F.Delta) as FullLength,
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
E.*,
|
||||||
my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() );
|
unix_timestamp(E.StartTime) as Time,
|
||||||
|
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 Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
|
my $res = $sth->execute()
|
||||||
|
or Fatal( "Can't execute: ".$sth->errstr() );
|
||||||
my $event = $sth->fetchrow_hashref();
|
my $event = $sth->fetchrow_hashref();
|
||||||
$sth->finish();
|
$sth->finish();
|
||||||
my $event_path = getEventPath( $event );
|
my $event_path = getEventPath( $event );
|
||||||
|
@ -228,14 +259,24 @@ if ( $overwrite || !-s $video_file )
|
||||||
$video_size = $size;
|
$video_size = $size;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $command = $Config{ZM_PATH_FFMPEG}." -y -r $frame_rate ".$Config{ZM_FFMPEG_INPUT_OPTIONS}." -i %0".$Config{ZM_EVENT_IMAGE_DIGITS}."d-capture.jpg -s $video_size ".$Config{ZM_FFMPEG_OUTPUT_OPTIONS}." '$video_file' > ffmpeg.log 2>&1";
|
my $command = $Config{ZM_PATH_FFMPEG}
|
||||||
|
." -y -r $frame_rate "
|
||||||
|
.$Config{ZM_FFMPEG_INPUT_OPTIONS}
|
||||||
|
." -i %0"
|
||||||
|
.$Config{ZM_EVENT_IMAGE_DIGITS}
|
||||||
|
."d-capture.jpg -s $video_size "
|
||||||
|
.$Config{ZM_FFMPEG_OUTPUT_OPTIONS}
|
||||||
|
." '$video_file' > ffmpeg.log 2>&1"
|
||||||
|
;
|
||||||
Debug( $command."\n" );
|
Debug( $command."\n" );
|
||||||
my $output = qx($command);
|
my $output = qx($command);
|
||||||
|
|
||||||
my $status = $? >> 8;
|
my $status = $? >> 8;
|
||||||
if ( $status )
|
if ( $status )
|
||||||
{
|
{
|
||||||
Error( "Unable to generate video, check ".$event_path."/ffmpeg.log for details" );
|
Error( "Unable to generate video, check "
|
||||||
|
.$event_path."/ffmpeg.log for details"
|
||||||
|
);
|
||||||
exit( -1 );
|
exit( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,22 @@
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
|
||||||
# This does some basic setup for ZoneMinder to run and then periodically
|
=head1 NAME
|
||||||
# checks the fps output of the active daemons to check they haven't
|
|
||||||
# locked up. If they have then they are killed and restarted
|
zmwatch.pl - ZoneMinder WatchDog Script
|
||||||
#
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
zmwatch.pl
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
=cut
|
||||||
use strict;
|
use strict;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
|
@ -46,7 +57,7 @@ use constant START_DELAY => 30; # To give everything else time to start
|
||||||
use ZoneMinder;
|
use ZoneMinder;
|
||||||
use POSIX;
|
use POSIX;
|
||||||
use DBI;
|
use DBI;
|
||||||
use Data::Dumper;
|
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||||
|
|
||||||
$| = 1;
|
$| = 1;
|
||||||
|
|
||||||
|
@ -54,14 +65,6 @@ $ENV{PATH} = '/bin:/usr/bin';
|
||||||
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
|
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
|
||||||
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
||||||
|
|
||||||
sub Usage
|
|
||||||
{
|
|
||||||
print( "
|
|
||||||
Usage: zmwatch.pl
|
|
||||||
");
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
logInit();
|
logInit();
|
||||||
logSetSignal();
|
logSetSignal();
|
||||||
|
|
||||||
|
@ -72,30 +75,41 @@ sleep( START_DELAY );
|
||||||
my $dbh = zmDbConnect();
|
my $dbh = zmDbConnect();
|
||||||
|
|
||||||
my $sql = "select * from Monitors";
|
my $sql = "select * from Monitors";
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
my $sth = $dbh->prepare_cached( $sql )
|
||||||
|
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
my $now = time();
|
my $now = time();
|
||||||
my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() );
|
my $res = $sth->execute()
|
||||||
|
or Fatal( "Can't execute: ".$sth->errstr() );
|
||||||
while( my $monitor = $sth->fetchrow_hashref() )
|
while( my $monitor = $sth->fetchrow_hashref() )
|
||||||
{
|
{
|
||||||
if ( $monitor->{Function} ne 'None' )
|
if ( $monitor->{Function} ne 'None' )
|
||||||
{
|
{
|
||||||
my $restart = 0;
|
my $restart = 0;
|
||||||
if ( zmMemVerify( $monitor ) && zmMemRead( $monitor, "shared_data:valid" ) )
|
if ( zmMemVerify( $monitor )
|
||||||
|
&& zmMemRead( $monitor, "shared_data:valid" )
|
||||||
|
)
|
||||||
{
|
{
|
||||||
# Check we have got an image recently
|
# Check we have got an image recently
|
||||||
my $image_time = zmGetLastWriteTime( $monitor );
|
my $image_time = zmGetLastWriteTime( $monitor );
|
||||||
next if ( !defined($image_time) ); # Can't read from shared data
|
next if ( !defined($image_time) ); # Can't read from shared data
|
||||||
next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died.
|
next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died.
|
||||||
|
|
||||||
my $max_image_delay = ($monitor->{MaxFPS}&&($monitor->{MaxFPS}>0)&&($monitor->{MaxFPS}<1))?(3/$monitor->{MaxFPS}):$Config{ZM_WATCH_MAX_DELAY};
|
my $max_image_delay = ( $monitor->{MaxFPS}
|
||||||
|
&&($monitor->{MaxFPS}>0)
|
||||||
|
&&($monitor->{MaxFPS}<1)
|
||||||
|
) ? (3/$monitor->{MaxFPS})
|
||||||
|
: $Config{ZM_WATCH_MAX_DELAY}
|
||||||
|
;
|
||||||
my $image_delay = $now-$image_time;
|
my $image_delay = $now-$image_time;
|
||||||
Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" );
|
Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" );
|
||||||
if ( $image_delay > $max_image_delay )
|
if ( $image_delay > $max_image_delay )
|
||||||
{
|
{
|
||||||
Info( "Restarting capture daemon for ".$monitor->{Name}.", time since last capture $image_delay seconds ($now-$image_time)\n" );
|
Info( "Restarting capture daemon for "
|
||||||
|
.$monitor->{Name}.", time since last capture $image_delay seconds ($now-$image_time)\n"
|
||||||
|
);
|
||||||
$restart = 1;
|
$restart = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,19 +134,28 @@ while( 1 )
|
||||||
}
|
}
|
||||||
elsif ( $monitor->{Function} ne 'Monitor' )
|
elsif ( $monitor->{Function} ne 'Monitor' )
|
||||||
{
|
{
|
||||||
if ( zmMemVerify( $monitor ) && zmMemRead( $monitor, "shared_data:valid" ) )
|
if ( zmMemVerify( $monitor )
|
||||||
|
&& zmMemRead( $monitor, "shared_data:valid" )
|
||||||
|
)
|
||||||
{
|
{
|
||||||
# Check we have got an image recently
|
# Check we have got an image recently
|
||||||
my $image_time = zmGetLastReadTime( $monitor );
|
my $image_time = zmGetLastReadTime( $monitor );
|
||||||
next if ( !defined($image_time) ); # Can't read from shared data
|
next if ( !defined($image_time) ); # Can't read from shared data
|
||||||
next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died.
|
next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died.
|
||||||
|
|
||||||
my $max_image_delay = ($monitor->{MaxFPS}&&($monitor->{MaxFPS}>0)&&($monitor->{MaxFPS}<1))?(3/$monitor->{MaxFPS}):$Config{ZM_WATCH_MAX_DELAY};
|
my $max_image_delay = ( $monitor->{MaxFPS}
|
||||||
|
&&($monitor->{MaxFPS}>0)
|
||||||
|
&&($monitor->{MaxFPS}<1)
|
||||||
|
) ? (3/$monitor->{MaxFPS})
|
||||||
|
: $Config{ZM_WATCH_MAX_DELAY}
|
||||||
|
;
|
||||||
my $image_delay = $now-$image_time;
|
my $image_delay = $now-$image_time;
|
||||||
Debug( "Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay\n" );
|
Debug( "Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay\n" );
|
||||||
if ( $image_delay > $max_image_delay )
|
if ( $image_delay > $max_image_delay )
|
||||||
{
|
{
|
||||||
Info( "Restarting analysis daemon for ".$monitor->{Name}.", time since last analysis $image_delay seconds ($now-$image_time)\n" );
|
Info( "Restarting analysis daemon for "
|
||||||
|
.$monitor->{Name}.", time since last analysis $image_delay seconds ($now-$image_time)\n"
|
||||||
|
);
|
||||||
my $command = "zmdc.pl restart zma -m ".$monitor->{Id};
|
my $command = "zmdc.pl restart zma -m ".$monitor->{Id};
|
||||||
runCommand( $command );
|
runCommand( $command );
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,28 @@
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
|
||||||
# This script controls the monitoring of the X10 interface and the consequent
|
=head1 NAME
|
||||||
# management of the ZM daemons based on the receipt of X10 signals.
|
|
||||||
#
|
zmx10.pl - ZoneMinder X10 Control Script
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
zmx10.pl -c <command>,--command=<command> [-u <unit code>,--unit-code=<unit code>]
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This script controls the monitoring of the X10 interface and the consequent
|
||||||
|
management of the ZM daemons based on the receipt of X10 signals.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
-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'
|
||||||
|
-v, --verison - Pirnts the currently installed version of ZoneMinder
|
||||||
|
|
||||||
|
=cut
|
||||||
use strict;
|
use strict;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
|
@ -46,7 +64,8 @@ use ZoneMinder;
|
||||||
use POSIX;
|
use POSIX;
|
||||||
use Socket;
|
use Socket;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use Data::Dumper;
|
use autouse 'Pod::Usage'=>qw(pod2usage);
|
||||||
|
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||||
|
|
||||||
use constant SOCK_FILE => $Config{ZM_PATH_SOCKS}.'/zmx10.sock';
|
use constant SOCK_FILE => $Config{ZM_PATH_SOCKS}.'/zmx10.sock';
|
||||||
|
|
||||||
|
@ -56,18 +75,6 @@ $ENV{PATH} = '/bin:/usr/bin';
|
||||||
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
|
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
|
||||||
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
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'
|
|
||||||
-v, --verison - Pirnts the currently installed version of ZoneMinder
|
|
||||||
");
|
|
||||||
exit( -1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
logInit();
|
logInit();
|
||||||
logSetSignal();
|
logSetSignal();
|
||||||
|
|
||||||
|
@ -75,17 +82,20 @@ my $command;
|
||||||
my $unit_code;
|
my $unit_code;
|
||||||
my $version;
|
my $version;
|
||||||
|
|
||||||
if ( !GetOptions( 'command=s'=>\$command, 'unit-code=i'=>\$unit_code, version=>\$version ) )
|
GetOptions(
|
||||||
{
|
'command=s' =>\$command,
|
||||||
Usage();
|
'unit-code=i' =>\$unit_code,
|
||||||
}
|
'version' =>\$version
|
||||||
|
) or pod2usage(-exitstatus => -1);
|
||||||
|
|
||||||
if ( $version ) {
|
if ( $version ) {
|
||||||
print ZoneMinder::Base::ZM_VERSION;
|
print ZoneMinder::Base::ZM_VERSION;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
die( "No command given" ) unless( $command );
|
die( "No command given" ) unless( $command );
|
||||||
die( "No unit code given" ) unless( $unit_code || ($command =~ /(?:start|status|shutdown)/) );
|
die( "No unit code given" )
|
||||||
|
unless( $unit_code || ($command =~ /(?:start|status|shutdown)/) );
|
||||||
|
|
||||||
if ( $command eq "start" )
|
if ( $command eq "start" )
|
||||||
{
|
{
|
||||||
|
@ -93,7 +103,8 @@ if ( $command eq "start" )
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
|
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 )
|
||||||
|
or Fatal( "Can't open socket: $!" );
|
||||||
|
|
||||||
my $saddr = sockaddr_un( SOCK_FILE );
|
my $saddr = sockaddr_un( SOCK_FILE );
|
||||||
|
|
||||||
|
@ -108,8 +119,10 @@ if ( !connect( CLIENT, $saddr ) )
|
||||||
# Parent process just sleep and fall through
|
# Parent process just sleep and fall through
|
||||||
sleep( 2 );
|
sleep( 2 );
|
||||||
logReinit();
|
logReinit();
|
||||||
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
|
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 )
|
||||||
connect( CLIENT, $saddr ) or Fatal( "Can't connect: $!" );
|
or Fatal( "Can't open socket: $!" );
|
||||||
|
connect( CLIENT, $saddr )
|
||||||
|
or Fatal( "Can't connect: $!" );
|
||||||
}
|
}
|
||||||
elsif ( defined($cpid) )
|
elsif ( defined($cpid) )
|
||||||
{
|
{
|
||||||
|
@ -156,7 +169,7 @@ use POSIX;
|
||||||
use DBI;
|
use DBI;
|
||||||
use Socket;
|
use Socket;
|
||||||
use X10::ActiveHome;
|
use X10::ActiveHome;
|
||||||
use Data::Dumper;
|
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||||
|
|
||||||
our $dbh;
|
our $dbh;
|
||||||
our $x10;
|
our $x10;
|
||||||
|
@ -169,7 +182,8 @@ sub runServer
|
||||||
{
|
{
|
||||||
Info( "X10 server starting\n" );
|
Info( "X10 server starting\n" );
|
||||||
|
|
||||||
socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
|
socket( SERVER, PF_UNIX, SOCK_STREAM, 0 )
|
||||||
|
or Fatal( "Can't open socket: $!" );
|
||||||
unlink( main::SOCK_FILE );
|
unlink( main::SOCK_FILE );
|
||||||
my $saddr = sockaddr_un( main::SOCK_FILE );
|
my $saddr = sockaddr_un( main::SOCK_FILE );
|
||||||
bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" );
|
bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" );
|
||||||
|
@ -218,7 +232,9 @@ sub runServer
|
||||||
$device = $device_hash{$unit_code};
|
$device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device )
|
||||||
{
|
{
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
|
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
||||||
|
status=>'unknown'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,12 +325,16 @@ sub runServer
|
||||||
if ( defined( $monitor->{LastState} ) )
|
if ( defined( $monitor->{LastState} ) )
|
||||||
{
|
{
|
||||||
my $task_list;
|
my $task_list;
|
||||||
if ( ($state == STATE_ALARM || $state == STATE_ALERT) && ($monitor->{LastState} == STATE_IDLE || $monitor->{LastState} == STATE_TAPE) ) # Gone into alarm state
|
if ( ($state == STATE_ALARM || $state == STATE_ALERT)
|
||||||
|
&& ($monitor->{LastState} == STATE_IDLE || $monitor->{LastState} == STATE_TAPE)
|
||||||
|
) # Gone into alarm state
|
||||||
{
|
{
|
||||||
Debug( "Applying ON_list for $monitor_id\n" );
|
Debug( "Applying ON_list for $monitor_id\n" );
|
||||||
$task_list = $monitor->{"ON_list"};
|
$task_list = $monitor->{"ON_list"};
|
||||||
}
|
}
|
||||||
elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) || ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) ) # Come out of alarm state
|
elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE)
|
||||||
|
|| ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE)
|
||||||
|
) # Come out of alarm state
|
||||||
{
|
{
|
||||||
Debug( "Applying OFF_list for $monitor_id\n" );
|
Debug( "Applying OFF_list for $monitor_id\n" );
|
||||||
$task_list = $monitor->{"OFF_list"};
|
$task_list = $monitor->{"OFF_list"};
|
||||||
|
@ -363,14 +383,22 @@ sub addToDeviceList
|
||||||
my $function = shift;
|
my $function = shift;
|
||||||
my $limit = shift;
|
my $limit = shift;
|
||||||
|
|
||||||
Debug( "Adding to device list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" );
|
Debug( "Adding to device list, uc:$unit_code, ev:$event, mo:"
|
||||||
|
.$monitor->{Id}.", fu:$function, li:$limit\n"
|
||||||
|
);
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device )
|
||||||
{
|
{
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
|
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
||||||
|
status=>'unknown'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
my $task = { type=>"device", monitor=>$monitor, address=>$device->{appliance}->address(), function=>$function };
|
my $task = { type=>"device",
|
||||||
|
monitor=>$monitor,
|
||||||
|
address=>$device->{appliance}->address(),
|
||||||
|
function=>$function
|
||||||
|
};
|
||||||
if ( $limit )
|
if ( $limit )
|
||||||
{
|
{
|
||||||
$task->{limit} = $limit
|
$task->{limit} = $limit
|
||||||
|
@ -392,14 +420,22 @@ sub addToMonitorList
|
||||||
my $function = shift;
|
my $function = shift;
|
||||||
my $limit = shift;
|
my $limit = shift;
|
||||||
|
|
||||||
Debug( "Adding to monitor list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" );
|
Debug( "Adding to monitor list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}
|
||||||
|
.", fu:$function, li:$limit\n"
|
||||||
|
);
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device )
|
||||||
{
|
{
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
|
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
||||||
|
status=>'unknown'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
my $task = { type=>"monitor", device=>$device, id=>$monitor->{Id}, function=>$function };
|
my $task = { type=>"monitor",
|
||||||
|
device=>$device,
|
||||||
|
id=>$monitor->{Id},
|
||||||
|
function=>$function
|
||||||
|
};
|
||||||
if ( $limit )
|
if ( $limit )
|
||||||
{
|
{
|
||||||
$task->{limit} = $limit;
|
$task->{limit} = $limit;
|
||||||
|
@ -426,9 +462,16 @@ sub loadTasks
|
||||||
$device->{OFF_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,Nodect' ) and M.Enabled = 1 and find_in_set( 'X10', M.Triggers )";
|
my $sql = "SELECT M.*,T.* from Monitors as M
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
INNER JOIN TriggersX10 as T on (M.Id = T.MonitorId)
|
||||||
my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() );
|
WHERE find_in_set( M.Function, 'Modect,Record,Mocord,Nodect' )
|
||||||
|
AND M.Enabled = 1
|
||||||
|
AND find_IN_set( 'X10', M.Triggers )"
|
||||||
|
;
|
||||||
|
my $sth = $dbh->prepare_cached( $sql )
|
||||||
|
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
|
my $res = $sth->execute()
|
||||||
|
or Fatal( "Can't execute: ".$sth->errstr() );
|
||||||
while( my $monitor = $sth->fetchrow_hashref() )
|
while( my $monitor = $sth->fetchrow_hashref() )
|
||||||
{
|
{
|
||||||
next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok
|
next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok
|
||||||
|
@ -441,17 +484,30 @@ sub loadTasks
|
||||||
foreach my $code_string ( split( /,/, $monitor->{Activation} ) )
|
foreach my $code_string ( split( /,/, $monitor->{Activation} ) )
|
||||||
{
|
{
|
||||||
#Debug( "Code string: $code_string\n" );
|
#Debug( "Code string: $code_string\n" );
|
||||||
my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
my ( $invert, $unit_code, $modifier, $limit )
|
||||||
|
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
||||||
$limit = 0 if ( !$limit );
|
$limit = 0 if ( !$limit );
|
||||||
if ( $unit_code )
|
if ( $unit_code )
|
||||||
{
|
{
|
||||||
if ( !$modifier || $modifier eq '+' )
|
if ( !$modifier || $modifier eq '+' )
|
||||||
{
|
{
|
||||||
addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_active":"stop_active", $limit );
|
addToDeviceList( $unit_code,
|
||||||
|
"ON",
|
||||||
|
$monitor,
|
||||||
|
!$invert ? "start_active"
|
||||||
|
: "stop_active",
|
||||||
|
$limit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ( !$modifier || $modifier eq '-' )
|
if ( !$modifier || $modifier eq '-' )
|
||||||
{
|
{
|
||||||
addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_active":"start_active", $limit );
|
addToDeviceList( $unit_code,
|
||||||
|
"OFF",
|
||||||
|
$monitor,
|
||||||
|
!$invert ? "stop_active"
|
||||||
|
: "start_active",
|
||||||
|
$limit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,17 +518,30 @@ sub loadTasks
|
||||||
foreach my $code_string ( split( /,/, $monitor->{AlarmInput} ) )
|
foreach my $code_string ( split( /,/, $monitor->{AlarmInput} ) )
|
||||||
{
|
{
|
||||||
#Debug( "Code string: $code_string\n" );
|
#Debug( "Code string: $code_string\n" );
|
||||||
my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
my ( $invert, $unit_code, $modifier, $limit )
|
||||||
|
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
||||||
$limit = 0 if ( !$limit );
|
$limit = 0 if ( !$limit );
|
||||||
if ( $unit_code )
|
if ( $unit_code )
|
||||||
{
|
{
|
||||||
if ( !$modifier || $modifier eq '+' )
|
if ( !$modifier || $modifier eq '+' )
|
||||||
{
|
{
|
||||||
addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_alarm":"stop_alarm", $limit );
|
addToDeviceList( $unit_code,
|
||||||
|
"ON",
|
||||||
|
$monitor,
|
||||||
|
!$invert ? "start_alarm"
|
||||||
|
: "stop_alarm",
|
||||||
|
$limit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ( !$modifier || $modifier eq '-' )
|
if ( !$modifier || $modifier eq '-' )
|
||||||
{
|
{
|
||||||
addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_alarm":"start_alarm", $limit );
|
addToDeviceList( $unit_code,
|
||||||
|
"OFF",
|
||||||
|
$monitor,
|
||||||
|
!$invert ? "stop_alarm"
|
||||||
|
: "start_alarm",
|
||||||
|
$limit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,17 +552,30 @@ sub loadTasks
|
||||||
foreach my $code_string ( split( /,/, $monitor->{AlarmOutput} ) )
|
foreach my $code_string ( split( /,/, $monitor->{AlarmOutput} ) )
|
||||||
{
|
{
|
||||||
#Debug( "Code string: $code_string\n" );
|
#Debug( "Code string: $code_string\n" );
|
||||||
my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
my ( $invert, $unit_code, $modifier, $limit )
|
||||||
|
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
||||||
$limit = 0 if ( !$limit );
|
$limit = 0 if ( !$limit );
|
||||||
if ( $unit_code )
|
if ( $unit_code )
|
||||||
{
|
{
|
||||||
if ( !$modifier || $modifier eq '+' )
|
if ( !$modifier || $modifier eq '+' )
|
||||||
{
|
{
|
||||||
addToMonitorList( $monitor, "ON", $unit_code, !$invert?"on":"off", $limit );
|
addToMonitorList( $monitor,
|
||||||
|
"ON",
|
||||||
|
$unit_code,
|
||||||
|
!$invert ? "on"
|
||||||
|
: "off",
|
||||||
|
$limit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ( !$modifier || $modifier eq '-' )
|
if ( !$modifier || $modifier eq '-' )
|
||||||
{
|
{
|
||||||
addToMonitorList( $monitor, "OFF", $unit_code, !$invert?"off":"on", $limit );
|
addToMonitorList( $monitor,
|
||||||
|
"OFF",
|
||||||
|
$unit_code,
|
||||||
|
!$invert ? "off"
|
||||||
|
: "on",
|
||||||
|
$limit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,8 +610,11 @@ sub addPendingTask
|
||||||
}
|
}
|
||||||
elsif ( $task->{type} eq "monitor" )
|
elsif ( $task->{type} eq "monitor" )
|
||||||
{
|
{
|
||||||
if (( $task->{device}->{appliance}->unit_code() != $pending_task->{device}->{appliance}->unit_code() )
|
if (( $task->{device}->{appliance}->unit_code()
|
||||||
|| ( $task->{function} ne $pending_task->{function} ))
|
!= $pending_task->{device}->{appliance}->unit_code()
|
||||||
|
)
|
||||||
|
|| ( $task->{function} ne $pending_task->{function} )
|
||||||
|
)
|
||||||
{
|
{
|
||||||
push( @$new_pending_list, $pending_task )
|
push( @$new_pending_list, $pending_task )
|
||||||
}
|
}
|
||||||
|
@ -554,12 +639,18 @@ sub addPendingTask
|
||||||
my $pending_task;
|
my $pending_task;
|
||||||
if ( $task->{type} eq "device" )
|
if ( $task->{type} eq "device" )
|
||||||
{
|
{
|
||||||
$pending_task = { type=>$task->{type}, monitor=>$task->{monitor}, function=>$task->{function} };
|
$pending_task = { type=>$task->{type},
|
||||||
|
monitor=>$task->{monitor},
|
||||||
|
function=>$task->{function}
|
||||||
|
};
|
||||||
$pending_task->{function} =~ s/start/stop/;
|
$pending_task->{function} =~ s/start/stop/;
|
||||||
}
|
}
|
||||||
elsif ( $task->{type} eq "monitor" )
|
elsif ( $task->{type} eq "monitor" )
|
||||||
{
|
{
|
||||||
$pending_task = { type=>$task->{type}, device=>$task->{device}, function=>$task->{function} };
|
$pending_task = { type=>$task->{type},
|
||||||
|
device=>$task->{device},
|
||||||
|
function=>$task->{function}
|
||||||
|
};
|
||||||
$pending_task->{function} =~ s/on/off/;
|
$pending_task->{function} =~ s/on/off/;
|
||||||
}
|
}
|
||||||
push( @$pending_list, $pending_task );
|
push( @$pending_list, $pending_task );
|
||||||
|
@ -592,7 +683,11 @@ sub processTask
|
||||||
{
|
{
|
||||||
if ( $instruction eq "start" )
|
if ( $instruction eq "start" )
|
||||||
{
|
{
|
||||||
zmTriggerEventOn( $task->{monitor}, 0, main::CAUSE_STRING, $task->{address} );
|
zmTriggerEventOn( $task->{monitor},
|
||||||
|
0,
|
||||||
|
main::CAUSE_STRING,
|
||||||
|
$task->{address}
|
||||||
|
);
|
||||||
if ( $task->{limit} )
|
if ( $task->{limit} )
|
||||||
{
|
{
|
||||||
addPendingTask( $task );
|
addPendingTask( $task );
|
||||||
|
@ -661,7 +756,9 @@ sub x10listen
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device )
|
||||||
{
|
{
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' };
|
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
||||||
|
status=>'unknown'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
next if ( $event->func() !~ /(?:ON|OFF)/ );
|
next if ( $event->func() !~ /(?:ON|OFF)/ );
|
||||||
$device->{status} = $event->func();
|
$device->{status} = $event->func();
|
||||||
|
|
Loading…
Reference in New Issue