diff --git a/fhem/CHANGED b/fhem/CHANGED index 1223a5536..ee267f85d 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # 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. + - feature: 89_FULLY: Non blocking commands, expert mode - bugfix: 73_AutoShuttersControl: little fixes in commandref - feature: 49_SSCam: trigger several number of snapshots with alternative text and send it alltogether by email diff --git a/fhem/FHEM/89_FULLY.pm b/fhem/FHEM/89_FULLY.pm index bb22d0ca9..8c38dcac6 100755 --- a/fhem/FHEM/89_FULLY.pm +++ b/fhem/FHEM/89_FULLY.pm @@ -1,11 +1,13 @@ ############################################################################## # -# 89_FULLY.pm 0.9.002 +# 89_FULLY.pm 1.0 # # $Id$ # # Control Fully browser on Android tablets from FHEM. -# Requires Fully Plus license! +# Requires Fully App Plus license! +# +# (c) 2019 by zap (zap01 t-online de) # ############################################################################## @@ -13,7 +15,6 @@ package main; use strict; use warnings; -use Blocking; use SetExtensions; # Declare functions @@ -27,18 +28,18 @@ sub FULLY_Attr ($@); sub FULLY_Detail ($@); sub FULLY_UpdateDeviceInfo ($); sub FULLY_Execute ($$$$); +sub FULLY_ExecuteNB ($$$$); +sub FULLY_ExecuteCB ($$$); sub FULLY_ScreenOff ($); sub FULLY_GetDeviceInfo ($); sub FULLY_ProcessDeviceInfo ($$); -sub FULLY_GotDeviceInfo ($); -sub FULLY_Abort ($); sub FULLY_UpdateReadings ($$); sub FULLY_Ping ($$); -my $FULLY_VERSION = "0.9.002"; +my $FULLY_VERSION = "1.0"; # Timeout for Fully requests -my $FULLY_TIMEOUT = 4; +my $FULLY_TIMEOUT = 5; # Polling interval my $FULLY_POLL_INTERVAL = 3600; @@ -51,6 +52,7 @@ my $FULLY_REQUIRED_VERSION = 1.27; my $FULLY_DEFAULT_PROT = 'http'; my $FULLY_DEFAULT_PORT = '2323'; +# Code for Fully Javascript injection. Not implemented because of problems with Tablet UI. my $FULLY_FHEM_COMMAND = qq( function SendRequest(FHEM_Address, Devicename, Command) { var Port = "8085" @@ -65,9 +67,9 @@ function SendRequest(FHEM_Address, Devicename, Command) { } ); -################################################## +###################################################################### # Initialize module -################################################## +###################################################################### sub FULLY_Initialize ($) { @@ -83,7 +85,7 @@ sub FULLY_Initialize ($) $hash->{parseParams} = 1; $hash->{AttrList} = "pingBeforeCmd:0,1,2 pollInterval requestTimeout repeatCommand:0,1,2 " . - "disable:0,1 " . + "disable:0,1 expert:0,1 waitAfterPing:0,1,2" . $readingFnAttributes; } @@ -99,7 +101,7 @@ sub FULLY_Define ($$) return "Usage: define devname [http|https]://IP_or_Hostname password [poll-interval]" if (@$a < 4); - return "FULLY: polling interval must be in range 10 - 86400" + return "FULLY: polling interval must be in range ".$FULLY_POLL_RANGE[0]."-".$FULLY_POLL_RANGE[1] if (@$a == 5 && ($$a[4] !~ /^[1-9][0-9]+$/ || $$a[4] < $FULLY_POLL_RANGE[0] || $$a[4] > $FULLY_POLL_RANGE[1])); @@ -111,6 +113,7 @@ sub FULLY_Define ($$) $hash->{prot} = $FULLY_DEFAULT_PROT; $hash->{host} = $$a[2]; } + $hash->{port} = $FULLY_DEFAULT_PORT; $hash->{version} = $FULLY_VERSION; $hash->{onForTimer} = 'off'; @@ -119,10 +122,7 @@ sub FULLY_Define ($$) Log3 $name, 1, "FULLY: [$name] Version $FULLY_VERSION Opening device ".$hash->{host}; - my $result = FULLY_GetDeviceInfo ($name); - if (!FULLY_UpdateReadings ($hash, $result)) { - Log3 $name, 2, "FULLY: [$name] Update of device info failed"; - } + FULLY_GetDeviceInfo ($name); if (@$a == 5) { $attr{$name}{'pollInterval'} = $$a[4]; @@ -147,7 +147,7 @@ sub FULLY_Attr ($@) if ($cmd eq 'set') { if ($attrname eq 'pollInterval') { - if ($attrval >= 10 && $attrval <= 86400) { + if ($attrval >= $FULLY_POLL_RANGE[0] && $attrval <= $FULLY_POLL_RANGE[1]) { my $curval = AttrVal ($name, 'pollInterval', $FULLY_POLL_INTERVAL); if ($attrval != $curval) { Log3 $name, 2, "FULLY: [$name] Polling interval set to $attrval"; @@ -161,7 +161,7 @@ sub FULLY_Attr ($@) $hash->{nextUpdate} = 'off'; } else { - return "FULLY: Polling interval must be in range 10-86400"; + return "FULLY: Polling interval must be in range ".$FULLY_POLL_RANGE[0]."-".$FULLY_POLL_RANGE[1]; } } elsif ($attrname eq 'requestTimeout') { @@ -178,37 +178,35 @@ sub FULLY_Attr ($@) return undef; } -##################################### +###################################################################### # Delete device -##################################### +###################################################################### sub FULLY_Undef ($$) { my ($hash, $arg) = @_; RemoveInternalTimer ($hash); - BlockingKill ($hash->{fully}{bc}) if (defined ($hash->{fully}{bc})); return undef; } -##################################### +###################################################################### # Shutdown FHEM -##################################### +###################################################################### sub FULLY_Shutdown ($) { my ($hash) = @_; RemoveInternalTimer ($hash); - BlockingKill ($hash->{fully}{bc}) if (defined ($hash->{fully}{bc})); return undef; } -##################################### +###################################################################### # Enhance device detail view -##################################### +###################################################################### sub FULLY_Detail ($@) { @@ -229,9 +227,9 @@ sub FULLY_Detail ($@) return $html; } -##################################### +###################################################################### # Set commands -##################################### +###################################################################### sub FULLY_Set ($@) { @@ -242,7 +240,6 @@ sub FULLY_Set ($@) "off:noArg on:noArg on-for-timer playSound restart:noArg screenOffTimer screenSaver:start,stop ". "screenSaverTimer screenSaverURL speak startURL stopSound:noArg unlock:noArg url ". "volume"; - my $response; # Fully commands without argument my %cmds = ( @@ -255,92 +252,85 @@ sub FULLY_Set ($@) "stopSound" => "stopSound" ); + my @c = (); + my @p = (); + my $disable = AttrVal ($name, 'disable', 0); return undef if ($disable); + my $expert = AttrVal ($name, 'expert', 0); + $options .= " setStringSetting setBooleanSetting" if ($expert); if (exists ($cmds{$opt})) { - $response = FULLY_Execute ($hash, $cmds{$opt}, undef, 1); + push (@c, $cmds{$opt}); } elsif ($opt eq 'on-for-timer') { my $par = shift @$a; $par = "forever" if (!defined ($par)); + if ($par eq 'forever') { - $response = FULLY_Execute ($hash, "setBooleanSetting", - { "key" => "keepScreenOn", "value" => "true" }, 1); - $response = FULLY_Execute ($hash, "screenOn", undef, 0) - if (defined ($response) && $response ne ''); + push (@c, "setBooleanSetting", "screenOn"); + push (@p, { "key" => "keepScreenOn", "value" => "true" }, undef); + RemoveInternalTimer ($hash, "FULLY_ScreenOff"); } elsif ($par eq 'off') { - $response = FULLY_Execute ($hash, "setBooleanSetting", - { "key" => "keepScreenOn", "value" => "false" }, 1); - $response = FULLY_Execute ($hash, "setStringSetting", - { "key" => "timeToScreenOffV2", "value" => "0" }, 0) - if (defined ($response) && $response ne ''); + push (@c, "setBooleanSetting", "setStringSetting"); + push (@p, { "key" => "keepScreenOn", "value" => "false" }, + { "key" => "timeToScreenOffV2", "value" => "0" }); + RemoveInternalTimer ($hash, "FULLY_ScreenOff"); } elsif ($par =~ /^[0-9]+$/) { - $response = FULLY_Execute ($hash, "setBooleanSetting", - { "key" => "keepScreenOn", "value" => "true" }, 1); - $response = FULLY_Execute ($hash, "screenOn", undef, 0) - if (defined ($response) && $response ne ''); + push (@c, "setBooleanSetting", "screenOn"); + push (@p, { "key" => "keepScreenOn", "value" => "false" }, undef); InternalTimer (gettimeofday()+$par, "FULLY_ScreenOff", $hash, 0); } else { return "Usage: set $name on-for-timer [{ Seconds | forever | off }]"; } - RemoveInternalTimer ($hash, "FULLY_ScreenOff") if ($par eq 'off' || $par eq 'forever'); - $hash->{onForTimer} = $par if (defined ($response) && $response ne ''); + $hash->{onForTimer} = $par; } elsif ($opt eq 'screenOffTimer') { my $value = shift @$a; return "Usage: set $name $opt {seconds}" if (!defined ($value)); - $response = FULLY_Execute ($hash, "setStringSetting", - { "key" => "timeToScreenOffV2", "value" => "$value" }, 1); + push (@c, "setStringSetting"); + push (@p, { "key" => "timeToScreenOffV2", "value" => "$value" }); } elsif ($opt eq 'screenSaver') { my $state = shift @$a; - return "Usage: set $name $opt { start | stop }" if (!defined ($state)); - if ($state eq 'start') { - $response = FULLY_Execute ($hash, "startScreensaver", undef, 1); - } - elsif ($state eq 'stop') { - $response = FULLY_Execute ($hash, "stopScreensaver", undef, 1); - } - else { - return "Usage: set $name $opt { start | stop }"; - } + return "Usage: set $name $opt { start | stop }" if (!defined ($state) || $state !~ /^(start|stop)$/); + push (@c, ($state eq 'start') ? "startScreensaver" : "stopScreensaver"); } elsif ($opt eq 'screenSaverTimer') { my $value = shift @$a; return "Usage: set $name $opt {seconds}" if (!defined ($value)); - $response = FULLY_Execute ($hash, "setStringSetting", - { "key" => "timeToScreensaverV2", "value" => "$value" }, 1); + push (@c, "setStringSetting"); + push (@p, { "key" => "timeToScreensaverV2", "value" => "$value" }); } elsif ($opt eq 'screenSaverURL') { my $value = shift @$a; return "Usage: set $name $opt {URL}" if (!defined ($value)); - $response = FULLY_Execute ($hash, "setStringSetting", - { "key" => "screensaverURL", "value" => "$value" }, 1); + push (@c, "setStringSetting"); + push (@p, { "key" => "screensaverURL", "value" => "$value" }); } elsif ($opt eq 'startURL') { my $value = shift @$a; return "Usage: set $name $opt {URL}" if (!defined ($value)); - $response = FULLY_Execute ($hash, "setStringSetting", - { "key" => "startURL", "value" => "$value" }, 1); + push (@c, "setStringSetting"); + push (@p, { "key" => "startURL", "value" => "$value" }); } elsif ($opt eq 'brightness') { my $value = shift @$a; return "Usage: set $name brightness 0-255" if (!defined ($value)); $value = 255 if ($value > 255); - $response = FULLY_Execute ($hash, "setStringSetting", - { "key" => "screenBrightness", "value" => "$value" }, 1); + push (@c, "setStringSetting"); + push (@p, { "key" => "screenBrightness", "value" => "$value" }); } elsif ($opt eq 'motionDetection') { my $state = shift @$a; return "Usage: set $name motionDetection { on | off }" if (!defined ($state)); my $value = $state eq 'on' ? 'true' : 'false'; - $response = FULLY_Execute ($hash, "setBooleanSetting", - { "key" => "motionDetection", "value" => "$value" }, 1); + push (@c, "setBooleanSetting"); + push (@p, { "key" => "motionDetection", "value" => "$value" }); } elsif ($opt eq 'speak') { my $text = shift @$a; @@ -351,45 +341,50 @@ sub FULLY_Set ($@) $text =~ s/\[$device:$reading\]/$value/g; } my $enctext = urlEncode ($text); - $response = FULLY_Execute ($hash, "textToSpeech", { "text" => "$enctext" }, 1); + push (@c, "textToSpeech"); + push (@p, { "text" => "$enctext" }); } elsif ($opt eq 'playSound') { my $url = shift @$a; my $loop = shift @$a; $loop = defined ($loop) ? 'true' : 'false'; return "Usage: set $name playSound {url} [loop]" if (!defined ($url)); - $response = FULLY_Execute ($hash, "playSound", - { "url" => "$url", "loop" => "$loop"}, 1); + push (@c, "playSound"); + push (@p, { "url" => "$url", "loop" => "$loop"}); } elsif ($opt eq 'volume') { my $level = shift @$a; my $stream = shift @$a; return "Usage: set $name volume {level} {stream}" if (!defined ($stream) || $level !~ /^[0-9]+$/ || $stream !~ /^[0-9]+$/); - $response = FULLY_Execute ($hash, "setAudioVolume", - { "level" => "$level", "stream" => "$stream"}, 1); + push (@c, "setAudioVolume"); + push (@p, { "level" => "$level", "stream" => "$stream"}); } elsif ($opt eq 'url') { my $url = shift @$a; - my $cmd = defined ($url) ? "loadURL" : "loadStartURL"; - $response = FULLY_Execute ($hash, $cmd, { "url" => "$url" }, 1); + push (@c, defined ($url) ? "loadURL" : "loadStartURL"); + } + elsif ($opt eq 'setStringSetting' || $opt eq 'setBooleanSetting') { + return "FULLY: Command $opt only available in expert mode" if ($expert == 0); + my $key = shift @$a; + my $value = shift @$a; + return "Usage: set $name $opt {key} {value}" if (!defined ($value)); + push (@c, $opt); + push (@p, { "key" => "$key", "value" => "$value" }); } else { return "FULLY: Unknown argument $opt, choose one of ".$options; } - my $result = FULLY_ProcessDeviceInfo ($name, $response); - if (!FULLY_UpdateReadings ($hash, $result)) { - Log3 $name, 2, "FULLY: [$name] Command failed"; - return "FULLY: Command failed"; - } + # Execute command requests + FULLY_ExecuteNB ($hash, \@c, \@p, 1) if (scalar (@c) > 0); return undef; } -##################################### +###################################################################### # Get commands -##################################### +###################################################################### sub FULLY_Get ($@) { @@ -424,22 +419,18 @@ sub FULLY_Get ($@) return "FULLY: Command not implemented"; } elsif ($opt eq 'update') { - my $result = FULLY_GetDeviceInfo ($name); - if (!FULLY_UpdateReadings ($hash, $result)) { - Log3 $name, 2, "FULLY: [$name] Command failed"; - return "FULLY: Command failed"; - } + FULLY_GetDeviceInfo ($name); } else { return "FULLY: Unknown argument $opt, choose one of ".$options; } - + return undef; } -##################################### +###################################################################### # Execute Fully command -##################################### +###################################################################### sub FULLY_Execute ($$$$) { @@ -475,54 +466,181 @@ sub FULLY_Execute ($$$$) return $response; } -##################################### +###################################################################### +# Execute Fully commands non blocking +###################################################################### + +sub FULLY_ExecuteNB ($$$$) +{ + my ($hash, $command, $param, $doping) = @_; + my $name = $hash->{NAME}; + + # Get attributes + my $timeout = AttrVal ($name, 'requestTimeout', $FULLY_TIMEOUT); + my $repeatCommand = min (AttrVal ($name, 'repeatCommand', 0), 2); + my $ping = min (AttrVal ($name, 'pingBeforeCmd', 0), 2); + + my @urllist; + my $nc = scalar (@$command); + for (my $i=0; $i<$nc; $i++) { + my $url = $hash->{prot}.'://'.$hash->{host}.':'.$hash->{port}."/?cmd=".$$command[$i]; + + if (defined ($param) && defined ($$param[$i])) { + foreach my $parname (keys %{$$param[$i]}) { + if (defined ($$param[$i]->{$parname})) { + $url .= "&$parname=".$$param[$i]->{$parname}; + } + } + } + + Log3 $name, 4, "FULLY: [$name] Pushing $url on command stack"; + push (@urllist, "$url&password=".$hash->{fully}{password}); + } + + # Ping tablet device + FULLY_Ping ($hash, $ping) if ($doping && $ping > 0); + + my $reqpar = { + url => $urllist[0], + orgurl => $urllist[0], + urllist => [@urllist], + timeout => $timeout, + method => "GET", + hash => $hash, + cmdno => 1, + cmdcnt => $nc, + repeat => $repeatCommand, + execcnt => 0, + callback => \&FULLY_ExecuteCB + }; + + Log3 $name, 4, "FULLY: [$name] Executing command ".$urllist[0]; + HttpUtils_NonblockingGet ($reqpar); +} + +###################################################################### +# Callback function for non blocking requests +###################################################################### + +sub FULLY_ExecuteCB ($$$) +{ + my ($param, $err, $data) = @_; + my $hash = $param->{hash}; + my $name = $hash->{NAME}; + + if ($err eq '') { + if ($param->{cmdno} == $param->{cmdcnt}) { + # Last request, update readings + Log3 $name, 4, "FULLY: [$name] Last command executed. Processing results"; + my $result = FULLY_ProcessDeviceInfo ($name, $data); + if (!FULLY_UpdateReadings ($hash, $result)) { + Log3 $name, 2, "FULLY: [$name] Command failed"; + } + } + else { + # Execute next request + my @urllist = @{$param->{urllist}}; + my $reqpar = { + url => $urllist[$param->{cmdno}], + orgurl => $urllist[$param->{cmdno}], + urllist => $param->{urllist}, + timeout => $param->{timeout}, + method => "GET", + hash => $hash, + cmdno => $param->{cmdno}+1, + cmdcnt => $param->{cmdcnt}, + repeat => $param->{repeat}, + execcnt => 0, + callback => \&FULLY_ExecuteCB + }; + + Log3 $name, 4, "FULLY: [$name] Executing command ".$urllist[$param->{cmdno}]; + HttpUtils_NonblockingGet ($reqpar); + } + } + else { + # Repeat failed request + if ($param->{execcnt} < $param->{repeat}) { + my $reqpar = { + url => $param->{orgurl}, + orgurl => $param->{orgurl}, + urllist => $param->{urllist}, + timeout => $param->{timeout}, + method => "GET", + hash => $hash, + cmdno => $param->{cmdno}, + cmdcnt => $param->{cmdcnt}, + repeat => $param->{repeat}, + execcnt => $param->{execcnt}+1, + callback => \&FULLY_ExecuteCB + }; + + Log3 $name, 4, "FULLY: [$name] Repeating command ".$param->{orgurl}; + HttpUtils_NonblockingGet ($reqpar); + } + else { + Log3 $name, 2, "FULLY: [$name] Error during request. $err"; + } + } +} + +###################################################################### # Timer function: Turn screen off -##################################### +###################################################################### sub FULLY_ScreenOff ($) { my ($hash) = @_; - my $response = FULLY_Execute ($hash, "setBooleanSetting", - { "key" => "keepScreenOn", "value" => "false" }, 1); - $response = FULLY_Execute ($hash, "screenOff", undef, 1) - if (defined ($response) && $response ne ''); - $hash->{onForTimer} = 'off' if (defined ($response) && $response ne ''); + my @c = ("setBooleanSetting", "screenOff"); + my @p = ({ "key" => "keepScreenOn", "value" => "false" }, undef); + FULLY_ExecuteNB ($hash, \@c, \@p, 1); + $hash->{onForTimer} = 'off'; } -##################################### +###################################################################### # Timer function: Read device info -##################################### +###################################################################### sub FULLY_UpdateDeviceInfo ($) { my ($hash) = @_; my $name = $hash->{NAME}; - my $disable = AttrVal ($name, 'disable', 0); - if (!exists ($hash->{fully}{bc}) && $disable == 0) { - $hash->{fully}{bc} = BlockingCall ("FULLY_GetDeviceInfo", $name, "FULLY_GotDeviceInfo", - 120, "FULLY_Abort", $hash); + my $disable = AttrVal ($name, 'disable', 0); + return if ($disable); + + my $pollInterval = AttrVal ($name, 'pollInterval', $FULLY_POLL_INTERVAL); + + my @c = ("deviceInfo"); + + FULLY_ExecuteNB ($hash, \@c, undef, 1); + + if ($pollInterval > 0) { + $hash->{nextUpdate} = strftime "%d.%m.%Y %H:%M:%S", localtime (time+$pollInterval); + InternalTimer (gettimeofday()+$pollInterval, "FULLY_UpdateDeviceInfo", $hash, 0); + } + else { + $hash->{nextUpdate} = "none"; } } -##################################### +###################################################################### # Get tablet device information -##################################### +###################################################################### sub FULLY_GetDeviceInfo ($) { my ($name) = @_; my $hash = $defs{$name}; - my $result = FULLY_Execute ($hash, 'deviceInfo', undef, 1); - - return FULLY_ProcessDeviceInfo ($name, $result); + my @c = ("deviceInfo"); + FULLY_ExecuteNB ($hash, \@c, undef, 1); } -##################################### +###################################################################### # Extract parameters from HTML code -##################################### +###################################################################### sub FULLY_ProcessDeviceInfo ($$) { @@ -567,72 +685,9 @@ sub FULLY_ProcessDeviceInfo ($$) return $parameters; } -##################################### -# Success function for blocking call -##################################### - -sub FULLY_GotDeviceInfo ($) -{ - my ($string) = @_; - - my ($name, $result) = split ('\|', $string, 2); - my $hash = $defs{$name}; - - my $pollInterval = AttrVal ($name, 'pollInterval', $FULLY_POLL_INTERVAL); - my $timeout = AttrVal ($name, 'requestTimeout', $FULLY_TIMEOUT); - - delete $hash->{fully}{bc} if (exists ($hash->{fully}{bc})); - - my $rc = FULLY_UpdateReadings ($hash, $string); - if (!$rc) { - Log3 $name, 2, "FULLY: [$name] Request timed out"; - if ($hash->{fully}{schedule} == 0) { - $hash->{fully}{schedule} += 1; - Log3 $name, 2, "FULLY: [$name] Rescheduling in $timeout seconds."; - $pollInterval = $timeout; - } - else { - $hash->{fully}{schedule} = 0; - } - } - - $hash->{nextUpdate} = strftime "%d.%m.%Y %H:%M:%S", localtime (time+$pollInterval); - InternalTimer (gettimeofday()+$pollInterval, "FULLY_UpdateDeviceInfo", $hash, 0) - if ($pollInterval > 0); -} - -##################################### -# Abort function for blocking call -##################################### - -sub FULLY_Abort ($) -{ - my ($hash) = @_; - my $name = $hash->{NAME}; - - my $pollInterval = AttrVal ($name, 'pollInterval', $FULLY_POLL_INTERVAL); - my $timeout = AttrVal ($name, 'requestTimeout', $FULLY_TIMEOUT); - - delete $hash->{fully}{bc} if (exists ($hash->{fully}{bc})); - - Log3 $name, 2, "FULLY: [$name] request timed out"; - if ($hash->{fully}{schedule} == 0) { - $hash->{fully}{schedule} += 1; - Log3 $name, 2, "FULLY: [$name] Rescheduling in $timeout seconds."; - $pollInterval = $timeout; - } - else { - $hash->{fully}{schedule} = 0; - } - - $hash->{nextUpdate} = strftime "%d.%m.%Y %H:%M:%S", localtime (time+$pollInterval); - InternalTimer (gettimeofday()+$pollInterval, "FULLY_UpdateDeviceInfo", $hash, 0) - if ($pollInterval > 0); -} - -##################################### +###################################################################### # Update readings -##################################### +###################################################################### sub FULLY_UpdateReadings ($$) { @@ -666,11 +721,11 @@ sub FULLY_UpdateReadings ($$) return $rc; } -##################################### +###################################################################### # Send ICMP request to tablet device # Adapted from presence module. # Thx Markus. -##################################### +###################################################################### sub FULLY_Ping ($$) { @@ -678,23 +733,26 @@ sub FULLY_Ping ($$) my $name = $hash->{NAME}; my $host = $hash->{host}; my $temp; + + my $waitAfterPing = min (AttrVal ($name, 'waitAfterPing', 0), 2); - if ($^O =~ m/(Win|cygwin)/) - { - $temp = qx(ping -n $count -4 $host); + my $os = $^O; + Log3 $name, 4, "FULLY: [$name] Sending $count ping request(s) to tablet $host. OS=$os"; + + if ($^O =~ m/(Win|cygwin)/) { + $temp = qx(ping -n $count -4 $host >nul); } - elsif ($^O =~ m/solaris/) - { - $temp = qx(ping $host $count 2>&1); + elsif ($^O =~ m/solaris/) { + $temp = qx(ping $host $count 2>&1 >/dev/null); } - else - { - $temp = qx(ping -c $count $host 2>&1); + elsif ($^O =~ m/darwin/) { + $temp = qx(ping -c $count -t 1 $host 2>&1 >/dev/null); + } + else { + $temp = qx(ping -c $count -W 1 $host 2>&1 >/dev/null); } - Log3 $name, 4, "FULLY: [$name] Ping response = $temp" if (defined ($temp)); - - sleep (1); + sleep ($waitAfterPing) if ($waitAfterPing > 0); return $temp; } @@ -710,15 +768,18 @@ sub FULLY_Ping ($$)

FULLY