mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-20 13:26:02 +00:00
added new mode shellscript and function to use shell script calls and perl function calls
git-svn-id: https://svn.fhem.de/fhem/trunk@3067 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
d10fc25929
commit
0a6d409c83
@ -63,33 +63,139 @@ PRESENCE_Define($$)
|
||||
my @a = split("[ \t]+", $def);
|
||||
my $dev;
|
||||
|
||||
if($a[2] ne "lan-bluetooth" and not (@a == 4 or @a == 5 or @a == 6))
|
||||
|
||||
|
||||
if(defined($a[2]) and defined($a[3]) and not defined($a[7]))
|
||||
{
|
||||
if($a[2] eq "local-bluetooth")
|
||||
{
|
||||
unless($a[3] =~ /^\s*([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\s*$/)
|
||||
{
|
||||
my $msg = "given address is not a bluetooth hardware address";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg
|
||||
}
|
||||
|
||||
$hash->{MODE} = "local-bluetooth";
|
||||
$hash->{ADDRESS} = $a[3];
|
||||
$hash->{TIMEOUT_NORMAL} = (defined($a[4]) ? $a[4] : 30);
|
||||
$hash->{TIMEOUT_PRESENT} = (defined($a[5]) ? $a[5] : 30);
|
||||
|
||||
}
|
||||
elsif($a[2] eq "fritzbox")
|
||||
{
|
||||
|
||||
unless(-X "/usr/bin/ctlmgr_ctl")
|
||||
{
|
||||
my $msg = "this is not a fritzbox or you running FHEM with the AVM Beta Image. Please use the FHEM FritzBox Image from fhem.de";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
unless($< == 0)
|
||||
{
|
||||
my $msg = "FHEM is not running under root (currently ".(getpwuid($<))[0].") This check can only performed with root access to the FritzBox";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
$hash->{MODE} = "fritzbox";
|
||||
$hash->{ADDRESS} = $a[3];
|
||||
$hash->{TIMEOUT_NORMAL} = (defined($a[4]) ? $a[4] : 30);
|
||||
$hash->{TIMEOUT_PRESENT} = (defined($a[5]) ? $a[5] : 30);
|
||||
|
||||
}
|
||||
elsif($a[2] eq "lan-ping")
|
||||
{
|
||||
if(-X "/usr/bin/ctrlmgr_ctl" and not $< == 0)
|
||||
{
|
||||
my $msg = "FHEM is not running under root (currently ".(getpwuid($<))[0].") This check can only performed with root access to the FritzBox";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
$hash->{MODE} = "lan-ping";
|
||||
$hash->{ADDRESS} = $a[3];
|
||||
$hash->{TIMEOUT_NORMAL} = (defined($a[4]) ? $a[4] : 30);
|
||||
$hash->{TIMEOUT_PRESENT} = (defined($a[5]) ? $a[5] : 30);
|
||||
|
||||
}
|
||||
elsif($a[2] =~ /(shellscript|function)/)
|
||||
{
|
||||
if($def =~ /(\S+) \w+ (\S+) ["']{0,1}(.+?)['"]{0,1}\s*(\d*)\s*(\d*)$/s)
|
||||
{
|
||||
|
||||
$hash->{MODE} = $2;
|
||||
$hash->{helper}{call} = $3;
|
||||
$hash->{TIMEOUT_NORMAL} = (defined($4) ? $4 : 30);
|
||||
$hash->{TIMEOUT_PRESENT} = (defined($5) ? $5 : 30);
|
||||
|
||||
if($hash->{helper}{call} =~ /\|/)
|
||||
{
|
||||
my $msg = "The command contains a pipe ( | ) symbol, which is not allowed.";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
if($hash->{MODE} eq "function" and not $hash->{helper}{call} =~ /^\{.+\}$/)
|
||||
{
|
||||
my $msg = "The function call must be encapsulated by brackets ( {...} ).";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
elsif($a[2] eq "lan-bluetooth")
|
||||
{
|
||||
|
||||
unless($a[3] =~ /^\s*([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\s*$/)
|
||||
{
|
||||
my $msg = "given address is not a bluetooth hardware address";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg
|
||||
}
|
||||
|
||||
$hash->{MODE} = "lan-bluetooth";
|
||||
$hash->{ADDRESS} = $a[3];
|
||||
$hash->{TIMEOUT_NORMAL} = (defined($a[5]) ? $a[5] : 30);
|
||||
$hash->{TIMEOUT_PRESENT} = (defined($a[6]) ? $a[6] : 30);
|
||||
|
||||
$dev = $a[4];
|
||||
$dev .= ":5222" if($dev !~ m/:/ && $dev ne "none" && $dev !~ m/\@/);
|
||||
|
||||
$hash->{DeviceName} = $dev;
|
||||
|
||||
return DevIo_OpenDev($hash, 0, "PRESENCE_DoInit");
|
||||
}
|
||||
else
|
||||
{
|
||||
my $msg = "unknown mode: ".$a[2]." - Please use lan-ping, lan-bluetooth, local-bluetooth, fritzbox, shellscript or function";
|
||||
Log 2, $msg;
|
||||
return $msg
|
||||
}
|
||||
|
||||
DevIo_CloseDev($hash);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
my $msg = "wrong syntax: define <name> PRESENCE <mode> <device-address> [ <check-interval> [ <present-check-interval> ] ]";
|
||||
Log 2, $msg;
|
||||
return $msg;
|
||||
}
|
||||
elsif($a[2] eq "lan-bluetooth" and not (@a == 5 or @a == 6)) {
|
||||
my $msg = "wrong syntax: define <name> PRESENCE lan-bluetooth <bluetooth-device-address> <ip-address>[:port] [ <check-interval> ]";
|
||||
Log 2, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
DevIo_CloseDev($hash);
|
||||
|
||||
my $name = $a[0];
|
||||
my $destination = $a[2];
|
||||
my $address = $a[3];
|
||||
my $timeout = (defined($a[4]) ? $a[4] : 30);
|
||||
|
||||
my $presence_timeout = (defined($a[5]) ? $a[5] : $timeout);
|
||||
|
||||
$timeout = (defined($a[5]) ? $a[5] : 30) if($destination eq "lan-bluetooth");
|
||||
$presence_timeout = (defined($a[6]) ? $a[6] : 30) if($destination eq "lan-bluetooth");
|
||||
|
||||
$hash->{ADDRESS} = $address;
|
||||
$hash->{TIMEOUT_NORMAL} = $timeout;
|
||||
$hash->{TIMEOUT_PRESENT} = $presence_timeout;
|
||||
|
||||
|
||||
my $timeout = $hash->{TIMEOUT_NORMAL};
|
||||
my $presence_timeout = $hash->{TIMEOUT_PRESENCE};
|
||||
|
||||
|
||||
|
||||
|
||||
if(defined($timeout) and not $timeout =~ /^\d+$/)
|
||||
{
|
||||
@ -122,73 +228,25 @@ PRESENCE_Define($$)
|
||||
return $msg;
|
||||
}
|
||||
|
||||
if(($destination eq "local-bluetooth" or $destination eq "lan-bluetooth") and not $address =~ /^\s*([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\s*$/)
|
||||
{
|
||||
my $msg = "given address is not a bluetooth hardware address";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
if($destination eq "fritzbox" and not -X "/usr/bin/ctlmgr_ctl")
|
||||
{
|
||||
my $msg = "this is not a fritzbox or you running FHEM with the AVM Beta Image. Please use the FHEM FritzBox Image from fhem.de";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
if(-X "/usr/bin/ctlmgr_ctl" and ($destination eq "fritzbox" or $destination eq "lan-ping") and not $< == 0)
|
||||
{
|
||||
delete $hash->{helper}{cachednr} if(defined($hash->{helper}{cachednr}));
|
||||
|
||||
my $msg = "FHEM is not running under root (currently ".(getpwuid($<))[0].") This check can only performed with root access to the FritzBox";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
if($destination eq "lan-ping" or $destination eq "local-bluetooth" or $destination eq "fritzbox")
|
||||
if($hash->{MODE} =~ /(lan-ping|local-bluetooth|fritzbox|shellscript|function)/)
|
||||
{
|
||||
|
||||
$hash->{MODE} = $destination;
|
||||
|
||||
delete $hash->{helper}{cachednr} if(defined($hash->{helper}{cachednr}));
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer(gettimeofday()+2, "PRESENCE_StartLocalScan", $hash, 0) unless(exists($hash->{helper}{DISABLED}) and $hash->{helper}{DISABLED});
|
||||
InternalTimer(gettimeofday()+2, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED});
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
elsif($destination eq "lan-bluetooth")
|
||||
elsif($hash->{MODE} eq "lan-bluetooth")
|
||||
{
|
||||
$hash->{MODE} = "lan-bluetooth";
|
||||
$dev = $a[4];
|
||||
$dev .= ":5222" if($dev !~ m/:/ && $dev ne "none" && $dev !~ m/\@/);
|
||||
|
||||
|
||||
if(defined($timeout) and not $timeout =~ /^\d+$/)
|
||||
{
|
||||
my $msg = "timeout must be a number";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
|
||||
if(defined($timeout) and not $timeout > 0)
|
||||
{
|
||||
my $msg = "timeout must be greater than zero";
|
||||
Log 2, "PRESENCE: ".$msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
$hash->{DeviceName} = $dev;
|
||||
my $ret = DevIo_OpenDev($hash, 0, "PRESENCE_DoInit");
|
||||
|
||||
return $ret;
|
||||
return DevIo_OpenDev($hash, 0, "PRESENCE_DoInit");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return "unknown mode: $destination Please use lan-ping, lan-bluetooth or local-bluetooth";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -414,19 +472,29 @@ sub PRESENCE_StartLocalScan($;$)
|
||||
|
||||
$local = 0 unless(defined($local));
|
||||
|
||||
$hash->{STATE} = "active" if($hash->{STATE} eq "???");
|
||||
|
||||
|
||||
if($hash->{MODE} eq "local-bluetooth")
|
||||
{
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalBluetoothScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalBluetoothScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash->{NAME}) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
}
|
||||
elsif($hash->{MODE} eq "lan-ping")
|
||||
{
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalPingScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalPingScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash->{NAME}) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
}
|
||||
elsif($hash->{MODE} eq "fritzbox")
|
||||
{
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalFritzBoxScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local."|".AttrVal($hash->{NAME}, "fritzbox_repeater", "0"), "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalFritzBoxScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local."|".AttrVal($hash->{NAME}, "fritzbox_repeater", "0"), "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash->{NAME}) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
}
|
||||
elsif($hash->{MODE} eq "shellscript")
|
||||
{
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalShellScriptScan", $hash->{NAME}."|".$hash->{helper}{call}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash->{NAME}) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
}
|
||||
elsif($hash->{MODE} eq "function")
|
||||
{
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalFunctionScan", $hash->{NAME}."|".$hash->{helper}{call}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash->{NAME}) unless(exists($hash->{helper}{RUNNING_PID}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub
|
||||
@ -605,9 +673,88 @@ PRESENCE_DoLocalBluetoothScan($)
|
||||
return $return;
|
||||
}
|
||||
|
||||
sub
|
||||
PRESENCE_DoLocalShellScriptScan($)
|
||||
{
|
||||
|
||||
my ($string) = @_;
|
||||
my ($name, $call, $local) = split("\\|", $string);
|
||||
|
||||
my $ret;
|
||||
my $return;
|
||||
|
||||
Log GetLogLevel($name, 5), "PRESENCE_DoLocalShellScriptScan: $string";
|
||||
|
||||
$ret = qx($call);
|
||||
|
||||
chomp $ret;
|
||||
|
||||
if(not defined($ret))
|
||||
{
|
||||
$return = "$name|$local|error|scriptcall doesn't return any output";
|
||||
}
|
||||
elsif($ret eq "1")
|
||||
{
|
||||
$return = "$name|$local|present";
|
||||
}
|
||||
elsif($ret eq "0")
|
||||
{
|
||||
$return = "$name|$local|absent";
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret =~ s/\n/<<line-break>>/g;
|
||||
|
||||
$return = "$name|$local|error|unexpected script output (expected 0 or 1): $ret";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
PRESENCE_DoLocalFunctionScan($)
|
||||
{
|
||||
|
||||
my ($string) = @_;
|
||||
my ($name, $call, $local) = split("\\|", $string);
|
||||
|
||||
my $ret;
|
||||
my $return;
|
||||
|
||||
Log GetLogLevel($name, 2), "PRESENCE_DoLocalFunctionScan: $string";
|
||||
|
||||
$ret = AnalyzeCommandChain(undef, $call);
|
||||
|
||||
chomp $ret;
|
||||
|
||||
if(not defined($ret))
|
||||
{
|
||||
$return = "$name|$local|error|function call doesn't return any output";
|
||||
}
|
||||
elsif($ret eq "1")
|
||||
{
|
||||
$return = "$name|$local|present";
|
||||
}
|
||||
elsif($ret eq "0")
|
||||
{
|
||||
$return = "$name|$local|absent";
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret =~ s/\n/<<line-break>>/g;
|
||||
|
||||
$return = "$name|$local|error|unexpected function output (expected 0 or 1): $ret";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
sub
|
||||
PRESENCE_ProcessLocalScan($)
|
||||
@ -626,6 +773,7 @@ PRESENCE_ProcessLocalScan($)
|
||||
|
||||
Log GetLogLevel($hash->{NAME}, 5), "PRESENCE_ProcessLocalScan: $string";
|
||||
|
||||
|
||||
if(defined($hash->{helper}{RETRY_COUNT}))
|
||||
{
|
||||
Log GetLogLevel($hash->{NAME}, 2), "PRESENCE: ".$hash->{NAME}." returned a valid result after ".$hash->{helper}{RETRY_COUNT}." unsuccesful ".($hash->{helper}{RETRY_COUNT} > 1 ? "retries" : "retry");
|
||||
@ -655,6 +803,8 @@ PRESENCE_ProcessLocalScan($)
|
||||
}
|
||||
elsif($a[2] eq "error")
|
||||
{
|
||||
$a[3] =~ s/<<line-break>>/\n/g;
|
||||
|
||||
Log GetLogLevel($hash->{NAME}, 2), "PRESENCE: error while processing device ".$hash->{NAME}." - ".$a[3];
|
||||
}
|
||||
|
||||
@ -674,8 +824,8 @@ sub
|
||||
PRESENCE_ProcessAbortedScan($)
|
||||
{
|
||||
|
||||
my ($hash) = @_;
|
||||
|
||||
my ($name) = @_;
|
||||
my $hash = $defs{$name};
|
||||
|
||||
delete($hash->{helper}{RUNNING_PID});
|
||||
RemoveInternalTimer($hash);
|
||||
|
Loading…
x
Reference in New Issue
Block a user