From a01d30c8bdef0399379e38b86f2bca08ef3339e4 Mon Sep 17 00:00:00 2001
From: rudolfkoenig
Date: Sun, 30 Jun 2013 19:42:31 +0000
Subject: [PATCH] updateInBackground global attribute
git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@3373 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/CHANGED | 5 +--
fhem/FHEM/01_FHEMWEB.pm | 19 +++++++++-
fhem/FHEM/98_backup.pm | 8 +++--
fhem/FHEM/98_telnet.pm | 13 +++++++
fhem/FHEM/98_update.pm | 57 ++++++++++++++++++++++++++----
fhem/FHEM/Blocking.pm | 35 +++++++++++-------
fhem/docs/commandref_frame.html | 7 ++++
fhem/docs/commandref_frame_DE.html | 16 ++++++---
fhem/fhem.pl | 4 +--
fhem/www/pgm2/console.js | 12 ++++++-
10 files changed, 144 insertions(+), 32 deletions(-)
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.
+
+ updateInBackground
+ If this attribute is set to 1, the update will be executed in the
+ backgrund process. The return message is communicated via events, and
+ in telnet the inform command is activated, in FHEMWEB the Event
+ Monitor.
+
backup_before_update
diff --git a/fhem/docs/commandref_frame_DE.html b/fhem/docs/commandref_frame_DE.html
index 1768ea926..c1b07bbaa 100644
--- a/fhem/docs/commandref_frame_DE.html
+++ b/fhem/docs/commandref_frame_DE.html
@@ -1019,12 +1019,20 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.
autoload_undefined_devices
- wenn dieses Attribut gesetzt ist, werden die zu einer neu empfangenen
- Nachricht zugehörigen Module automatisch geladen. Dies erfolgt vom
- autocreate Gerät, um so automatisch ein FHEM-Gerät bei erreichen
- einer entsprechenden Nachricht zu erstellen.
+ wenn dieses Attribut gesetzt ist, werden die zu einer neu empfangenen
+ Nachricht zugehörigen Module automatisch geladen. Dies
+ erfolgt vom autocreate Gerät, um so
+ automatisch ein FHEM-Gerät bei erreichen einer entsprechenden
+ Nachricht zu erstellen.
+
+ updateInBackground
+ wenn dieses Attribut gesetzt ist, wird das update Befehl in einem
+ separaten Prozess ausgeführt, und alle Meldungen werden per Event
+ übermittelt. In der telnet Sitzung wird inform, in FHEMWEB wird
+ das Event Monitor aktiviert.
+
backup_before_update
diff --git a/fhem/fhem.pl b/fhem/fhem.pl
index 6ea5ba520..877ed68c5 100755
--- a/fhem/fhem.pl
+++ b/fhem/fhem.pl
@@ -167,6 +167,7 @@ use vars qw(%data); # Hash for user data
use vars qw($devcount); # To sort the devices
use vars qw(%defaultattr); # Default attributes, used by FHEM2FHEM
use vars qw(%addNotifyCB); # Used by event enhancers (e.g. avarage)
+use vars qw(%inform); # Used by telnet_ActivateInform
use vars qw($reread_active);
@@ -177,7 +178,6 @@ my $ipv6; # Using IPV6
my $currlogfile; # logfile, without wildcards
my $currcfgfile=""; # current config/include file
my $logopened = 0; # logfile opened or using stdout
-my %inform; # Inform hash
my $rcvdquit; # Used for quit handling in init files
my $sig_term = 0; # if set to 1, terminate (saving the state)
my %intAt; # Internal at timer hash.
@@ -207,7 +207,7 @@ $modules{Global}{AttrList} =
"autoload_undefined_devices:1,0 dupTimeout latitude longitude " .
"backupcmd backupdir backupsymlink backup_before_update " .
"exclude_from_update motd updatebranch uniqueID ".
- "sendStatistics:onUpdate,manually,never ".
+ "sendStatistics:onUpdate,manually,never updateInBackground:1,0".
"showInternalValues:1,0 ";
$modules{Global}{AttrFn} = "GlobalAttr";
diff --git a/fhem/www/pgm2/console.js b/fhem/www/pgm2/console.js
index ccf3a2459..7a491e6e4 100644
--- a/fhem/www/pgm2/console.js
+++ b/fhem/www/pgm2/console.js
@@ -1,5 +1,7 @@
var consConn;
+var isFF = (navigator.userAgent.toLowerCase().indexOf('firefox') > -1);
+
function
consUpdate()
{
@@ -15,8 +17,16 @@ consUpdate()
return;
var el = document.getElementById("console");
- if(el)
+ if(el) {
el.innerHTML="Events:
"+consConn.responseText;
+ // Scroll to bottom. FF is different from Safari/Chrome
+ var p = el.parentElement; // content div
+ if(isFF)
+ p.parentElement.parentElement.scrollTop = p.scrollHeight; // html tag
+ else
+ p.parentElement.scrollTop = p.scrollHeight; // body tag
+ console.log("P4:"+p.scrollHeight);
+ }
}
function