diff --git a/fhem/CHANGED b/fhem/CHANGED index dd573222e..f99992aa3 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,8 +1,9 @@ # Add changes at the top of the list. Keep it in ASCII - SVN + - feature: updateInBackground global attribute - feature: SYSSTAT: allow stateFormat - - feature: Module 70_VIERA supports now module 95_remotecontrol with own layout - for VIERA TV + - feature: Module 70_VIERA supports now module 95_remotecontrol with own + layout for VIERA TV - feature: InternalVal function added (like ReadingsVal) - feature: new module speedtest to monitor internet connection speed with speedtest-cli diff --git a/fhem/FHEM/01_FHEMWEB.pm b/fhem/FHEM/01_FHEMWEB.pm index 34f63adf2..05f39ae44 100755 --- a/fhem/FHEM/01_FHEMWEB.pm +++ b/fhem/FHEM/01_FHEMWEB.pm @@ -75,6 +75,7 @@ use vars qw(%FW_webArgs); # all arguments specified in the GET my $FW_zlib_checked; my $FW_use_zlib = 1; +my $FW_activateInform = 0; ######################### # As we are _not_ multithreaded, it is safe to use global variables. @@ -113,6 +114,7 @@ FHEMWEB_Initialize($) $hash->{DefFn} = "FW_Define"; $hash->{UndefFn} = "FW_Undef"; $hash->{NotifyFn}= "FW_SecurityCheck"; + $hash->{ActivateInformFn} = "FW_ActivateInform"; $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 webname fwcompress:0,1 ". "plotmode:gnuplot,gnuplot-scroll,SVG plotsize endPlotToday:1,0 plotfork ". @@ -554,6 +556,11 @@ FW_answerCall($) "onload=\"FW_delayedStart()\"" : ""; FW_pO "\n
"; + if($FW_activateInform) { + $FW_cmdret = $FW_activateInform = ""; + $cmd = "style eventMonitor"; + } + if($FW_cmdret) { $FW_detail = ""; $FW_room = ""; @@ -2406,7 +2413,11 @@ FW_Notify($$) # Collect multiple changes (e.g. from noties) into one message $ntfy->{INFORMBUF} .= $data; RemoveInternalTimer($ln); - InternalTimer(gettimeofday()+0.1, "FW_FlushInform", $ln, 0); + if(length($ntfy->{INFORMBUF}) > 1024) { + FW_FlushInform($ln); + } else { + InternalTimer(gettimeofday()+0.1, "FW_FlushInform", $ln, 0); + } } return undef; @@ -2674,6 +2685,12 @@ FW_dropdownFn() return undef; } +sub +FW_ActivateInform() +{ + $FW_activateInform = 1; +} + 1; =pod diff --git a/fhem/FHEM/98_backup.pm b/fhem/FHEM/98_backup.pm index c4a696bf2..d120c76e5 100644 --- a/fhem/FHEM/98_backup.pm +++ b/fhem/FHEM/98_backup.pm @@ -163,6 +163,7 @@ createArchiv($) $dateTime =~ s/ /_/g; $dateTime =~ s/(:|-)//g; + my $cmd=""; if (!defined($backupcmd)) { if (lc($symlink) eq "no") { $tarOpts = "cf"; @@ -171,10 +172,13 @@ createArchiv($) } # prevents tar's output of "Removing leading /" and return total bytes of archive - $ret = `(tar -$tarOpts - @pathname | gzip > $backupdir/FHEM-$dateTime.tar.gz) 2>&1`; + $cmd = "tar -$tarOpts - @pathname |gzip > $backupdir/FHEM-$dateTime.tar.gz"; } else { - $ret = `($backupcmd "@pathname") 2>&1`; + $ret = "$backupcmd \"@pathname\""; } + Log 2, "Backup with command: $cmd"; + $ret = `($cmd) 2>&1`; + if($ret) { chomp $ret; Log 1, "backup $ret"; diff --git a/fhem/FHEM/98_telnet.pm b/fhem/FHEM/98_telnet.pm index c80acb118..ff37aef41 100644 --- a/fhem/FHEM/98_telnet.pm +++ b/fhem/FHEM/98_telnet.pm @@ -22,6 +22,10 @@ telnet_Initialize($) $hash->{NotifyFn}= "telnet_SecurityCheck"; $hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 globalpassword password ". "allowfrom SSL connectTimeout connectInterval"; + $hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 globalpassword password ". + "allowfrom SSL connectTimeout connectInterval"; + $hash->{ActivateInformFn} = "telnet_ActivateInform"; + } ##################################### @@ -292,6 +296,15 @@ telnet_Undef($$) return TcpServer_Close($hash); } +sub +telnet_ActivateInform($) +{ + my ($cl) = @_; + my $name = $cl->{NAME}; + CommandInform($cl, "timer") if(!$inform{$name}); +} + + 1; =pod diff --git a/fhem/FHEM/98_update.pm b/fhem/FHEM/98_update.pm index 7f7beda7b..77b4b2e8d 100644 --- a/fhem/FHEM/98_update.pm +++ b/fhem/FHEM/98_update.pm @@ -27,6 +27,7 @@ use strict; use warnings; use HttpUtils; use File::Copy qw(cp mv); +use Blocking; sub CommandUpdate($$); sub update_CheckFhemRelease($$$); @@ -192,19 +193,61 @@ CommandUpdate($$) ($notice,$unconfirmed) = update_CheckNotice($BRANCH,$update,"before"); $ret .= $notice if(defined($notice)); return $ret if($unconfirmed); - $ret .= update_DoUpdate($srcdir,$BRANCH,$update,$force,$cl); - ($notice,$unconfirmed) = update_CheckNotice($BRANCH,$update,"after"); - $ret .= $notice if(defined($notice)); - my $sendStatistics = AttrVal("global","sendStatistics",undef); - if(defined($sendStatistics) && lc($sendStatistics) eq "onupdate") { - $ret .= "\n\n"; - $ret .= AnalyzeCommandChain(undef, "fheminfo send"); + + if(AttrVal("global","updateInBackground",undef)) { + CallFn($cl->{NAME}, "ActivateInformFn", $cl); + BlockingCall("update_DoUpdateInBackground", {srcdir=>$srcdir, + BRANCH=>$BRANCH, update=>$update, force=>$force,cl=>$cl}); + $ret = "Executing the update the background."; + + } else { + $ret .= update_DoUpdate($srcdir,$BRANCH,$update,$force,$cl); + ($notice,$unconfirmed) = update_CheckNotice($BRANCH,$update,"after"); + $ret .= $notice if(defined($notice)); + my $sendStatistics = AttrVal("global","sendStatistics",undef); + if(defined($sendStatistics) && lc($sendStatistics) eq "onupdate") { + $ret .= "\n\n"; + $ret .= AnalyzeCommandChain(undef, "fheminfo send"); + } } + } return $ret; } +my $inLog = 0; +sub +update_Log2Event($$) +{ + my ($level, $text) = @_; + return if($inLog || $level > $attr{global}{verbose}); + $inLog = 1; + BlockingInformParent("DoTrigger", ["global", $text, 1], 0); + BlockingInformParent("Log", [$level, $text], 0); + $inLog = 0; +} + +sub +update_DoUpdateInBackground($) +{ + my ($h) = @_; + + no warnings 'redefine'; # The main process is not affected + *Log = \&update_Log2Event; + sleep(2); # Give time for ActivateInform / FHEMWEB / JavaScript + + my $ret = update_DoUpdate($h->{srcdir}, $h->{BRANCH}, $h->{update}, + $h->{force}, $h->{cl}); + my ($notice,$unconfirmed) = + update_CheckNotice($h->{BRANCH}, $h->{update}, "after"); + $ret .= $notice if(defined($notice)); + if(lc(AttrVal("global","sendStatistics","")) eq "onupdate") { + $ret .= "\n\n"; + $ret .= AnalyzeCommandChain(undef, "fheminfo send"); + } +} + ######################################## sub update_CheckNotice($$$) diff --git a/fhem/FHEM/Blocking.pm b/fhem/FHEM/Blocking.pm index ac45b7719..4af86d151 100644 --- a/fhem/FHEM/Blocking.pm +++ b/fhem/FHEM/Blocking.pm @@ -22,6 +22,7 @@ sub BlockingKill($); sub BlockingInformParent($;$$); my $telnetDevice; +my $telnetClient; sub BlockingCall($$@) @@ -102,30 +103,36 @@ BlockingInformParent($;$$) $waitForRead = 1 if (!defined($waitForRead)); # Write the data back, calling the function - my $addr = "localhost:$defs{$telnetDevice}{PORT}"; - my $client = IO::Socket::INET->new(PeerAddr => $addr); - Log 1, "CallBlockingFn: Can't connect to $addr\n" if(!$client); - - if (defined($param)) { - $param =~ s/'/\\'/g; - $param = "'$param'" - } else { - $param = ""; + if(!$telnetClient) { + my $addr = "localhost:$defs{$telnetDevice}{PORT}"; + $telnetClient = IO::Socket::INET->new(PeerAddr => $addr); + Log 1, "CallBlockingFn: Can't connect to $addr\n" if(!$telnetClient); } - syswrite($client, "{$informFn($param)}\n"); + if(defined($param)) { + if(ref($param) eq "ARRAY") { + $param = join(",", map { $_ =~ s/'/\\'/g; "'$_'" } @{$param}); + + } else { + $param =~ s/'/\\'/g; + $param = "'$param'" + } + } else { + $param = ""; + } + + syswrite($telnetClient, "{$informFn($param)}\n"); if ($waitForRead) { - my $len = sysread($client, $ret, 4096); + my $len = sysread($telnetClient, $ret, 4096); chop($ret); $ret = undef if(!defined($len)); } - close($client) if($client); - return $ret; } +# Parent sub BlockingKill($) { @@ -148,9 +155,11 @@ BlockingKill($) } } +# Child sub BlockingExit() { + close($telnetClient) if($telnetClient); if($^O =~ m/Win/) { eval "require threads;"; diff --git a/fhem/docs/commandref_frame.html b/fhem/docs/commandref_frame.html index 2b24b5513..0637d8c1a 100644 --- a/fhem/docs/commandref_frame.html +++ b/fhem/docs/commandref_frame.html @@ -982,6 +982,13 @@ A line ending with \ will be concatenated with the next one, so long lines receiving a corresponding message.