diff --git a/fhem/CHANGED b/fhem/CHANGED index a64ccffe5..c00e9a49d 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,6 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. - SVN + - bugfix: PRESENCE: Fix nonworking initialization in mode "lan-bluetooth" - bugfix: fhem.pl: write-select to avoid blocking in inform/Event Monitor - bugfix: fix issue with DST changes in 57_Calendar.pm - feature: new module 36_LaCrosse.pm for LaCrosse IT+ temperature and diff --git a/fhem/FHEM/73_PRESENCE.pm b/fhem/FHEM/73_PRESENCE.pm index 56458561b..fed3fb8ab 100755 --- a/fhem/FHEM/73_PRESENCE.pm +++ b/fhem/FHEM/73_PRESENCE.pm @@ -40,18 +40,18 @@ use DevIo; sub PRESENCE_Initialize($) { - my ($hash) = @_; + my ($hash) = @_; - require "$attr{global}{modpath}/FHEM/DevIo.pm"; + require "$attr{global}{modpath}/FHEM/DevIo.pm"; -# Provider - $hash->{ReadFn} = "PRESENCE_Read"; - $hash->{ReadyFn} = "PRESENCE_Ready"; - $hash->{SetFn} = "PRESENCE_Set"; - $hash->{DefFn} = "PRESENCE_Define"; - $hash->{UndefFn} = "PRESENCE_Undef"; - $hash->{AttrFn} = "PRESENCE_Attr"; - $hash->{AttrList}= "do_not_notify:0,1 disable:0,1 fritzbox_repeater:0,1 ping_count:1,2,3,4,5,6,7,8,9,10 ".$readingFnAttributes; + # Provider + $hash->{ReadFn} = "PRESENCE_Read"; + $hash->{ReadyFn} = "PRESENCE_Ready"; + $hash->{SetFn} = "PRESENCE_Set"; + $hash->{DefFn} = "PRESENCE_Define"; + $hash->{UndefFn} = "PRESENCE_Undef"; + $hash->{AttrFn} = "PRESENCE_Attr"; + $hash->{AttrList}= "do_not_notify:0,1 disable:0,1 fritzbox_repeater:0,1 ping_count:1,2,3,4,5,6,7,8,9,10 ".$readingFnAttributes; } @@ -59,191 +59,179 @@ PRESENCE_Initialize($) sub PRESENCE_Define($$) { - my ($hash, $def) = @_; - my @a = split("[ \t]+", $def); - my $dev; + my ($hash, $def) = @_; + my @a = split("[ \t]+", $def); + my $dev; - - - if(defined($a[2]) and defined($a[3])) - { - if($a[2] eq "local-bluetooth") - { - unless($a[3] =~ /^\s*([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\s*$/) + if(defined($a[2]) and defined($a[3])) { - 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} = ($4 ne "" ? $4 : 30); - $hash->{TIMEOUT_PRESENT} = ($5 ne "" ? $5 : 30); + 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 + } - if($hash->{helper}{call} =~ /\|/) - { - my $msg = "The command contains a pipe ( | ) symbol, which is not allowed."; - 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; + } - 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; - } + $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} = ($4 ne "" ? $4 : 30); + $hash->{TIMEOUT_PRESENT} = ($5 ne "" ? $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 + } + + DevIo_CloseDev($hash); + + $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; + + } + else + { + my $msg = "unknown mode: ".$a[2]." - Please use lan-ping, lan-bluetooth, local-bluetooth, fritzbox, shellscript or function"; + Log 2, $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*$/) + else { - my $msg = "given address is not a bluetooth hardware address"; - Log 2, "PRESENCE: ".$msg; - return $msg + my $msg = "wrong syntax: define PRESENCE [ [ ] ]"; + Log 2, $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; - - } - 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 PRESENCE [ [ ] ]"; - Log 2, $msg; - return $msg; - } - - - - - - - - my $timeout = $hash->{TIMEOUT_NORMAL}; - my $presence_timeout = $hash->{TIMEOUT_PRESENCE}; - - - + my $timeout = $hash->{TIMEOUT_NORMAL}; + my $presence_timeout = $hash->{TIMEOUT_PRESENCE}; + if(defined($timeout) and not $timeout =~ /^\d+$/) { - my $msg = "check-interval must be a number"; - Log 2, "PRESENCE: ".$msg; - return $msg; + my $msg = "check-interval must be a number"; + Log 2, "PRESENCE: ".$msg; + return $msg; } if(defined($timeout) and not $timeout > 0) { - my $msg = "check-interval must be greater than zero"; - Log 2, "PRESENCE: ".$msg; - return $msg; + my $msg = "check-interval must be greater than zero"; + Log 2, "PRESENCE: ".$msg; + return $msg; } if(defined($presence_timeout) and not $presence_timeout =~ /^\d+$/) { - my $msg = "presence-check-interval must be a number"; - Log 2, "PRESENCE: ".$msg; - return $msg; + my $msg = "presence-check-interval must be a number"; + Log 2, "PRESENCE: ".$msg; + return $msg; } if(defined($presence_timeout) and not $presence_timeout > 0) { - my $msg = "presence-check-interval must be greater than zero"; - Log 2, "PRESENCE: ".$msg; - return $msg; + my $msg = "presence-check-interval must be greater than zero"; + Log 2, "PRESENCE: ".$msg; + return $msg; } - delete $hash->{helper}{cachednr} if(defined($hash->{helper}{cachednr})); + delete $hash->{helper}{cachednr} if(defined($hash->{helper}{cachednr})); - if($hash->{MODE} =~ /(lan-ping|local-bluetooth|fritzbox|shellscript|function)/) - { - - RemoveInternalTimer($hash); - InternalTimer(gettimeofday()+2, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); - - return; - - } - elsif($hash->{MODE} eq "lan-bluetooth") - { - return DevIo_OpenDev($hash, 0, "PRESENCE_DoInit"); - } + if($hash->{MODE} =~ /(lan-ping|local-bluetooth|fritzbox|shellscript|function)/) + { + + RemoveInternalTimer($hash); + InternalTimer(gettimeofday()+2, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); + + return; + + } + elsif($hash->{MODE} eq "lan-bluetooth") + { + return DevIo_OpenDev($hash, 0, "PRESENCE_DoInit"); + } } @@ -253,19 +241,18 @@ PRESENCE_Define($$) sub PRESENCE_Undef($$) { - my ($hash, $arg) = @_; - my $name = $hash->{NAME}; + my ($hash, $arg) = @_; + my $name = $hash->{NAME}; - - RemoveInternalTimer($hash); + RemoveInternalTimer($hash); - if(defined($hash->{helper}{RUNNING_PID})) - { - BlockingKill($hash->{helper}{RUNNING_PID}); - } + if(defined($hash->{helper}{RUNNING_PID})) + { + BlockingKill($hash->{helper}{RUNNING_PID}); + } - DevIo_CloseDev($hash); - return undef; + DevIo_CloseDev($hash); + return undef; } sub @@ -279,11 +266,11 @@ PRESENCE_Set($@) if($a[1] eq "statusRequest") { - if($hash->{MODE} ne "lan-bluetooth") - { - PRESENCE_StartLocalScan($hash, 1); - return ""; - } + if($hash->{MODE} ne "lan-bluetooth") + { + PRESENCE_StartLocalScan($hash, 1); + return ""; + } } else @@ -302,74 +289,77 @@ PRESENCE_Set($@) sub PRESENCE_Attr(@) { - my @a = @_; - my $hash = $defs{$a[1]}; + my @a = @_; + my $hash = $defs{$a[1]}; - if($a[0] eq "set" && $a[2] eq "disable") - { - if($a[3] eq "0") - { - - readingsSingleUpdate($hash, "state", "defined",0) if(exists($hash->{helper}{DISABLED}) and $hash->{helper}{DISABLED} == 1); - if(defined($hash->{DeviceName})) + if($a[0] eq "set" && $a[2] eq "disable") { - if(defined($hash->{FD})) + if($a[3] eq "0") + { + + readingsSingleUpdate($hash, "state", "defined",0) if(exists($hash->{helper}{DISABLED}) and $hash->{helper}{DISABLED} == 1); + + if(defined($hash->{DeviceName})) + { + if(defined($hash->{FD})) + { + PRESENCE_DoInit($hash) if(exists($hash->{helper}{DISABLED})); + $hash->{helper}{DISABLED} = 0; + } + else + { + $hash->{helper}{DISABLED} = 0; + DevIo_OpenDev($hash, 0, "PRESENCE_DoInit"); + } + } + else + { + $hash->{helper}{DISABLED} = 0; + PRESENCE_StartLocalScan($hash); + } + + $hash->{helper}{DISABLED} = 0; + } + elsif($a[3] eq "1") { - PRESENCE_DoInit($hash) if(exists($hash->{helper}{DISABLED})); - $hash->{helper}{DISABLED} = 0; + if(defined($hash->{FD})) + { + DevIo_SimpleWrite($hash, "stop\n", 0); + } + + RemoveInternalTimer($hash); + + $hash->{helper}{DISABLED} = 1; + readingsSingleUpdate($hash, "state", "disabled",1); + } + + } + elsif($a[0] eq "del" && $a[2] eq "disable") + { + + readingsSingleUpdate($hash, "state", "defined",0) if(exists($hash->{helper}{DISABLED}) and $hash->{helper}{DISABLED} == 1); + + if(defined($hash->{DeviceName})) + { + if(defined($hash->{FD})) + { + PRESENCE_DoInit($hash) if(exists($hash->{helper}{DISABLED})); + $hash->{helper}{DISABLED} = 0; + } + else + { + $hash->{helper}{DISABLED} = 0; + DevIo_OpenDev($hash, 0, "PRESENCE_DoInit"); + } } else { - $hash->{helper}{DISABLED} = 0; - DevIo_OpenDev($hash, 0, "PRESENCE_DoInit"); + $hash->{helper}{DISABLED} = 0; + PRESENCE_StartLocalScan($hash); } } - else - { - $hash->{helper}{DISABLED} = 0; - PRESENCE_StartLocalScan($hash); - } - $hash->{helper}{DISABLED} = 0; - } - elsif($a[3] eq "1") - { - if(defined($hash->{FD})) - { - DevIo_SimpleWrite($hash, "stop\n", 0); - } - - RemoveInternalTimer($hash); - - $hash->{helper}{DISABLED} = 1; - readingsSingleUpdate($hash, "state", "disabled",1); - } - - } - elsif($a[0] eq "del" && $a[2] eq "disable") - { - - readingsSingleUpdate($hash, "state", "defined",0) if(exists($hash->{helper}{DISABLED}) and $hash->{helper}{DISABLED} == 1); - if(defined($hash->{DeviceName})) - { - if(defined($hash->{FD})) - { - PRESENCE_DoInit($hash) if(exists($hash->{helper}{DISABLED})); - $hash->{helper}{DISABLED} = 0; - } - else - { - $hash->{helper}{DISABLED} = 0; - DevIo_OpenDev($hash, 0, "PRESENCE_DoInit"); - } - } - else - { - $hash->{helper}{DISABLED} = 0; - PRESENCE_StartLocalScan($hash); - } - } - return undef; + return undef; } @@ -379,61 +369,60 @@ PRESENCE_Attr(@) sub PRESENCE_Read($) { - my ($hash) = @_; + my ($hash) = @_; - my $buf = DevIo_SimpleRead($hash); - return "" if(!defined($buf)); - - chomp $buf; + my $buf = DevIo_SimpleRead($hash); + return "" if(!defined($buf)); + + chomp $buf; - readingsBeginUpdate($hash); + readingsBeginUpdate($hash); if($buf eq "absence") { - readingsBulkUpdate($hash, "state", "absent"); + readingsBulkUpdate($hash, "state", "absent"); } elsif($buf =~ /present;(.+?)$/) { - readingsBulkUpdate($hash, "state", "present"); - - if($1 =~ /^(.*);(.+)$/) - { - readingsBulkUpdate($hash, "room", $2); - readingsBulkUpdate($hash, "device_name", $1); - } - else - { - readingsBulkUpdate($hash, "device_name", $1); - } + readingsBulkUpdate($hash, "state", "present"); + if($1 =~ /^(.*);(.+)$/) + { + readingsBulkUpdate($hash, "room", $2); + readingsBulkUpdate($hash, "device_name", $1); + } + else + { + readingsBulkUpdate($hash, "device_name", $1); + } } elsif($buf eq "command accepted") { - readingsBulkUpdate($hash, "command_accepted", "yes"); + readingsBulkUpdate($hash, "command_accepted", "yes"); } elsif($buf eq "command rejected") { - readingsBulkUpdate($hash, "command_accepted", "no"); + readingsBulkUpdate($hash, "command_accepted", "no"); } elsif($buf =~ /socket_closed;(.+?)$/) { - Log3 $hash->{NAME}, 3, "PRESENCE: collectord lost connection to room $1 for device ".$hash->{NAME}; + Log3 $hash->{NAME}, 3, "PRESENCE: collectord lost connection to room $1 for device ".$hash->{NAME}; } elsif($buf =~ /socket_reconnected;(.+?)$/) { - Log3 $hash->{NAME}, 3, "PRESENCE: collectord reconnected to room $1 for device ".$hash->{NAME}; - + Log3 $hash->{NAME}, 3, "PRESENCE: collectord reconnected to room $1 for device ".$hash->{NAME}; } elsif($buf =~ /error;(.+?)$/) { - Log3 $hash->{NAME}, 3, "PRESENCE: room $1 cannot execute hcitool to check device ".$hash->{NAME}; + Log3 $hash->{NAME}, 3, "PRESENCE: room $1 cannot execute hcitool to check device ".$hash->{NAME}; } elsif($buf =~ /error$/) { - Log3 $hash->{NAME}, 3, "PRESENCE: presenced cannot execute hcitool to check device ".$hash->{NAME}; + Log3 $hash->{NAME}, 3, "PRESENCE: presenced cannot execute hcitool to check device ".$hash->{NAME}; } + readingsEndUpdate($hash, 1); } @@ -446,19 +435,25 @@ PRESENCE_DoInit($) if( not exists($hash->{helper}{DISABLED}) or (exists($hash->{helper}{DISABLED}) and $hash->{helper}{DISABLED} == 0)) { - readingsSingleUpdate($hash, "state", "active",0); - DevIo_SimpleWrite($hash, $hash->{ADDRESS}."|".$hash->{TIMEOUT_NORMAL}."\n", 0); + readingsSingleUpdate($hash, "state", "active",0); + DevIo_SimpleWrite($hash, $hash->{ADDRESS}."|".$hash->{TIMEOUT_NORMAL}."\n", 0); } + else + { + readingsSingleUpdate($hash, "state", "disabled",0); + } + + return undef; + } sub PRESENCE_Ready($) { - my ($hash) = @_; + my ($hash) = @_; - - return DevIo_OpenDev($hash, 1, "PRESENCE_DoInit") if($hash->{MODE} eq "lan-bluetooth"); + return DevIo_OpenDev($hash, 1, "PRESENCE_DoInit") if($hash->{MODE} eq "lan-bluetooth"); } @@ -479,23 +474,23 @@ sub PRESENCE_StartLocalScan($;$) 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) unless(exists($hash->{helper}{RUNNING_PID})); } elsif($hash->{MODE} eq "lan-ping") { - $hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalPingScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local."|".AttrVal($hash->{NAME}, "ping_count", "4"), "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash) unless(exists($hash->{helper}{RUNNING_PID})); + $hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalPingScan", $hash->{NAME}."|".$hash->{ADDRESS}."|".$local."|".AttrVal($hash->{NAME}, "ping_count", "4"), "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash) 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) 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) unless(exists($hash->{helper}{RUNNING_PID})); + $hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalShellScriptScan", $hash->{NAME}."|".$hash->{helper}{call}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash) 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) unless(exists($hash->{helper}{RUNNING_PID})); + $hash->{helper}{RUNNING_PID} = BlockingCall("PRESENCE_DoLocalFunctionScan", $hash->{NAME}."|".$hash->{helper}{call}."|".$local, "PRESENCE_ProcessLocalScan", 60, "PRESENCE_ProcessAbortedScan", $hash) unless(exists($hash->{helper}{RUNNING_PID})); } } @@ -514,8 +509,6 @@ PRESENCE_DoLocalPingScan($) if($^O =~ m/(Win|cygwin)/) { - - $temp = qx(ping -n $count -4 $device); chomp $temp; @@ -611,14 +604,15 @@ PRESENCE_DoLocalFritzBoxScan($) if(not $status =~ /^\s*\d+\s*$/) { - return "$name|$local|error|could not execute ctlmgr_ctl (cached)"; + return "$name|$local|error|could not execute ctlmgr_ctl (cached)"; } + return ($status == 0)? "$name|$local|absent|$number" : "$name|$local|present|$number"; ###MH - } - else - { - Log3 $name, 5, "PRESENCE ($name) - cached device name ($cached_name) does not match expected name ($device). perform a full scan"; - } + } + else + { + Log3 $name, 5, "PRESENCE ($name) - cached device name ($cached_name) does not match expected name ($device). perform a full scan"; + } } my $max = PRESENCE_ExecuteFritzBoxCMD($name, "/usr/bin/ctlmgr_ctl r landevice settings/landevice/count"); @@ -632,31 +626,30 @@ PRESENCE_DoLocalFritzBoxScan($) return "$name|$local|error|could not execute ctlmgr_ctl"; } - - my $net_device; $number = 0; while($number <= $max) { - $net_device = PRESENCE_ExecuteFritzBoxCMD($name, "/usr/bin/ctlmgr_ctl r landevice settings/landevice$number/name"); + $net_device = PRESENCE_ExecuteFritzBoxCMD($name, "/usr/bin/ctlmgr_ctl r landevice settings/landevice$number/name"); chomp $net_device; Log3 $name, 5, "PRESENCE ($name) - checking with device number $number the $check_command state ($net_device)"; - if($net_device eq $device) - { - $status = PRESENCE_ExecuteFritzBoxCMD($name, "/usr/bin/ctlmgr_ctl r landevice settings/landevice$number/$check_command"); - - chomp $status; - - Log3 $name, 5, "PRESENCE ($name) - $check_command for device number $net_device is $status"; - last; - } - $number++; - sleep 0.2; + if($net_device eq $device) + { + $status = PRESENCE_ExecuteFritzBoxCMD($name, "/usr/bin/ctlmgr_ctl r landevice settings/landevice$number/$check_command"); + + chomp $status; + + Log3 $name, 5, "PRESENCE ($name) - $check_command for device number $net_device is $status"; + last; + } + + $number++; + sleep 0.2; } return ($status == 0 ? "$name|$local|absent" : "$name|$local|present").($number <= $max ? "|$number" : ""); @@ -682,36 +675,36 @@ PRESENCE_DoLocalBluetoothScan($) { while($wait) { # check if another hcitool process is running - $ps = qx(ps ax | grep hcitool | grep -v grep); - if(not $ps =~ /^\s*$/) - { - # sleep between 1 and 5 seconds and try again - Log3 $name, 5, "PRESENCE ($name) - another hcitool command is running. waiting..."; - sleep(rand(4)+1); - } - else - { - $wait = 0; - } - } + $ps = qx(ps ax | grep hcitool | grep -v grep); + if(not $ps =~ /^\s*$/) + { + # sleep between 1 and 5 seconds and try again + Log3 $name, 5, "PRESENCE ($name) - another hcitool command is running. waiting..."; + sleep(rand(4)+1); + } + else + { + $wait = 0; + } + } - $devname = qx(hcitool name $device); + $devname = qx(hcitool name $device); - chomp($devname); - Log3 $name, 4, "PRESENCE ($name) - hcitool returned: $devname"; + chomp($devname); + Log3 $name, 4, "PRESENCE ($name) - hcitool returned: $devname"; - if(not $devname =~ /^\s*$/) - { - $return = "$name|$local|present|$devname"; - } - else - { - $return = "$name|$local|absent"; - } + if(not $devname =~ /^\s*$/) + { + $return = "$name|$local|present|$devname"; + } + else + { + $return = "$name|$local|absent"; + } } else { - $return = "$name|$local|error|no hcitool binary found. Please check that the bluez-package is properly installed"; + $return = "$name|$local|error|no hcitool binary found. Please check that the bluez-package is properly installed"; } return $return; @@ -735,21 +728,21 @@ PRESENCE_DoLocalShellScriptScan($) if(not defined($ret)) { - $return = "$name|$local|error|scriptcall doesn't return any output"; + $return = "$name|$local|error|scriptcall doesn't return any output"; } elsif($ret eq "1") { - $return = "$name|$local|present"; + $return = "$name|$local|present"; } elsif($ret eq "0") { - $return = "$name|$local|absent"; + $return = "$name|$local|absent"; } else { - $ret =~ s/\n/<>/g; + $ret =~ s/\n/<>/g; - $return = "$name|$local|error|unexpected script output (expected 0 or 1): $ret"; + $return = "$name|$local|error|unexpected script output (expected 0 or 1): $ret"; } @@ -777,21 +770,21 @@ PRESENCE_DoLocalFunctionScan($) if(not defined($ret)) { - $return = "$name|$local|error|function call doesn't return any output"; + $return = "$name|$local|error|function call doesn't return any output"; } elsif($ret eq "1") { - $return = "$name|$local|present"; + $return = "$name|$local|present"; } elsif($ret eq "0") { - $return = "$name|$local|absent"; + $return = "$name|$local|absent"; } else { - $ret =~ s/\n/<>/g; + $ret =~ s/\n/<>/g; - $return = "$name|$local|error|unexpected function output (expected 0 or 1): $ret"; + $return = "$name|$local|error|unexpected function output (expected 0 or 1): $ret"; } @@ -803,105 +796,97 @@ PRESENCE_DoLocalFunctionScan($) sub PRESENCE_ProcessLocalScan($) { - my ($string) = @_; + my ($string) = @_; - return unless(defined($string)); + return unless(defined($string)); - my @a = split("\\|",$string); - my $hash = $defs{$a[0]}; - return if($hash->{helper}{DISABLED}); + my @a = split("\\|",$string); + my $hash = $defs{$a[0]}; + + return if($hash->{helper}{DISABLED}); - - my $local = $a[1]; - - Log3 $hash->{NAME}, 5, "PRESENCE_ProcessLocalScan: $string"; + my $local = $a[1]; + Log3 $hash->{NAME}, 5, "PRESENCE_ProcessLocalScan: $string"; - if(defined($hash->{helper}{RETRY_COUNT})) - { - Log3 $hash->{NAME}, 2, "PRESENCE: ".$hash->{NAME}." returned a valid result after ".$hash->{helper}{RETRY_COUNT}." unsuccesful ".($hash->{helper}{RETRY_COUNT} > 1 ? "retries" : "retry"); - delete($hash->{helper}{RETRY_COUNT}); - } + if(defined($hash->{helper}{RETRY_COUNT})) + { + Log3 $hash->{NAME}, 2, "PRESENCE: ".$hash->{NAME}." returned a valid result after ".$hash->{helper}{RETRY_COUNT}." unsuccesful ".($hash->{helper}{RETRY_COUNT} > 1 ? "retries" : "retry"); + delete($hash->{helper}{RETRY_COUNT}); + } - if($hash->{MODE} eq "fritzbox" and defined($a[3])) - { - $hash->{helper}{cachednr} = $a[3] if(($a[2] eq "present") || ($a[2] eq "absent")); - } - elsif($hash->{MODE} eq "fritzbox" and defined($hash->{helper}{cachednr})) - { - delete($hash->{helper}{cachednr}); - } + if($hash->{MODE} eq "fritzbox" and defined($a[3])) + { + $hash->{helper}{cachednr} = $a[3] if(($a[2] eq "present") || ($a[2] eq "absent")); + } + elsif($hash->{MODE} eq "fritzbox" and defined($hash->{helper}{cachednr})) + { + delete($hash->{helper}{cachednr}); + } - readingsBeginUpdate($hash); + readingsBeginUpdate($hash); - if($a[2] eq "present") - { - readingsBulkUpdate($hash, "state", "present"); - readingsBulkUpdate($hash, "device_name", $a[3]) if(defined($a[3]) and $hash->{MODE} =~ /^(lan-bluetooth|local-bluetooth)$/ ); - } - elsif($a[2] eq "absent") - { - readingsBulkUpdate($hash, "state", "absent"); - } - elsif($a[2] eq "error") - { - $a[3] =~ s/<>/\n/g; + if($a[2] eq "present") + { + readingsBulkUpdate($hash, "state", "present"); + readingsBulkUpdate($hash, "device_name", $a[3]) if(defined($a[3]) and $hash->{MODE} =~ /^(lan-bluetooth|local-bluetooth)$/ ); + } + elsif($a[2] eq "absent") + { + readingsBulkUpdate($hash, "state", "absent"); + } + elsif($a[2] eq "error") + { + $a[3] =~ s/<>/\n/g; - Log3 $hash->{NAME}, 2, "PRESENCE: error while processing device ".$hash->{NAME}." - ".$a[3]; - } + Log3 $hash->{NAME}, 2, "PRESENCE: error while processing device ".$hash->{NAME}." - ".$a[3]; + } - readingsEndUpdate($hash, 1); + readingsEndUpdate($hash, 1); - delete($hash->{helper}{RUNNING_PID}); + delete($hash->{helper}{RUNNING_PID}); - #Schedule the next check withing $timeout if it is a regular run - unless($local) - { - RemoveInternalTimer($hash); - InternalTimer(gettimeofday()+($a[2] eq "present" ? $hash->{TIMEOUT_PRESENT} : $hash->{TIMEOUT_NORMAL}), "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); - } + #Schedule the next check withing $timeout if it is a regular run + unless($local) + { + RemoveInternalTimer($hash); + InternalTimer(gettimeofday()+($a[2] eq "present" ? $hash->{TIMEOUT_PRESENT} : $hash->{TIMEOUT_NORMAL}), "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); + } } sub PRESENCE_ProcessAbortedScan($) { - my ($hash) = @_; - + my ($hash) = @_; + + delete($hash->{helper}{RUNNING_PID}); + RemoveInternalTimer($hash); - delete($hash->{helper}{RUNNING_PID}); - RemoveInternalTimer($hash); - - if(defined($hash->{helper}{RETRY_COUNT})) - { - if($hash->{helper}{RETRY_COUNT} >= 3) - { - Log3 $hash->{NAME}, 2, "PRESENCE: ".$hash->{NAME}." could not be checked after ".$hash->{helper}{RETRY_COUNT}." ".($hash->{helper}{RETRY_COUNT} > 1 ? "retries" : "retry"). " (resuming normal operation)" if($hash->{helper}{RETRY_COUNT} == 3); - InternalTimer(gettimeofday()+10, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); - $hash->{helper}{RETRY_COUNT}++; - } - else - { - Log3 $hash->{NAME}, 2, "PRESENCE: ".$hash->{NAME}." could not be checked after ".$hash->{helper}{RETRY_COUNT}." ".($hash->{helper}{RETRY_COUNT} > 1 ? "retries" : "retry")." (retrying in 10 seconds)"; - InternalTimer(gettimeofday()+10, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); - $hash->{helper}{RETRY_COUNT}++; - } + if(defined($hash->{helper}{RETRY_COUNT})) + { + if($hash->{helper}{RETRY_COUNT} >= 3) + { + Log3 $hash->{NAME}, 2, "PRESENCE: ".$hash->{NAME}." could not be checked after ".$hash->{helper}{RETRY_COUNT}." ".($hash->{helper}{RETRY_COUNT} > 1 ? "retries" : "retry"). " (resuming normal operation)" if($hash->{helper}{RETRY_COUNT} == 3); + InternalTimer(gettimeofday()+10, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); + $hash->{helper}{RETRY_COUNT}++; + } + else + { + Log3 $hash->{NAME}, 2, "PRESENCE: ".$hash->{NAME}." could not be checked after ".$hash->{helper}{RETRY_COUNT}." ".($hash->{helper}{RETRY_COUNT} > 1 ? "retries" : "retry")." (retrying in 10 seconds)"; + InternalTimer(gettimeofday()+10, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); + $hash->{helper}{RETRY_COUNT}++; + } - } - else - { - $hash->{helper}{RETRY_COUNT} = 1; - InternalTimer(gettimeofday()+10, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); - Log 2, "PRESENCE: ".$hash->{NAME}." could not be checked (retrying in 10 seconds)" - - - } - - - - + } + else + { + $hash->{helper}{RETRY_COUNT} = 1; + InternalTimer(gettimeofday()+10, "PRESENCE_StartLocalScan", $hash, 0) unless($hash->{helper}{DISABLED}); + Log 2, "PRESENCE: ".$hash->{NAME}." could not be checked (retrying in 10 seconds)" + } } 1;