Merge remote-tracking branch 'origin/master' into enocean

This commit is contained in:
Marc Hoppe
2012-01-07 11:01:35 +01:00
18 changed files with 692 additions and 336 deletions

View File

@@ -1,3 +1,7 @@
- SVN
- feature: internal NotifyOrderPrefix: 98_average.pm is more straightforward
- 2011-12-31 (5.2) - 2011-12-31 (5.2)
- bugfix: applying smallscreen attributes to firefox/opera - bugfix: applying smallscreen attributes to firefox/opera
- feature: CUL_TX added (thanks to Peterp) - feature: CUL_TX added (thanks to Peterp)

View File

@@ -955,6 +955,8 @@ CUL_Attr(@)
my $name = $a[1]; my $name = $a[1];
my $hash = $defs{$name}; my $hash = $defs{$name};
$a[3] = "SlowRF" if(!$a[3] || $a[3] ne "HomeMatic");
if($a[3] eq "HomeMatic") { if($a[3] eq "HomeMatic") {
return if($hash->{initString} =~ m/Ar/); return if($hash->{initString} =~ m/Ar/);
$hash->{Clients} = $clientsHomeMatic; $hash->{Clients} = $clientsHomeMatic;

View File

@@ -155,7 +155,7 @@ FileLog_Set($@)
# #
# It will set the %data values # It will set the %data values
# min<x>, max<x>, avg<x>, cnt<x>, currdate<x>, currval<x>, sum<x> # min<x>, max<x>, avg<x>, cnt<x>, currdate<x>, currval<x>, sum<x>
# for each requested column, beggining with <x> = 1 # for each requested column, beginning with <x> = 1
sub sub
FileLog_Get($@) FileLog_Get($@)

View File

@@ -325,6 +325,10 @@ CommandUsb($$)
my $msg; my $msg;
my $dir = "/dev"; my $dir = "/dev";
if($^O =~ m/Win/) {
return "This command is not yet supported on windows";
}
require "$attr{global}{modpath}/FHEM/DevIo.pm"; require "$attr{global}{modpath}/FHEM/DevIo.pm";
foreach my $dev (sort split("\n", `ls $dir`)) { foreach my $dev (sort split("\n", `ls $dir`)) {

View File

@@ -13,6 +13,7 @@ average_Initialize($)
my ($hash) = @_; my ($hash) = @_;
$hash->{DefFn} = "average_Define"; $hash->{DefFn} = "average_Define";
$hash->{NotifyFn} = "average_Notify"; $hash->{NotifyFn} = "average_Notify";
$hash->{NotifyOrderPrefix} = "10-"; # Want to be called before the rest
$hash->{AttrList} = "disable:0,1"; $hash->{AttrList} = "disable:0,1";
} }
@@ -50,8 +51,8 @@ average_Notify($$)
my $re = $avg->{REGEXP}; my $re = $avg->{REGEXP};
my $max = int(@{$dev->{CHANGED}}); my $max = int(@{$dev->{CHANGED}});
my $tn; my $tn;
my $myIdx = $max;
my $trigger = "";
for (my $i = 0; $i < $max; $i++) { for (my $i = 0; $i < $max; $i++) {
my $s = $dev->{CHANGED}[$i]; my $s = $dev->{CHANGED}[$i];
@@ -100,7 +101,7 @@ average_Notify($$)
$r->{$cumName}{VAL} = $cum; $r->{$cumName}{VAL} = $cum;
$r->{$avgName}{VAL} = sprintf("%0.1f", $cum/$secNow); $r->{$avgName}{VAL} = sprintf("%0.1f", $cum/$secNow);
} else { } else {
$trigger .= " $avgName:".$r->{$avgName}{VAL}; $dev->{CHANGED}[$myIdx++] = "$avgName: ".$r->{$avgName}{VAL};
$r->{$cumName}{VAL} = $secNow*$val; $r->{$cumName}{VAL} = $secNow*$val;
$r->{$avgName}{VAL} = $val; $r->{$avgName}{VAL} = $val;
@@ -108,24 +109,7 @@ average_Notify($$)
$r->{$cumName}{TIME} = $r->{$avgName}{TIME} = $tn; $r->{$cumName}{TIME} = $r->{$avgName}{TIME} = $tn;
} }
} }
$addNotifyCB{"avg:$avgName:$devName"} = "average_Callback $devName $trigger"
if($trigger);
return undef; return undef;
} }
sub
average_Callback($)
{
my ($arg) = @_;
my ($dev, @list) = split(" ", $arg);
my $n = 0;
for(my $n = 0; $n < @list; $n++) {
my ($name, $value) = split(":", $list[$n]);
$defs{$dev}{CHANGED}[$n] = "$name: $value";
}
DoTrigger($dev, undef);
}
1; 1;

View File

@@ -41,6 +41,8 @@ CommandUpdatefhem($$)
my @commandchain = split(/ +/,$param); my @commandchain = split(/ +/,$param);
# Check if the first parameter is "backup" # Check if the first parameter is "backup"
if($param) {
my @commandchain = split(/ +/,$param);
if(uc($commandchain[0]) eq "BACKUP") { if(uc($commandchain[0]) eq "BACKUP") {
my $backupdir = AttrVal("global", "backupdir", "/tmp/FHEM_Backup"); my $backupdir = AttrVal("global", "backupdir", "/tmp/FHEM_Backup");
# create the backupfolder # create the backupfolder
@@ -71,6 +73,7 @@ CommandUpdatefhem($$)
$param = $commandchain[1]; $param = $commandchain[1];
} }
} }
}
# Read in the OLD filetimes.txt # Read in the OLD filetimes.txt
my %oldtime; my %oldtime;

View File

@@ -59,7 +59,7 @@ dist:
find .f -name .svn -print | xargs rm -rf find .f -name .svn -print | xargs rm -rf
find .f -name \*.orig -print | xargs rm -f find .f -name \*.orig -print | xargs rm -f
find .f -name .#\* -print | xargs rm -f find .f -name .#\* -print | xargs rm -f
find .f -type f -print |\ find .f -type f -print | grep -v Makefile |\
xargs perl -pi -e 's/=VERS=/$(VERS)/g;s/=DATE=/$(DATE)/g' xargs perl -pi -e 's/=VERS=/$(VERS)/g;s/=DATE=/$(DATE)/g'
mv .f $(DESTDIR) mv .f $(DESTDIR)
tar cf - $(DESTDIR) | gzip > $(DESTDIR).tar.gz tar cf - $(DESTDIR) | gzip > $(DESTDIR).tar.gz
@@ -77,7 +77,7 @@ deb:
find .f -name .svn -print | xargs rm -rf find .f -name .svn -print | xargs rm -rf
find .f -name \*.orig -print | xargs rm -f find .f -name \*.orig -print | xargs rm -f
find .f -name .#\* -print | xargs rm -f find .f -name .#\* -print | xargs rm -f
find .f -type f -print |\ find .f -type f -print | grep -v Makefile |\
xargs perl -pi -e 's/=VERS=/$(VERS)/g;s/=DATE=/$(DATE)/g' xargs perl -pi -e 's/=VERS=/$(VERS)/g;s/=DATE=/$(DATE)/g'
find .f -type f | xargs chmod 644 find .f -type f | xargs chmod 644
find .f -type d | xargs chmod 755 find .f -type d | xargs chmod 755
@@ -90,3 +90,6 @@ deb:
fb7390: fb7390:
cd contrib/FB7390 && ./makeimage $(DESTDIR) cd contrib/FB7390 && ./makeimage $(DESTDIR)
fb7270:
cd contrib/FB7270 && ./makeimage $(DESTDIR)

View File

@@ -3,15 +3,29 @@
# Server-Side script to check out the fhem SVN repository, and upload the # Server-Side script to check out the fhem SVN repository, and upload the
# changed files to the server # changed files to the server
$ENV{CVS_RSH}="/usr/bin/ssh";
print "\n\n";
print localtime() . "\n"; print localtime() . "\n";
chdir("/home/rudi/fhemupdate/culfw");
system("svn update .");
chdir("/home/rudi/fhemupdate/fhem"); chdir("/home/rudi/fhemupdate/fhem");
system("mkdir -p UPLOAD"); system("mkdir -p UPLOAD");
system("svn update . > /dev/null 2>&1"); system("svn update .");
die "SVN failed, exiting\n" if($?); die "SVN failed, exiting\n" if($?);
my $ndiff = `diff fhem.pl fhem.pl.txt | wc -l`;
if($ndiff != 4) { # more than the standard stuff is different
print "Modifying fhem.pl: >$ndiff<\n";
system('perl -p -e "s/=DATE=/"`date +"%Y-%m-%d"`"/;'.
's/=VERS=/"`grep ^VERS= Makefile | '.
'sed -e s/VERS=//`"+SVN/" fhem.pl > fhem.pl.txt');
}
my @filelist = ( my @filelist = (
"./fhem.pl", "./fhem.pl.txt",
"FHEM/.*.pm", "FHEM/.*.pm",
"webfrontend/pgm2/.*", "webfrontend/pgm2/.*",
"docs/commandref.html", "docs/commandref.html",
@@ -19,6 +33,7 @@ my @filelist = (
"docs/HOWTO.html", "docs/HOWTO.html",
"docs/fhem.*.png", "docs/fhem.*.png",
"docs/.*.jpg", "docs/.*.jpg",
"../culfw/Devices/CUL/.*.hex",
); );
# Read in the file timestamps # Read in the file timestamps
@@ -45,6 +60,7 @@ if(open FH, "UPLOAD/filetimes.txt") {
while(my $l = <FH>) { while(my $l = <FH>) {
chomp($l); chomp($l);
my ($ts, $fs, $file) = split(" ", $l, 3); my ($ts, $fs, $file) = split(" ", $l, 3);
$oldtime{"$file.txt"} = $ts if($file eq "fhem.pl");
$oldtime{$file} = $ts; $oldtime{$file} = $ts;
} }
close(FH); close(FH);
@@ -58,12 +74,14 @@ print FTP "put filetimes.txt\n";
print FTP "pas\n"; # Without passive only 28 files can be transferred print FTP "pas\n"; # Without passive only 28 files can be transferred
my $cnt; my $cnt;
foreach my $f (sort keys %filetime) { foreach my $f (sort keys %filetime) {
print FH "$filetime{$f} $filesize{$f} $f\n"; my $fn = $f;
$fn =~ s/.txt$// if($fn =~ m/.pl.txt$/);
print FH "$filetime{$f} $filesize{$f} $fn\n";
my $newfname = $f; my $newfname = $f;
$newfname .= ".txt" if($newfname =~ m/.pl$/); # Cant download .pl files
if(!$oldtime{$f} || $oldtime{$f} ne $filetime{$f}) { if(!$oldtime{$f} || $oldtime{$f} ne $filetime{$f}) {
print FTP "put $newfname\n"; print FTP "put $f\n";
system("cp ../$filedir{$f}/$f $newfname"); system("cp ../$filedir{$f}/$f $f");
$cnt++; $cnt++;
} }
} }

View File

@@ -505,7 +505,7 @@ A line ending with \ will be concatenated with the next one, so long lines
<br> <br>
getstate fl<br> getstate fl<br>
ack:0 actuator:2 day-temp:21.5 desired-temp:22.5 [...] measured-temp:22.9 [...] ack:0 actuator:2 day-temp:21.5 desired-temp:22.5 [...] measured-temp:22.9 [...]
<code></ul> </code></ul>
Note: to use this command copy the file contrib/getstate/99_getstate.pm into Note: to use this command copy the file contrib/getstate/99_getstate.pm into
your FHEM directory. your FHEM directory.
<br> <br>
@@ -1099,7 +1099,9 @@ A line ending with \ will be concatenated with the next one, so long lines
Specify the logfile to write. You can use "-" for Specify the logfile to write. You can use "-" for
stdout, in this case the server won't background itself.<br> stdout, in this case the server won't background itself.<br>
The logfile name can also take wildcards for easier logfile rotation, The logfile name can also take wildcards for easier logfile rotation,
see the <a href="#FileLog">FileLog</a> section. see the <a href="#FileLog">FileLog</a> section. Just apply the
<code>archivecmd / archivedir / nrarchive</code> attributes to the
<code>global</code> device as you would do for a FileLog device.
</li><br> </li><br>
<a name="modpath"></a> <a name="modpath"></a>
@@ -7654,9 +7656,10 @@ href="http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=29870">U
shell command (no enclosing " is needed), and each % in the command shell command (no enclosing " is needed), and each % in the command
will be replaced with the name of the old logfile.<br> will be replaced with the name of the old logfile.<br>
If this attribute is not set, but nrarchive and/or archivecmd is set, If this attribute is not set, but nrarchive and/or archivecmd are set,
then all superfluous logfiles will be moved to archivedir (or deleted if then nrarchive logfiles are kept while older ones are moved to
archivedir is not set).</li><br> archivedir (or deleted if archivedir is not set).
</li><br>
<li><a href="#disable">disable</a></li> <li><a href="#disable">disable</a></li>

76
fhem.pl
View File

@@ -1148,12 +1148,13 @@ CommandDefine($$)
{ {
my ($cl, $def) = @_; my ($cl, $def) = @_;
my @a = split("[ \t][ \t]*", $def, 3); my @a = split("[ \t][ \t]*", $def, 3);
my $name = $a[0];
return "Usage: define <name> <type> <type dependent arguments>" return "Usage: define <name> <type> <type dependent arguments>"
if(int(@a) < 2); if(int(@a) < 2);
return "$a[0] already defined, delete it first" if(defined($defs{$a[0]})); return "$name already defined, delete it first" if(defined($defs{$name}));
return "Invalid characters in name (not A-Za-z0-9.:_): $a[0]" return "Invalid characters in name (not A-Za-z0-9.:_): $name"
if($a[0] !~ m/^[a-z0-9.:_]*$/i); if($name !~ m/^[a-z0-9.:_]*$/i);
my $m = $a[1]; my $m = $a[1];
if(!$modules{$m}) { # Perhaps just wrong case? if(!$modules{$m}) { # Perhaps just wrong case?
@@ -1175,7 +1176,7 @@ CommandDefine($$)
my %hash; my %hash;
$hash{NAME} = $a[0]; $hash{NAME} = $name;
$hash{TYPE} = $m; $hash{TYPE} = $m;
$hash{STATE} = "???"; $hash{STATE} = "???";
$hash{DEF} = $a[2] if(int(@a) > 2); $hash{DEF} = $a[2] if(int(@a) > 2);
@@ -1183,19 +1184,24 @@ CommandDefine($$)
# If the device wants to issue initialization gets/sets, then it needs to be # If the device wants to issue initialization gets/sets, then it needs to be
# in the global hash. # in the global hash.
$defs{$a[0]} = \%hash; $defs{$name} = \%hash;
my $ret = CallFn($a[0], "DefFn", \%hash, $def); my $ret = CallFn($name, "DefFn", \%hash, $def);
if($ret) { if($ret) {
Log 1, "define: $ret"; Log 1, "define: $ret";
delete $defs{$a[0]}; # Veto delete $defs{$name}; # Veto
delete $attr{$a[0]}; delete $attr{$name};
} else { } else {
foreach my $da (sort keys (%defaultattr)) { # Default attributes foreach my $da (sort keys (%defaultattr)) { # Default attributes
CommandAttr($cl, "$a[0] $da $defaultattr{$da}"); CommandAttr($cl, "$name $da $defaultattr{$da}");
}
DoTrigger("global", "DEFINED $name");
if($modules{$m}{NotifyFn} && !$hash{NTFY_ORDER}) {
$hash{NTFY_ORDER} = ($modules{$m}{NotifyOrderPrefix} ?
$modules{$m}{NotifyOrderPrefix} : "50-") . $name;
} }
DoTrigger("global", "DEFINED $a[0]");
} }
return $ret; return $ret;
@@ -2099,8 +2105,26 @@ DoTrigger($$)
Log 5, "Triggering $dev ($max changes)"; Log 5, "Triggering $dev ($max changes)";
return "" if(defined($attr{$dev}) && defined($attr{$dev}{do_not_notify})); return "" if(defined($attr{$dev}) && defined($attr{$dev}{do_not_notify}));
################
# Log/notify modules
# If modifying a device in its own trigger, do not call the triggers from
# the inner loop.
if(!defined($defs{$dev}{INTRIGGER})) {
$defs{$dev}{INTRIGGER}=1;
my @ntfyList = sort { $defs{$a}{NTFY_ORDER} cmp $defs{$b}{NTFY_ORDER} }
grep { $defs{$_}{NTFY_ORDER} } keys %defs;
foreach my $n (@ntfyList) {
next if(!defined($defs{$n})); # Was deleted in a previous notify
Log 5, "$dev trigger: Checking $n for notify";
my $r = CallFn($n, "NotifyFn", $defs{$n}, $defs{$dev});
$ret .= $r if($r);
}
delete($defs{$dev}{INTRIGGER});
}
################ ################
# Inform # Inform
$max = int(@{$defs{$dev}{CHANGED}}); # can be enriched in the notifies
foreach my $c (keys %client) { # Do client loop first, is cheaper foreach my $c (keys %client) { # Do client loop first, is cheaper
next if(!$client{$c}{inform} || $client{$c}{inform} eq "raw"); next if(!$client{$c}{inform} || $client{$c}{inform} eq "raw");
my $tn = TimeNow(); my $tn = TimeNow();
@@ -2118,24 +2142,6 @@ DoTrigger($$)
} }
} }
################
# Log/notify modules
# If modifying a device in its own trigger, do not call the triggers from
# the inner loop.
if(!defined($defs{$dev}{INTRIGGER})) {
$defs{$dev}{INTRIGGER}=1;
foreach my $n (sort keys %defs) {
next if(!defined($defs{$n})); # Was deleted in a previous notify
if(defined($modules{$defs{$n}{TYPE}})) {
if($modules{$defs{$n}{TYPE}}{NotifyFn}) {
Log 5, "$dev trigger: Checking $n for notify";
my $r = CallFn($n, "NotifyFn", $defs{$n}, $defs{$dev});
$ret .= $r if($r);
}
}
}
delete($defs{$dev}{INTRIGGER});
}
#################### ####################
# Used by triggered perl programs to check the old value # Used by triggered perl programs to check the old value
@@ -2147,20 +2153,6 @@ DoTrigger($$)
Log 3, "NTFY return: $ret" if($ret); Log 3, "NTFY return: $ret" if($ret);
# Enhancers like avarage need this
if(!defined($defs{$dev}{InNtfyCb}) && %addNotifyCB) {
$defs{$dev}{InNtfyCb}=1;
foreach my $cb (keys %addNotifyCB) {
my ($fn, $arg) = split(" ", $addNotifyCB{$cb}, 2);
delete $addNotifyCB{$cb};
no strict "refs";
&{$fn}($arg);
use strict "refs";
}
delete($defs{$dev}{CHANGED});
delete($defs{$dev}{InNtfyCb});
}
return $ret; return $ret;
} }

View File

@@ -32,9 +32,9 @@ sub FW_textfield($$);
sub FW_updateHashes(); sub FW_updateHashes();
sub FW_zoomLink($$$); sub FW_zoomLink($$$);
sub pF($@); sub pF($@);
sub pH(@); sub FW_pH(@);
sub pHPlain(@); sub FW_pHPlain(@);
sub pO(@); sub FW_pO(@);
use vars qw($FW_dir); # moddir (./FHEM), needed by SVG use vars qw($FW_dir); # moddir (./FHEM), needed by SVG
use vars qw($FW_ME); # webname (default is fhem), needed by 97_GROUP use vars qw($FW_ME); # webname (default is fhem), needed by 97_GROUP
@@ -337,7 +337,7 @@ FW_AnswerCall($)
my $f = $1; my $f = $1;
$f =~ s,/,,g; # little bit of security $f =~ s,/,,g; # little bit of security
open(FH, "$FW_dir/$f") || return 0; open(FH, "$FW_dir/$f") || return 0;
pO join("", <FH>); FW_pO join("", <FH>);
close(FH); close(FH);
$FW_RETTYPE = "text/plain; charset=$FW_encoding" if($f !~ m/\.*html$/); $FW_RETTYPE = "text/plain; charset=$FW_encoding" if($f !~ m/\.*html$/);
return 1; return 1;
@@ -349,7 +349,7 @@ FW_AnswerCall($)
$prf = "touchpad" if(!$prf && $FW_tp); $prf = "touchpad" if(!$prf && $FW_tp);
return 0 if(!open(FH, "$FW_dir/$prf$cssName.css") && return 0 if(!open(FH, "$FW_dir/$prf$cssName.css") &&
!open(FH, "$FW_dir/$cssName.css")); !open(FH, "$FW_dir/$cssName.css"));
pO join("", <FH>); FW_pO join("", <FH>);
close(FH); close(FH);
$FW_RETTYPE = "text/css"; $FW_RETTYPE = "text/css";
return 1; return 1;
@@ -365,7 +365,7 @@ FW_AnswerCall($)
return 0 if(!$img || !open(FH, "$FW_dir/$img")); return 0 if(!$img || !open(FH, "$FW_dir/$img"));
} }
binmode (FH); # necessary for Windows binmode (FH); # necessary for Windows
pO join("", <FH>); FW_pO join("", <FH>);
close(FH); close(FH);
my @f_ext = split(/\./,$img); #kpb my @f_ext = split(/\./,$img); #kpb
$FW_RETTYPE = "image/$f_ext[-1]"; $FW_RETTYPE = "image/$f_ext[-1]";
@@ -373,7 +373,7 @@ FW_AnswerCall($)
} elsif($arg =~ m,^$FW_ME/(.*).js,) { #kpb java include } elsif($arg =~ m,^$FW_ME/(.*).js,) { #kpb java include
open(FH, "$FW_dir/$1.js") || return 0; open(FH, "$FW_dir/$1.js") || return 0;
pO join("", <FH>); FW_pO join("", <FH>);
close(FH); close(FH);
$FW_RETTYPE = "application/javascript"; $FW_RETTYPE = "application/javascript";
return 1; return 1;
@@ -412,10 +412,11 @@ FW_AnswerCall($)
$FW_tp ? "640,160" : "800,160"); $FW_tp ? "640,160" : "800,160");
$FW_reldoc = "$FW_ME/commandref.html"; $FW_reldoc = "$FW_ME/commandref.html";
$FW_cmdret = $docmd ? fC($cmd) : ""; $FW_cmdret = $docmd ? FW_fC($cmd) : "";
if($FW_inform) { # Longpoll header if($FW_inform) { # Longpoll header
$defs{$FW_cname}{inform} = $FW_room; $defs{$FW_cname}{inform} = $FW_room;
$defs{$FW_cname}{NTFY_ORDER} = $FW_cname; # else notifyfn won't be called
my $c = $defs{$FW_cname}{CD}; my $c = $defs{$FW_cname}{CD};
print $c "HTTP/1.1 200 OK\r\n", print $c "HTTP/1.1 200 OK\r\n",
"Content-Type: text/plain; charset=$FW_encoding\r\n\r\n"; "Content-Type: text/plain; charset=$FW_encoding\r\n\r\n";
@@ -424,7 +425,7 @@ FW_AnswerCall($)
if($FW_XHR) { if($FW_XHR) {
$FW_RETTYPE = "text/plain; charset=$FW_encoding"; $FW_RETTYPE = "text/plain; charset=$FW_encoding";
pO $FW_cmdret; FW_pO $FW_cmdret;
return 0; return 0;
} }
@@ -446,7 +447,7 @@ FW_AnswerCall($)
} }
$defs{$aa[0]}{currentlogfile} =~ m,([^/]*)$,; $defs{$aa[0]}{currentlogfile} =~ m,([^/]*)$,;
$aa[2] = "CURRENT" if($1 eq $aa[2]); $aa[2] = "CURRENT" if($1 eq $aa[2]);
$FW_cmdret = fC("define wl_$max weblink fileplot $aa[0]:$aa[1]:$aa[2]"); $FW_cmdret = FW_fC("define wl_$max weblink fileplot $aa[0]:$aa[1]:$aa[2]");
if(!$FW_cmdret) { if(!$FW_cmdret) {
$FW_detail = "wl_$max"; $FW_detail = "wl_$max";
FW_updateHashes(); FW_updateHashes();
@@ -455,44 +456,44 @@ FW_AnswerCall($)
my $t = AttrVal("global", "title", "Home, Sweet Home"); my $t = AttrVal("global", "title", "Home, Sweet Home");
pO '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; FW_pO '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
pO '<html xmlns="http://www.w3.org/1999/xhtml">'; FW_pO '<html xmlns="http://www.w3.org/1999/xhtml">';
pO "<head>\n<title>$t</title>"; FW_pO "<head>\n<title>$t</title>";
# Enable WebApp # Enable WebApp
if($FW_tp || $FW_ss) { if($FW_tp || $FW_ss) {
pO '<link rel="apple-touch-icon-precomposed" href="'.$FW_ME.'/fhemicon.png"/>'; FW_pO '<link rel="apple-touch-icon-precomposed" href="'.$FW_ME.'/fhemicon.png"/>';
pO '<meta name="apple-mobile-web-app-capable" content="yes"/>'; FW_pO '<meta name="apple-mobile-web-app-capable" content="yes"/>';
#pO '<meta name="viewport" content="width=device-width"/>' #FW_pO '<meta name="viewport" content="width=device-width"/>'
if($FW_ss) { if($FW_ss) {
pO '<meta name="viewport" content="width=320"/>'; FW_pO '<meta name="viewport" content="width=320"/>';
} elsif($FW_tp) { } elsif($FW_tp) {
pO '<meta name="viewport" content="width=768"/>'; FW_pO '<meta name="viewport" content="width=768"/>';
} }
} }
my $rf = AttrVal($FW_wname, "refresh", ""); my $rf = AttrVal($FW_wname, "refresh", "");
pO "<meta http-equiv=\"refresh\" content=\"$rf\">" if($rf); FW_pO "<meta http-equiv=\"refresh\" content=\"$rf\">" if($rf);
pO "<link href=\"$FW_ME/style.css\" rel=\"stylesheet\"/>"; FW_pO "<link href=\"$FW_ME/style.css\" rel=\"stylesheet\"/>";
pO "<script type=\"text/javascript\" src=\"$FW_ME/svg.js\"></script>" FW_pO "<script type=\"text/javascript\" src=\"$FW_ME/svg.js\"></script>"
if($FW_plotmode eq "SVG"); if($FW_plotmode eq "SVG");
pO "<script type=\"text/javascript\" src=\"$FW_ME/longpoll.js\"></script>" FW_pO "<script type=\"text/javascript\" src=\"$FW_ME/longpoll.js\"></script>"
if($FW_longpoll); if($FW_longpoll);
pO "</head>\n<body name=\"$t\">"; FW_pO "</head>\n<body name=\"$t\">";
if($FW_cmdret) { if($FW_cmdret) {
$FW_detail = ""; $FW_detail = "";
$FW_room = ""; $FW_room = "";
$FW_cmdret =~ s/</&lt;/g; $FW_cmdret =~ s/</&lt;/g;
$FW_cmdret =~ s/>/&gt;/g; $FW_cmdret =~ s/>/&gt;/g;
pO "<div id=\"content\">"; FW_pO "<div id=\"content\">";
$FW_cmdret = "<pre>$FW_cmdret</pre>" if($FW_cmdret =~ m/\n/); $FW_cmdret = "<pre>$FW_cmdret</pre>" if($FW_cmdret =~ m/\n/);
if($FW_ss) { if($FW_ss) {
pO "<div class=\"tiny\">$FW_cmdret</div>"; FW_pO "<div class=\"tiny\">$FW_cmdret</div>";
} else { } else {
pO $FW_cmdret; FW_pO $FW_cmdret;
} }
pO "</div>"; FW_pO "</div>";
} }
FW_roomOverview($cmd); FW_roomOverview($cmd);
@@ -500,7 +501,7 @@ FW_AnswerCall($)
FW_doDetail($FW_detail) if($FW_detail); FW_doDetail($FW_detail) if($FW_detail);
FW_showRoom() if($FW_room && !$FW_detail); FW_showRoom() if($FW_room && !$FW_detail);
FW_logWrapper($cmd) if($cmd =~ /^logwrapper/); FW_logWrapper($cmd) if($cmd =~ /^logwrapper/);
pO "</body></html>"; FW_pO "</body></html>";
return 0; return 0;
} }
@@ -584,7 +585,7 @@ FW_makeTable($$@)
my($name, $hash, $cmd) = (@_); my($name, $hash, $cmd) = (@_);
return if(!$hash || !int(keys %{$hash})); return if(!$hash || !int(keys %{$hash}));
pO "<table class=\"block wide\">"; FW_pO "<table class=\"block wide\">";
my $row = 1; my $row = 1;
foreach my $n (sort keys %{$hash}) { foreach my $n (sort keys %{$hash}) {
@@ -600,33 +601,33 @@ FW_makeTable($$@)
} else { } else {
pO "<td><div class=\"dname\">$n</div></td>"; FW_pO "<td><div class=\"dname\">$n</div></td>";
if(ref($val)) { if(ref($val)) {
my ($v, $t) = ($val->{VAL}, $val->{TIME}); my ($v, $t) = ($val->{VAL}, $val->{TIME});
if($FW_ss) { if($FW_ss) {
$t = ($t ? "<br><div class=\"tiny\">$t</div>" : ""); $t = ($t ? "<br><div class=\"tiny\">$t</div>" : "");
pO "<td><div class=\"dval\">$v$t</div></td>"; FW_pO "<td><div class=\"dval\">$v$t</div></td>";
} else { } else {
$t = "" if(!$t); $t = "" if(!$t);
pO "<td>$v</td><td>$t</td>"; FW_pO "<td>$v</td><td>$t</td>";
} }
} else { } else {
pO "<td><div class=\"dval\">$val</div></td>"; FW_pO "<td><div class=\"dval\">$val</div></td>";
} }
} }
pH "cmd.$name=$cmd $name $n&amp;detail=$name", $cmd, 1 FW_pH "cmd.$name=$cmd $name $n&amp;detail=$name", $cmd, 1
if($cmd && !$FW_ss); if($cmd && !$FW_ss);
pO "</tr>"; FW_pO "</tr>";
} }
pO "</table>"; FW_pO "</table>";
pO "<br>"; FW_pO "<br>";
} }
@@ -638,13 +639,13 @@ FW_makeSelect($$$)
return if(!$list || $FW_hiddenroom{input}); return if(!$list || $FW_hiddenroom{input});
my @al = map { s/[:;].*//;$_ } split(" ", $list); my @al = map { s/[:;].*//;$_ } split(" ", $list);
pO "<form method=\"get\" action=\"$FW_ME\">"; FW_pO "<form method=\"get\" action=\"$FW_ME\">";
pO FW_hidden("detail", $d); FW_pO FW_hidden("detail", $d);
pO FW_hidden("dev.$cmd$d", $d); FW_pO FW_hidden("dev.$cmd$d", $d);
pO FW_submit("cmd.$cmd$d", $cmd) . "&nbsp;$d"; FW_pO FW_submit("cmd.$cmd$d", $cmd) . "&nbsp;$d";
pO FW_select("arg.$cmd$d",\@al,undef); FW_pO FW_select("arg.$cmd$d",\@al,undef);
pO FW_textfield("val.$cmd$d", 30); FW_pO FW_textfield("val.$cmd$d", 30);
pO "</form>"; FW_pO "</form>";
} }
@@ -654,35 +655,35 @@ FW_doDetail($)
{ {
my ($d) = @_; my ($d) = @_;
pO "<form method=\"get\" action=\"$FW_ME\">"; FW_pO "<form method=\"get\" action=\"$FW_ME\">";
pO FW_hidden("detail", $d); FW_pO FW_hidden("detail", $d);
my $t = $defs{$d}{TYPE}; my $t = $defs{$d}{TYPE};
pO "<div id=\"content\">"; FW_pO "<div id=\"content\">";
pO "<table><tr><td>"; FW_pO "<table><tr><td>";
FW_makeSelect($d, "set", getAllSets($d)); FW_makeSelect($d, "set", getAllSets($d));
FW_makeTable($d, $defs{$d}); FW_makeTable($d, $defs{$d});
pO "Readings" if($defs{$d}{READINGS}); FW_pO "Readings" if($defs{$d}{READINGS});
FW_makeTable($d, $defs{$d}{READINGS}); FW_makeTable($d, $defs{$d}{READINGS});
FW_makeSelect($d, "attr", getAllAttr($d)); FW_makeSelect($d, "attr", getAllAttr($d));
FW_makeTable($d, $attr{$d}, "deleteattr"); FW_makeTable($d, $attr{$d}, "deleteattr");
if($t eq "FileLog" ) { if($t eq "FileLog" ) {
pO "<table class=\"block wide\">"; FW_pO "<table class=\"block wide\">";
FW_dumpFileLog($d, 0, 1); FW_dumpFileLog($d, 0, 1);
pO "</table>"; FW_pO "</table>";
} }
pO "</td></tr></table>"; FW_pO "</td></tr></table>";
FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}, 1) if($t eq "weblink"); FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}, 1) if($t eq "weblink");
pO "<br><br>"; FW_pO "<br><br>";
pH "$FW_reldoc#${t}", "Device specific help"; FW_pH "$FW_reldoc#${t}", "Device specific help";
pO "<br><br>"; FW_pO "<br><br>";
pO "</div>"; FW_pO "</div>";
pO "</form>"; FW_pO "</form>";
} }
@@ -705,30 +706,30 @@ FW_roomOverview($)
$FW_room = AttrVal($FW_detail, "room", undef); $FW_room = AttrVal($FW_detail, "room", undef);
$FW_room = $1 if($FW_room && $FW_room =~ m/^([^,]*),/); $FW_room = $1 if($FW_room && $FW_room =~ m/^([^,]*),/);
$FW_room = "" if(!$FW_room); $FW_room = "" if(!$FW_room);
pHPlain "room=$FW_room", FW_pHPlain "room=$FW_room",
"<div id=\"back\"><img src=\"$FW_ME/back.png\"></div>"; "<div id=\"back\"><img src=\"$FW_ME/back.png\"></div>";
pO "<div id=\"menu\">$FW_detail details</div>"; FW_pO "<div id=\"menu\">$FW_detail details</div>";
return; return;
} else { } else {
pO "<div id=\"logo\"></div>"; FW_pO "<div id=\"logo\"></div>";
} }
############## ##############
# HEADER # HEADER
pO "<div id=\"hdr\">"; FW_pO "<div id=\"hdr\">";
pO '<table border="0"><tr><td style="padding:0">'; FW_pO '<table border="0"><tr><td style="padding:0">';
pO "<form method=\"get\" action=\"$FW_ME\">"; FW_pO "<form method=\"get\" action=\"$FW_ME\">";
pO FW_hidden("room", "$FW_room") if($FW_room); FW_pO FW_hidden("room", "$FW_room") if($FW_room);
pO FW_textfield("cmd", $FW_ss ? 25 : 40); FW_pO FW_textfield("cmd", $FW_ss ? 25 : 40);
if(!$FW_ss && !$FW_hiddenroom{save}) { if(!$FW_ss && !$FW_hiddenroom{save}) {
pO "</form></td><td><form>" . FW_submit("cmd", "save"); FW_pO "</form></td><td><form>" . FW_submit("cmd", "save");
} }
pO "</form>"; FW_pO "</form>";
pO "</td></tr></table>"; FW_pO "</td></tr></table>";
pO "</div>"; FW_pO "</div>";
############## ##############
# MENU # MENU
@@ -776,46 +777,46 @@ FW_roomOverview($)
} }
pO "<div id=\"menu\">"; FW_pO "<div id=\"menu\">";
pO "<table>"; FW_pO "<table>";
if($FW_ss) { # Make a selection sensitive dropdown list if($FW_ss) { # Make a selection sensitive dropdown list
pO "<tr><td><select OnChange=\"location.href=" . FW_pO "<tr><td><select OnChange=\"location.href=" .
"this.options[this.selectedIndex].value\">"; "this.options[this.selectedIndex].value\">";
foreach(my $idx = 0; $idx < @list1; $idx++) { foreach(my $idx = 0; $idx < @list1; $idx++) {
next if(!$list1[$idx]); next if(!$list1[$idx]);
my $sel = ($list1[$idx] eq $FW_room ? " selected=\"selected\"" : ""); my $sel = ($list1[$idx] eq $FW_room ? " selected=\"selected\"" : "");
pO "<option value=$list2[$idx]$sel>$list1[$idx]</option>"; FW_pO "<option value=$list2[$idx]$sel>$list1[$idx]</option>";
} }
pO "</select></td>"; FW_pO "</select></td>";
if(!$FW_hiddenroom{save}) { if(!$FW_hiddenroom{save}) {
pO "<td><form method=\"get\" action=\"$FW_ME\">" . FW_pO "<td><form method=\"get\" action=\"$FW_ME\">" .
FW_submit("cmd", "save"). FW_submit("cmd", "save").
"</form></td>"; "</form></td>";
} }
pO "</tr>"; FW_pO "</tr>";
} else { } else {
foreach(my $idx = 0; $idx < @list1; $idx++) { foreach(my $idx = 0; $idx < @list1; $idx++) {
my ($l1, $l2) = ($list1[$idx], $list2[$idx]); my ($l1, $l2) = ($list1[$idx], $list2[$idx]);
if(!$l1) { if(!$l1) {
pO "</table></td></tr>" if($idx); FW_pO "</table></td></tr>" if($idx);
pO "<tr><td><table id=\"room\">" FW_pO "<tr><td><table id=\"room\">"
if($idx<int(@list1)-1); if($idx<int(@list1)-1);
} else { } else {
pF "<tr%s>", $l1 eq $FW_room ? " class=\"sel\"" : ""; pF "<tr%s>", $l1 eq $FW_room ? " class=\"sel\"" : "";
if($l2 =~ m/.html$/ || $l2 =~ m/^http/) { if($l2 =~ m/.html$/ || $l2 =~ m/^http/) {
pO "<td><a href=\"$l2\">$l1</a></td>"; FW_pO "<td><a href=\"$l2\">$l1</a></td>";
} else { } else {
pH $l2, $l1, 1; FW_pH $l2, $l1, 1;
} }
pO "</tr>"; FW_pO "</tr>";
} }
} }
} }
pO "</table>"; FW_pO "</table>";
pO "</div>"; FW_pO "</div>";
} }
@@ -829,9 +830,9 @@ FW_showRoom()
# (re-) list the icons # (re-) list the icons
FW_ReadIcons(); FW_ReadIcons();
pO "<form method=\"get\" action=\"$FW_ME\">"; FW_pO "<form method=\"get\" action=\"$FW_ME\">";
pO "<div id=\"content\">"; FW_pO "<div id=\"content\">";
pO "<table>"; # Need for equal width of subtables FW_pO "<table>"; # Need for equal width of subtables
my $rf = ($FW_room ? "&amp;room=$FW_room" : ""); # stay in the room my $rf = ($FW_room ? "&amp;room=$FW_room" : ""); # stay in the room
@@ -847,9 +848,9 @@ FW_showRoom()
!IsIgnored($_) } keys %{$FW_types{$type}}; !IsIgnored($_) } keys %{$FW_types{$type}};
next if(!@devs); next if(!@devs);
pO "\n<tr><td><div class=\"devType\">$type</div></td></tr>"; FW_pO "\n<tr><td><div class=\"devType\">$type</div></td></tr>";
pO "<tr><td>"; FW_pO "<tr><td>";
pO "<table class=\"block wide\" id=\"$type\">"; FW_pO "<table class=\"block wide\" id=\"$type\">";
foreach my $d (sort @devs) { foreach my $d (sort @devs) {
my $type = $defs{$d}{TYPE}; my $type = $defs{$d}{TYPE};
@@ -857,23 +858,23 @@ FW_showRoom()
pF "\n<tr class=\"%s\">", ($row&1)?"odd":"even"; pF "\n<tr class=\"%s\">", ($row&1)?"odd":"even";
my $devName = AttrVal($d, "alias", $d); my $devName = AttrVal($d, "alias", $d);
if($FW_hiddenroom{detail}) { if($FW_hiddenroom{detail}) {
pO "<td><div class=\"col1\">$devName</div></td>"; FW_pO "<td><div class=\"col1\">$devName</div></td>";
} else { } else {
pH "detail=$d", $devName, 1, "col1"; FW_pH "detail=$d", $devName, 1, "col1";
} }
$row++; $row++;
my ($allSets, $cmdlist, $txt) = FW_devState($d, $rf); my ($allSets, $cmdlist, $txt) = FW_devState($d, $rf);
pO "<td id=\"$d\">$txt"; FW_pO "<td id=\"$d\">$txt";
if(!$FW_ss) { if(!$FW_ss) {
pO "</td>"; FW_pO "</td>";
if($cmdlist) { if($cmdlist) {
foreach my $cmd (split(":", $cmdlist)) { foreach my $cmd (split(":", $cmdlist)) {
pH "cmd.$d=set $d $cmd$rf", ReplaceEventMap($d,$cmd,1), 1, "col3"; FW_pH "cmd.$d=set $d $cmd$rf", ReplaceEventMap($d,$cmd,1), 1, "col3";
} }
} elsif($allSets =~ m/ desired-temp /) { } elsif($allSets =~ m/ desired-temp /) {
@@ -884,7 +885,7 @@ FW_showRoom()
shift(@tv); # 5.0 is not valid shift(@tv); # 5.0 is not valid
$txt = int($txt*20)/$txt if($txt =~ m/^[0-9].$/); $txt = int($txt*20)/$txt if($txt =~ m/^[0-9].$/);
pO "<td>". FW_pO "<td>".
FW_hidden("arg.$d", "desired-temp") . FW_hidden("arg.$d", "desired-temp") .
FW_hidden("dev.$d", $d) . FW_hidden("dev.$d", $d) .
FW_select("val.$d", \@tv, ReadingsVal($d, "desired-temp", $txt)) . FW_select("val.$d", \@tv, ReadingsVal($d, "desired-temp", $txt)) .
@@ -896,12 +897,12 @@ FW_showRoom()
} }
} }
pO "</td>"; FW_pO "</td>";
} }
pO "</table>"; FW_pO "</table>";
pO "</td></tr>"; FW_pO "</td></tr>";
} }
pO "</table><br>"; FW_pO "</table><br>";
# Now the weblinks # Now the weblinks
my $buttons = 1; my $buttons = 1;
@@ -913,8 +914,8 @@ FW_showRoom()
$buttons = FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}, $buttons); $buttons = FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}, $buttons);
} }
pO "</div>"; FW_pO "</div>";
pO "</form>"; FW_pO "</form>";
} }
################# #################
@@ -952,7 +953,7 @@ FW_logWrapper($)
$path = AttrVal($d,"archivedir","") . "/$file" if(!-f $path); $path = AttrVal($d,"archivedir","") . "/$file" if(!-f $path);
if(!open(FH, $path)) { if(!open(FH, $path)) {
pO "<div id=\"content\">$path: $!</div>"; FW_pO "<div id=\"content\">$path: $!</div>";
return; return;
} }
binmode (FH); # necessary for Windows binmode (FH); # necessary for Windows
@@ -961,37 +962,37 @@ FW_logWrapper($)
$cnt =~ s/</&lt;/g; $cnt =~ s/</&lt;/g;
$cnt =~ s/>/&gt;/g; $cnt =~ s/>/&gt;/g;
pO "<div id=\"content\">"; FW_pO "<div id=\"content\">";
pO "<div class=\"tiny\">" if($FW_ss); FW_pO "<div class=\"tiny\">" if($FW_ss);
pO "<pre>$cnt</pre>"; FW_pO "<pre>$cnt</pre>";
pO "</div>" if($FW_ss); FW_pO "</div>" if($FW_ss);
pO "</div>"; FW_pO "</div>";
} else { } else {
pO "<div id=\"content\">"; FW_pO "<div id=\"content\">";
pO "<br>"; FW_pO "<br>";
FW_zoomLink("cmd=$cmd;zoom=-1", "Zoom-in.png", "zoom in"); FW_zoomLink("cmd=$cmd;zoom=-1", "Zoom-in.png", "zoom in");
FW_zoomLink("cmd=$cmd;zoom=1", "Zoom-out.png","zoom out"); FW_zoomLink("cmd=$cmd;zoom=1", "Zoom-out.png","zoom out");
FW_zoomLink("cmd=$cmd;off=-1", "Prev.png", "prev"); FW_zoomLink("cmd=$cmd;off=-1", "Prev.png", "prev");
FW_zoomLink("cmd=$cmd;off=1", "Next.png", "next"); FW_zoomLink("cmd=$cmd;off=1", "Next.png", "next");
pO "<table><tr><td>"; FW_pO "<table><tr><td>";
pO "<td>"; FW_pO "<td>";
my $wl = "&amp;pos=" . join(";", map {"$_=$FW_pos{$_}"} keys %FW_pos); my $wl = "&amp;pos=" . join(";", map {"$_=$FW_pos{$_}"} keys %FW_pos);
my $arg = "$FW_ME?cmd=showlog undef $d $type $file$wl"; my $arg = "$FW_ME?cmd=showlog undef $d $type $file$wl";
if(AttrVal($d,"plotmode",$FW_plotmode) eq "SVG") { if(AttrVal($d,"plotmode",$FW_plotmode) eq "SVG") {
my ($w, $h) = split(",", AttrVal($d,"plotsize",$FW_plotsize)); my ($w, $h) = split(",", AttrVal($d,"plotsize",$FW_plotsize));
pO "<embed src=\"$arg\" type=\"image/svg+xml\" " . FW_pO "<embed src=\"$arg\" type=\"image/svg+xml\" " .
"width=\"$w\" height=\"$h\" name=\"$d\"/>\n"; "width=\"$w\" height=\"$h\" name=\"$d\"/>\n";
} else { } else {
pO "<img src=\"$arg\"/>"; FW_pO "<img src=\"$arg\"/>";
} }
pO "<br>"; FW_pO "<br>";
pH "cmd=toweblink $d:$type:$file", "Convert to weblink"; FW_pH "cmd=toweblink $d:$type:$file", "Convert to weblink";
pO "</td>"; FW_pO "</td>";
pO "</td></tr></table>"; FW_pO "</td></tr></table>";
pO "</div>"; FW_pO "</div>";
} }
} }
@@ -1031,7 +1032,11 @@ FW_substcfg($$$$$$)
my $oll = $attr{global}{verbose}; my $oll = $attr{global}{verbose};
$attr{global}{verbose} = 0; # Else the filenames will be Log'ged $attr{global}{verbose} = 0; # Else the filenames will be Log'ged
my $title = AttrVal($wl, "title", "\"$file\"");
my $fileesc = $file;
$fileesc =~ s/\\/\\\\/g; # For Windows, by MarkusRR
my $title = AttrVal($wl, "title", "\"$fileesc\"");
$title = AnalyzeCommand(undef, "{ $title }"); $title = AnalyzeCommand(undef, "{ $title }");
my $label = AttrVal($wl, "label", undef); my $label = AttrVal($wl, "label", undef);
my @g_label; my @g_label;
@@ -1091,9 +1096,9 @@ FW_showLog($)
if($pm =~ m/SVG/) { # FW_fatal for SVG: if($pm =~ m/SVG/) { # FW_fatal for SVG:
$FW_RETTYPE = "image/svg+xml"; $FW_RETTYPE = "image/svg+xml";
pO '<svg xmlns="http://www.w3.org/2000/svg">'; FW_pO '<svg xmlns="http://www.w3.org/2000/svg">';
pO '<text x="20" y="20">'.$msg.'</text>'; FW_pO '<text x="20" y="20">'.$msg.'</text>';
pO '</svg>'; FW_pO '</svg>';
return; return;
} else { } else {
@@ -1142,7 +1147,7 @@ FW_showLog($)
my ($f,$t)=($FW_devs{$d}{from}, $FW_devs{$d}{to}); my ($f,$t)=($FW_devs{$d}{from}, $FW_devs{$d}{to});
my $oll = $attr{global}{verbose}; my $oll = $attr{global}{verbose};
$attr{global}{verbose} = 0; # Else the filenames will be Log'ged $attr{global}{verbose} = 0; # Else the filenames will be Log'ged
my @path = split(" ", fC("get $d $file $tmpfile $f $t " . my @path = split(" ", FW_fC("get $d $file $tmpfile $f $t " .
join(" ", @{$flog}))); join(" ", @{$flog})));
$attr{global}{verbose} = $oll; $attr{global}{verbose} = $oll;
@@ -1170,7 +1175,7 @@ FW_showLog($)
$FW_RETTYPE = "image/png"; $FW_RETTYPE = "image/png";
open(FH, "$tmpfile.png"); # read in the result and send it open(FH, "$tmpfile.png"); # read in the result and send it
binmode (FH); # necessary for Windows binmode (FH); # necessary for Windows
pO join("", <FH>); FW_pO join("", <FH>);
close(FH); close(FH);
unlink("$tmpfile.png"); unlink("$tmpfile.png");
@@ -1188,7 +1193,7 @@ FW_showLog($)
$ret = CommandReload(undef, "98_SVG"); $ret = CommandReload(undef, "98_SVG");
Log 0, $ret if($ret); Log 0, $ret if($ret);
} }
$ret = fC("get $d $file INT $f $t " . join(" ", @{$flog})); $ret = FW_fC("get $d $file INT $f $t " . join(" ", @{$flog}));
($cfg, $plot) = FW_substcfg(1, $wl, $cfg, $plot, $file, "<OuT>"); ($cfg, $plot) = FW_substcfg(1, $wl, $cfg, $plot, $file, "<OuT>");
SVG_render($wl, $f, $t, $cfg, $internal_data, $plot, $FW_wname); SVG_render($wl, $f, $t, $cfg, $internal_data, $plot, $FW_wname);
$FW_RETTYPE = "image/svg+xml"; $FW_RETTYPE = "image/svg+xml";
@@ -1202,7 +1207,7 @@ sub
FW_fatal($) FW_fatal($)
{ {
my ($msg) = @_; my ($msg) = @_;
pO "<html><body>$msg</body></html>"; FW_pO "<html><body>$msg</body></html>";
} }
################## ##################
@@ -1301,8 +1306,8 @@ FW_zoomLink($$$)
} }
pO "&nbsp;&nbsp;"; FW_pO "&nbsp;&nbsp;";
pHPlain "$cmd", "<img style=\"border-color:transparent\" alt=\"$alt\" ". FW_pHPlain "$cmd", "<img style=\"border-color:transparent\" alt=\"$alt\" ".
"src=\"$FW_ME/icons/$img\"/>"; "src=\"$FW_ME/icons/$img\"/>";
} }
@@ -1418,38 +1423,38 @@ FW_style($$)
# push(@fl, ""); # push(@fl, "");
# push(@fl, FW_fileList("$FW_dir/.*html")); # push(@fl, FW_fileList("$FW_dir/.*html"));
pO $start; FW_pO $start;
pO "$msg<br><br>" if($msg); FW_pO "$msg<br><br>" if($msg);
pO "<table class=\"block\" id=\"at\">"; FW_pO "<table class=\"block\" id=\"at\">";
my $row = 0; my $row = 0;
foreach my $file (@fl) { foreach my $file (@fl) {
pO "<tr class=\"" . ($row?"odd":"even") . "\">"; FW_pO "<tr class=\"" . ($row?"odd":"even") . "\">";
if($file eq "") { if($file eq "") {
pO "<td><br></td>"; FW_pO "<td><br></td>";
} else { } else {
pH "cmd=style edit $file", $file, 1; FW_pH "cmd=style edit $file", $file, 1;
} }
pO "</tr>"; FW_pO "</tr>";
$row = ($row+1)%2; $row = ($row+1)%2;
} }
pO "</table>$end"; FW_pO "</table>$end";
} elsif($a[1] eq "select") { } elsif($a[1] eq "select") {
my @fl = FW_fileList("$FW_dir/.*style.css"); my @fl = FW_fileList("$FW_dir/.*style.css");
pO "$start<table class=\"block\" id=\"at\">"; FW_pO "$start<table class=\"block\" id=\"at\">";
my $row = 0; my $row = 0;
foreach my $file (@fl) { foreach my $file (@fl) {
next if($file =~ m/(svg_|smallscreen|touchpad)style.css/); next if($file =~ m/(svg_|smallscreen|touchpad)style.css/);
$file =~ s/style.css//; $file =~ s/style.css//;
$file = "Default" if($file eq ""); $file = "Default" if($file eq "");
pO "<tr class=\"" . ($row?"odd":"even") . "\">"; FW_pO "<tr class=\"" . ($row?"odd":"even") . "\">";
pH "cmd=style set $file", "$file", 1; FW_pH "cmd=style set $file", "$file", 1;
pO "</tr>"; FW_pO "</tr>";
$row = ($row+1)%2; $row = ($row+1)%2;
} }
pO "</table>$end"; FW_pO "</table>$end";
} elsif($a[1] eq "set") { } elsif($a[1] eq "set") {
if($a[2] eq "Default") { if($a[2] eq "Default") {
@@ -1457,20 +1462,20 @@ FW_style($$)
} else { } else {
$attr{$FW_wname}{stylesheetPrefix} = $a[2]; $attr{$FW_wname}{stylesheetPrefix} = $a[2];
} }
pO "${start}Reload the page in the browser.$end"; FW_pO "${start}Reload the page in the browser.$end";
} elsif($a[1] eq "examples") { } elsif($a[1] eq "examples") {
my @fl = FW_fileList("$FW_dir/example.*"); my @fl = FW_fileList("$FW_dir/example.*");
pO "$start<table class=\"block\" id=\"at\">"; FW_pO "$start<table class=\"block\" id=\"at\">";
my $row = 0; my $row = 0;
foreach my $file (@fl) { foreach my $file (@fl) {
pO "<tr class=\"" . ($row?"odd":"even") . "\">"; FW_pO "<tr class=\"" . ($row?"odd":"even") . "\">";
pO "<td><a href=\"$FW_ME/$file\">$file</a></td>"; FW_pO "<td><a href=\"$FW_ME/$file\">$file</a></td>";
pO "</tr>"; FW_pO "</tr>";
$row = ($row+1)%2; $row = ($row+1)%2;
} }
pO "</table>$end"; FW_pO "</table>$end";
} elsif($a[1] eq "edit") { } elsif($a[1] eq "edit") {
@@ -1478,26 +1483,26 @@ FW_style($$)
my $f = ($a[2] eq "fhem.cfg" ? $attr{global}{configfile} : my $f = ($a[2] eq "fhem.cfg" ? $attr{global}{configfile} :
"$FW_dir/$a[2]"); "$FW_dir/$a[2]");
if(!open(FH, $f)) { if(!open(FH, $f)) {
pO "$f: $!"; FW_pO "$f: $!";
return; return;
} }
my $data = join("", <FH>); my $data = join("", <FH>);
close(FH); close(FH);
my $ncols = $FW_ss ? 40 : 80; my $ncols = $FW_ss ? 40 : 80;
pO "<div id=\"content\">"; FW_pO "<div id=\"content\">";
pO "<form>"; FW_pO "<form>";
$f =~ s,^.*/,,; $f =~ s,^.*/,,;
pO FW_submit("save", "Save $f"); FW_pO FW_submit("save", "Save $f");
pO "&nbsp;&nbsp;"; FW_pO "&nbsp;&nbsp;";
pO FW_submit("saveAs", "Save as"); FW_pO FW_submit("saveAs", "Save as");
pO FW_textfield("saveName", 30); FW_pO FW_textfield("saveName", 30);
pO "<br><br>"; FW_pO "<br><br>";
pO FW_hidden("cmd", "style save $a[2]"); FW_pO FW_hidden("cmd", "style save $a[2]");
pO "<textarea name=\"data\" cols=\"$ncols\" rows=\"30\">" . FW_pO "<textarea name=\"data\" cols=\"$ncols\" rows=\"30\">" .
"$data</textarea>"; "$data</textarea>";
pO "</form>"; FW_pO "</form>";
pO "</div>"; FW_pO "</div>";
} elsif($a[1] eq "save") { } elsif($a[1] eq "save") {
my $fName = $a[2]; my $fName = $a[2];
@@ -1507,7 +1512,7 @@ FW_style($$)
$fName = ($fName eq "fhem.cfg" ? $attr{global}{configfile} : $fName = ($fName eq "fhem.cfg" ? $attr{global}{configfile} :
"$FW_dir/$fName"); "$FW_dir/$fName");
if(!open(FH, ">$fName")) { if(!open(FH, ">$fName")) {
pO "$fName: $!"; FW_pO "$fName: $!";
return; return;
} }
$FW_data =~ s/\r//g if($^O !~ m/Win/); $FW_data =~ s/\r//g if($^O !~ m/Win/);
@@ -1515,7 +1520,7 @@ FW_style($$)
print FH $FW_data; print FH $FW_data;
close(FH); close(FH);
FW_style("style list", "Saved the file $fName"); FW_style("style list", "Saved the file $fName");
fC("rereadcfg") if($fName eq $attr{global}{configfile}); FW_fC("rereadcfg") if($fName eq $attr{global}{configfile});
} }
} }
@@ -1523,7 +1528,7 @@ FW_style($$)
################## ##################
# print (append) to output # print (append) to output
sub sub
pO(@) FW_pO(@)
{ {
my $arg = shift; my $arg = shift;
return if(!defined($arg)); return if(!defined($arg));
@@ -1534,36 +1539,36 @@ pO(@)
################# #################
# add href # add href
sub sub
pH(@) FW_pH(@)
{ {
my ($link, $txt, $td, $class) = @_; my ($link, $txt, $td, $class) = @_;
pO "<td>" if($td); FW_pO "<td>" if($td);
$link = ($link =~ m,^/,) ? $link : "$FW_ME?$link"; $link = ($link =~ m,^/,) ? $link : "$FW_ME?$link";
$class = "" if(!defined($class)); $class = "" if(!defined($class));
$class = " class=\"$class\"" if($class); $class = " class=\"$class\"" if($class);
if($FW_ss || $FW_tp) { # No pointer change if using onClick if($FW_ss || $FW_tp) { # No pointer change if using onClick
pO "<a onClick=\"location.href='$link'\"><div$class>$txt</div></a>"; FW_pO "<a onClick=\"location.href='$link'\"><div$class>$txt</div></a>";
} else { } else {
pO "<a href=\"$link\"><div$class>$txt</div></a>"; FW_pO "<a href=\"$link\"><div$class>$txt</div></a>";
} }
pO "</td>" if($td); FW_pO "</td>" if($td);
} }
sub sub
pHPlain(@) FW_pHPlain(@)
{ {
my ($link, $txt, $td) = @_; my ($link, $txt, $td) = @_;
pO "<td>" if($td); FW_pO "<td>" if($td);
if($FW_ss || $FW_tp) { if($FW_ss || $FW_tp) {
pO "<a onClick=\"location.href='$FW_ME?$link'\">$txt</a>"; FW_pO "<a onClick=\"location.href='$FW_ME?$link'\">$txt</a>";
} else { } else {
pO "<a href=\"$FW_ME?$link\">$txt</a>"; FW_pO "<a href=\"$FW_ME?$link\">$txt</a>";
} }
pO "</td>" if($td); FW_pO "</td>" if($td);
} }
@@ -1580,7 +1585,7 @@ pF($@)
################## ##################
# fhem command # fhem command
sub sub
fC($) FW_fC($)
{ {
my ($cmd) = @_; my ($cmd) = @_;
my $ret = AnalyzeCommand(undef, $cmd); my $ret = AnalyzeCommand(undef, $cmd);
@@ -1596,19 +1601,19 @@ FW_showWeblink($$$$)
my $attr = AttrVal($d, "htmlattr", ""); my $attr = AttrVal($d, "htmlattr", "");
if($t eq "link") { if($t eq "link") {
pO "<a href=\"$v\" $attr>$d</a>"; # no pH, want to open extra browser FW_pO "<a href=\"$v\" $attr>$d</a>"; # no FW_pH, want to open extra browser
} elsif($t eq "image") { } elsif($t eq "image") {
pO "<img src=\"$v\" $attr><br>"; FW_pO "<img src=\"$v\" $attr><br>";
pO "<br>"; FW_pO "<br>";
pHPlain "detail=$d", $d; FW_pHPlain "detail=$d", $d;
pO "<br>"; FW_pO "<br>";
} elsif($t eq "iframe") { } elsif($t eq "iframe") {
pO "<iframe src=\"$v\" $attr>Iframes disabled</iframe>"; FW_pO "<iframe src=\"$v\" $attr>Iframes disabled</iframe>";
pO "<br>"; FW_pO "<br>";
pHPlain "detail=$d", $d; FW_pHPlain "detail=$d", $d;
pO "<br>"; FW_pO "<br>";
} elsif($t eq "fileplot") { } elsif($t eq "fileplot") {
@@ -1623,12 +1628,12 @@ FW_showWeblink($$$$)
FW_zoomLink("off=-1", "Prev.png", "prev"); FW_zoomLink("off=-1", "Prev.png", "prev");
FW_zoomLink("off=1", "Next.png", "next"); FW_zoomLink("off=1", "Next.png", "next");
$buttons = 0; $buttons = 0;
pO "<br>"; FW_pO "<br>";
} }
my @va = split(":", $v, 3); my @va = split(":", $v, 3);
if(@va != 3 || !$defs{$va[0]} || !$defs{$va[0]}{currentlogfile}) { if(@va != 3 || !$defs{$va[0]} || !$defs{$va[0]}{currentlogfile}) {
pO "Broken definition: $v<br>"; FW_pO "Broken definition: $v<br>";
} else { } else {
if($va[2] eq "CURRENT") { if($va[2] eq "CURRENT") {
@@ -1641,16 +1646,16 @@ FW_showWeblink($$$$)
my $arg="$FW_ME?cmd=showlog $d $va[0] $va[1] $va[2]$wl"; my $arg="$FW_ME?cmd=showlog $d $va[0] $va[1] $va[2]$wl";
if(AttrVal($d,"plotmode",$FW_plotmode) eq "SVG") { if(AttrVal($d,"plotmode",$FW_plotmode) eq "SVG") {
my ($w, $h) = split(",", AttrVal($d,"plotsize",$FW_plotsize)); my ($w, $h) = split(",", AttrVal($d,"plotsize",$FW_plotsize));
pO "<embed src=\"$arg\" type=\"image/svg+xml\" " . FW_pO "<embed src=\"$arg\" type=\"image/svg+xml\" " .
"width=\"$w\" height=\"$h\" name=\"$d\"/>\n"; "width=\"$w\" height=\"$h\" name=\"$d\"/>\n";
} else { } else {
pO "<img src=\"$arg\"/>"; FW_pO "<img src=\"$arg\"/>";
} }
pO "<br>"; FW_pO "<br>";
pHPlain "detail=$d", $d; FW_pHPlain "detail=$d", $d;
pO "<br>"; FW_pO "<br>";
} }
} }
@@ -1724,26 +1729,26 @@ FW_makeEdit($$$)
"s.display = s.display=='none' ? 'block' : 'none';". "s.display = s.display=='none' ? 'block' : 'none';".
"s=document.getElementById('disp').style;". "s=document.getElementById('disp').style;".
"s.display = s.display=='none' ? 'block' : 'none';"; "s.display = s.display=='none' ? 'block' : 'none';";
pO "<td>"; FW_pO "<td>";
pO "<a onClick=\"$pgm\">$n</a>"; FW_pO "<a onClick=\"$pgm\">$n</a>";
pO "</td>"; FW_pO "</td>";
$val =~ s,\\\n,\n,g; $val =~ s,\\\n,\n,g;
my $eval = $val; my $eval = $val;
$eval = "<pre>$eval</pre>" if($eval =~ m/\n/); $eval = "<pre>$eval</pre>" if($eval =~ m/\n/);
pO "<td>"; FW_pO "<td>";
pO "<div class=\"dval\" id=\"disp\">$eval</div>"; FW_pO "<div class=\"dval\" id=\"disp\">$eval</div>";
pO "</td>"; FW_pO "</td>";
pO "</tr><tr><td colspan=\"2\">"; FW_pO "</tr><tr><td colspan=\"2\">";
pO "<div id=\"edit\" style=\"display:none\"><form>"; FW_pO "<div id=\"edit\" style=\"display:none\"><form>";
my $cmd = "modify"; my $cmd = "modify";
my $ncols = $FW_ss ? 30 : 60; my $ncols = $FW_ss ? 30 : 60;
pO "<textarea name=\"val.${cmd}$name\" cols=\"$ncols\" rows=\"10\">". FW_pO "<textarea name=\"val.${cmd}$name\" cols=\"$ncols\" rows=\"10\">".
"$val</textarea>"; "$val</textarea>";
pO "<br>" . FW_submit("cmd.${cmd}$name", "$cmd $name"); FW_pO "<br>" . FW_submit("cmd.${cmd}$name", "$cmd $name");
pO "</form></div>"; FW_pO "</form></div>";
pO "</td>"; FW_pO "</td>";
} }
sub sub
@@ -1765,16 +1770,16 @@ FW_dumpFileLog($$$)
pF "<tr class=\"%s\">", ($row&1)?"odd":"even"; pF "<tr class=\"%s\">", ($row&1)?"odd":"even";
pF "<td><div class=\"dname\">%s</div></td>", ($nr ? "" : $f); pF "<td><div class=\"dname\">%s</div></td>", ($nr ? "" : $f);
} }
pH "cmd=logwrapper $d $lt $f", FW_pH "cmd=logwrapper $d $lt $f",
"<div class=\"dval\">$name</div>", 1, "dval"; "<div class=\"dval\">$name</div>", 1, "dval";
if(!$oneRow) { if(!$oneRow) {
pO "</tr>"; FW_pO "</tr>";
$row++; $row++;
} }
$nr++; $nr++;
} }
if($oneRow) { if($oneRow) {
pO "</tr>"; FW_pO "</tr>";
$row++; $row++;
} }
} }

View File

@@ -54,48 +54,48 @@ SVG_render($$$$$$$)
my ($w, $h) = ($ow-2*$x, $oh-2*$y); # Rect size my ($w, $h) = ($ow-2*$x, $oh-2*$y); # Rect size
# Html Header # Html Header
pO '<?xml version="1.0" encoding="UTF-8"?>'; FW_pO '<?xml version="1.0" encoding="UTF-8"?>';
pO '<!DOCTYPE svg>'; FW_pO '<!DOCTYPE svg>';
pO '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" '. FW_pO '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" '.
'xmlns:xlink="http://www.w3.org/1999/xlink" >'; 'xmlns:xlink="http://www.w3.org/1999/xlink" >';
my $prf = AttrVal($FW_wname, "stylesheetPrefix", ""); my $prf = AttrVal($FW_wname, "stylesheetPrefix", "");
pO "<style type=\"text/css\"><![CDATA["; FW_pO "<style type=\"text/css\"><![CDATA[";
if(open(FH, "$FW_dir/${prf}svg_style.css") || if(open(FH, "$FW_dir/${prf}svg_style.css") ||
open(FH, "$FW_dir/svg_style.css")) { open(FH, "$FW_dir/svg_style.css")) {
pO join("", <FH>); FW_pO join("", <FH>);
close(FH); close(FH);
} else { } else {
Log 0, "Can't open $FW_dir/svg_style.css" Log 0, "Can't open $FW_dir/svg_style.css"
} }
pO "]]></style>"; FW_pO "]]></style>";
if(open(FH, "$FW_dir/${prf}svg_defs.svg") || if(open(FH, "$FW_dir/${prf}svg_defs.svg") ||
open(FH, "$FW_dir/svg_defs.svg")) { # gradient definitions open(FH, "$FW_dir/svg_defs.svg")) { # gradient definitions
pO join("", <FH>); FW_pO join("", <FH>);
close(FH); close(FH);
} else { } else {
Log 0, "Can't open $FW_dir/svg_defs.svg" Log 0, "Can't open $FW_dir/svg_defs.svg"
} }
# Background # Background
pO "<rect width =\"$ow\" height=\"$oh\" class=\"background\"/>"; FW_pO "<rect width =\"$ow\" height=\"$oh\" class=\"background\"/>";
# Rectangle # Rectangle
pO "<rect x=\"$x\" y=\"$y\" width =\"$w\" height =\"$h\" rx=\"8\" ry=\"8\" ". FW_pO "<rect x=\"$x\" y=\"$y\" width =\"$w\" height =\"$h\" rx=\"8\" ry=\"8\" ".
"fill=\"none\" class=\"border\"/>"; "fill=\"none\" class=\"border\"/>";
my ($off1,$off2) = ($ow/2, 3*$y/4); my ($off1,$off2) = ($ow/2, 3*$y/4);
my $title = ($conf{title} ? $conf{title} : " "); my $title = ($conf{title} ? $conf{title} : " ");
$title =~ s/</&lt;/g; $title =~ s/</&lt;/g;
$title =~ s/>/&gt;/g; $title =~ s/>/&gt;/g;
pO "<text id=\"svg_title\" x=\"$off1\" y=\"$off2\" " . FW_pO "<text id=\"svg_title\" x=\"$off1\" y=\"$off2\" " .
"class=\"title\" text-anchor=\"middle\">$title</text>"; "class=\"title\" text-anchor=\"middle\">$title</text>";
# Copy and Paste labels, hidden by default # Copy and Paste labels, hidden by default
pO "<text id=\"svg_paste\" x=\"" . ($ow-$x) . "\" y=\"$off2\" " . FW_pO "<text id=\"svg_paste\" x=\"" . ($ow-$x) . "\" y=\"$off2\" " .
"onclick=\"parent.svg_paste(evt)\" " . "onclick=\"parent.svg_paste(evt)\" " .
"class=\"paste\" text-anchor=\"end\"> </text>"; "class=\"paste\" text-anchor=\"end\"> </text>";
pO "<text id=\"svg_copy\" x=\"" . ($ow-2*$x) . "\" y=\"$off2\" " . FW_pO "<text id=\"svg_copy\" x=\"" . ($ow-2*$x) . "\" y=\"$off2\" " .
"onclick=\"parent.svg_copy(evt)\" " . "onclick=\"parent.svg_copy(evt)\" " .
"class=\"copy\" text-anchor=\"end\"> </text>"; "class=\"copy\" text-anchor=\"end\"> </text>";
@@ -104,13 +104,13 @@ SVG_render($$$$$$$)
$t =~ s/"//g; $t =~ s/"//g;
if(!$SVG_ss) { if(!$SVG_ss) {
($off1,$off2) = (3*$th/4, $oh/2); ($off1,$off2) = (3*$th/4, $oh/2);
pO "<text x=\"$off1\" y=\"$off2\" text-anchor=\"middle\" " . FW_pO "<text x=\"$off1\" y=\"$off2\" text-anchor=\"middle\" " .
"class=\"ylabel\" transform=\"rotate(270,$off1,$off2)\">$t</text>"; "class=\"ylabel\" transform=\"rotate(270,$off1,$off2)\">$t</text>";
$t = ($conf{y2label} ? $conf{y2label} : ""); $t = ($conf{y2label} ? $conf{y2label} : "");
$t =~ s/"//g; $t =~ s/"//g;
($off1,$off2) = ($ow-$th/4, $oh/2); ($off1,$off2) = ($ow-$th/4, $oh/2);
pO "<text x=\"$off1\" y=\"$off2\" text-anchor=\"middle\" " . FW_pO "<text x=\"$off1\" y=\"$off2\" text-anchor=\"middle\" " .
"class=\"y2label\" transform=\"rotate(270,$off1,$off2)\">$t</text>"; "class=\"y2label\" transform=\"rotate(270,$off1,$off2)\">$t</text>";
} }
@@ -138,7 +138,7 @@ SVG_render($$$$$$$)
$desc = sprintf("%s: Min:%g Max:%g Last:%g", $desc = sprintf("%s: Min:%g Max:%g Last:%g",
$t, $data{"min$j"}, $data{"max$j"}, $data{"currval$j"}); $t, $data{"min$j"}, $data{"max$j"}, $data{"currval$j"});
} }
pO "<text title=\"$desc\" ". FW_pO "<text title=\"$desc\" ".
"onclick=\"parent.svg_labelselect(evt)\" line_id=\"line_$i\" " . "onclick=\"parent.svg_labelselect(evt)\" line_id=\"line_$i\" " .
"x=\"$off1\" y=\"$off2\" text-anchor=\"end\" class=\"l" . "x=\"$off1\" y=\"$off2\" text-anchor=\"end\" class=\"l" .
(defined($linestyle[$i]) ? $linestyle[$i] : $i) . "\">$t</text>"; (defined($linestyle[$i]) ? $linestyle[$i] : $i) . "\">$t</text>";
@@ -195,7 +195,7 @@ SVG_render($$$$$$$)
$dxp = $hdx[0]; $dxp = $hdx[0];
if($dxp && int(@{$dxp}) < 2 && !$tosec) { # not enough data and no range... if($dxp && int(@{$dxp}) < 2 && !$tosec) { # not enough data and no range...
pO "</svg>"; FW_pO "</svg>";
return; return;
} }
@@ -238,24 +238,24 @@ SVG_render($$$$$$$)
for(my $i = $fromsec+$initoffset; $i < $tosec; $i += $tstep) { for(my $i = $fromsec+$initoffset; $i < $tosec; $i += $tstep) {
$i = time_align($i,$aligntics); $i = time_align($i,$aligntics);
$off1 = int($x+($i-$fromsec)*$tmul); $off1 = int($x+($i-$fromsec)*$tmul);
pO "<polyline points=\"$off1,$y $off1,$off2\"/>"; FW_pO "<polyline points=\"$off1,$y $off1,$off2\"/>";
pO "<polyline points=\"$off1,$off3 $off1,$off4\"/>"; FW_pO "<polyline points=\"$off1,$off3 $off1,$off4\"/>";
} }
# then the text and the grid # then the text and the grid
$off1 = $x; $off1 = $x;
$off2 = $y+$h+$th; $off2 = $y+$h+$th;
$t = fmtTime($first_tag, $fromsec); $t = fmtTime($first_tag, $fromsec);
pO "<text x=\"0\" y=\"$off2\" class=\"ylabel\">$t</text>"; FW_pO "<text x=\"0\" y=\"$off2\" class=\"ylabel\">$t</text>";
$initoffset = $step; $initoffset = $step;
$initoffset = int(($step/2)/86400)*86400 if($aligntext); $initoffset = int(($step/2)/86400)*86400 if($aligntext);
for(my $i = $fromsec+$initoffset; $i < $tosec; $i += $step) { for(my $i = $fromsec+$initoffset; $i < $tosec; $i += $step) {
$i = time_align($i,$aligntext); $i = time_align($i,$aligntext);
$off1 = int($x+($i-$fromsec)*$tmul); $off1 = int($x+($i-$fromsec)*$tmul);
$t = fmtTime($tag, $i); $t = fmtTime($tag, $i);
pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\" " . FW_pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\" " .
"text-anchor=\"middle\">$t</text>"; "text-anchor=\"middle\">$t</text>";
pO " <polyline points=\"$off1,$y $off1,$off4\" class=\"hgrid\"/>"; FW_pO " <polyline points=\"$off1,$y $off1,$off4\" class=\"hgrid\"/>";
} }
@@ -313,10 +313,10 @@ SVG_render($$$$$$$)
$tlabel =~ s/^"(.*)"$/$1/; $tlabel =~ s/^"(.*)"$/$1/;
$off2 = int($y+($ma-$tvalue)*$hmul); $off2 = int($y+($ma-$tvalue)*$hmul);
pO "<polyline points=\"$off3,$off2 $off4,$off2\"/>"; FW_pO "<polyline points=\"$off3,$off2 $off4,$off2\"/>";
$off2 += $th/4; $off2 += $th/4;
my $align = ($axis eq "x1y1" ? " text-anchor=\"end\"" : ""); my $align = ($axis eq "x1y1" ? " text-anchor=\"end\"" : "");
pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align> FW_pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align>
$tlabel</text>"; $tlabel</text>";
} }
@@ -324,16 +324,16 @@ SVG_render($$$$$$$)
for(my $i = $mi; $i <= $ma; $i += $step) { for(my $i = $mi; $i <= $ma; $i += $step) {
$off2 = int($y+($ma-$i)*$hmul); $off2 = int($y+($ma-$i)*$hmul);
pO " <polyline points=\"$off3,$off2 $off4,$off2\"/>"; FW_pO " <polyline points=\"$off3,$off2 $off4,$off2\"/>";
if($axis eq "x1y2") { if($axis eq "x1y2") {
my $o6 = $x+$w; my $o6 = $x+$w;
pO " <polyline points=\"$x,$off2 $o6,$off2\" class=\"vgrid\"/>" FW_pO " <polyline points=\"$x,$off2 $o6,$off2\" class=\"vgrid\"/>"
if($i > $mi && $i < $ma); if($i > $mi && $i < $ma);
} }
$off2 += $th/4; $off2 += $th/4;
my $align = ($axis eq "x1y1" ? " text-anchor=\"end\"" : ""); my $align = ($axis eq "x1y1" ? " text-anchor=\"end\"" : "");
my $txt = sprintf("%g", $i); my $txt = sprintf("%g", $i);
pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align>$txt</text>"; FW_pO "<text x=\"$off1\" y=\"$off2\" class=\"ylabel\"$align>$txt</text>";
} }
} }
@@ -372,7 +372,7 @@ SVG_render($$$$$$$)
$ly = $x1; $ly = $y1; $ly = $x1; $ly = $y1;
$ret = sprintf(" %d,%d %d,%d %d,%d %d,%d %d,%d", $ret = sprintf(" %d,%d %d,%d %d,%d %d,%d %d,%d",
$x1-3,$y1, $x1,$y1-3, $x1+3,$y1, $x1,$y1+3, $x1-3,$y1); $x1-3,$y1, $x1,$y1-3, $x1+3,$y1, $x1,$y1+3, $x1-3,$y1);
pO "<polyline $js_helpers points=\"$ret\" class=\"l$idx\"/>"; FW_pO "<polyline $js_helpers points=\"$ret\" class=\"l$idx\"/>";
} }
} elsif($type[$idx] eq "steps" || $type[$idx] eq "fsteps" ) { } elsif($type[$idx] eq "steps" || $type[$idx] eq "fsteps" ) {
@@ -394,7 +394,7 @@ SVG_render($$$$$$$)
} }
} }
} }
pO "<polyline $js_helpers points=\"$ret\" class=\"l$idx\"/>"; FW_pO "<polyline $js_helpers points=\"$ret\" class=\"l$idx\"/>";
} elsif($type[$idx] eq "histeps" ) { } elsif($type[$idx] eq "histeps" ) {
if(@{$dxp} == 1) { if(@{$dxp} == 1) {
@@ -411,7 +411,7 @@ SVG_render($$$$$$$)
$x1,$y1, ($x1+$x2)/2,$y1, ($x1+$x2)/2,$y2, $x2,$y2); $x1,$y1, ($x1+$x2)/2,$y1, ($x1+$x2)/2,$y2, $x2,$y2);
} }
} }
pO "<polyline $js_helpers points=\"$ret\" class=\"l$idx\"/>"; FW_pO "<polyline $js_helpers points=\"$ret\" class=\"l$idx\"/>";
} else { # lines and everything else } else { # lines and everything else
foreach my $i (0..int(@{$dxp})-1) { foreach my $i (0..int(@{$dxp})-1) {
@@ -422,7 +422,7 @@ SVG_render($$$$$$$)
$ret .= sprintf(" %d,%d", $x1, $y1); $ret .= sprintf(" %d,%d", $x1, $y1);
} }
pO "<polyline $js_helpers points=\"$ret\" style=\"stroke-width:" . FW_pO "<polyline $js_helpers points=\"$ret\" style=\"stroke-width:" .
(defined($linewidth[$idx]) ? $linewidth[$idx] : 1) . (defined($linewidth[$idx]) ? $linewidth[$idx] : 1) .
"\" class=\"l" . "\" class=\"l" .
(defined($linestyle[$idx]) ? $linestyle[$idx] : $idx) . "\"/>"; (defined($linestyle[$idx]) ? $linestyle[$idx] : $idx) . "\"/>";
@@ -430,7 +430,7 @@ SVG_render($$$$$$$)
} }
} }
pO "</svg>"; FW_pO "</svg>";
} }
sub sub

View File

@@ -0,0 +1,77 @@
###########################################################################
### Display values from a KS550.
# This file is only present for documentation and as a starting point
# for derivation of a subset of measures. Please see and use the other
# ks550_*.gplot files to plot KS550 data.
### FileLog definition corresponding to this file
# define <filelogname> FileLog /var/log/fhem/KS550_%Y.log <ks550name>:T:.*
### FileLog content
# 2012-01-01_00:00:03 KS550 T: 10.4 H: 97 W: 0 R: 976.45 IR: 0 WD: 40 WDR: 67.5 S: 155 B: 8
# This is the status line, which is printed to the logfile. For each of
# the data there is also a separate line available, which you can select
# using a different regular expression in the FileLog define.
# Try .* as an all quantor to see, which lines are available.
#
# Field description:
# 04 T: Temperature
# 06 H: Humidity
# 08 W: Wind velocity
# 10 R: Rain quantity
# 12 IR: Rain indicator
# 14 WD: Direction of wind
# 16 WDR: Range of wind directions (67.5 is the maximum range)
# 18 S: Sunshine duration
# 20 B: Brightness (minimum:8, maximum:255)
### Settings
set terminal size <SIZE>
set title '<TL>'
set ylabel '<L1>'
set y2label '<L2>'
set ytics
set y2tics
# Maybe define your own ranges (not really needed):
#set yrange [1:10]
#set y2range [0:300]
### Data extraction
# The following FileLog directives extract the values from the logfile
# lines. If you have only the status lines in the logfile, you do not
# need any regular expression, since the line is valid anyhow.
#
# Some data have default values, others not. Notice also the delta-*
# functions, which are called to compute Rain/h and Rain/d values by
# accumulating the changes as well as the data mapping for the rain
# indicator.
#FileLog 4:::
#FileLog 6:::
#FileLog 8:::
#FileLog 10::0:delta-h
#FileLog 10::0:delta-d
#FileLog 12::0:$fld[11]=~"32768"?1:0
#FileLog 14::0:
#FileLog 16::0:
#FileLog 18::0:delta-h
#FileLog 20::0:
plot \
title 'T' with lines,\
title 'H' with lines,\
title 'W' with lines,\
title 'R/h' with lines,\
title 'R/d' with lines,\
title 'IR' with lines,\
title 'WD' with lines,\
title 'WDR' with lines,\
title 'S' with lines,\
title 'B' with lines

View File

@@ -0,0 +1,67 @@
###########################################################################
### Display Light and Sunshine values from a KS550
# This file uses placeholders. For good results the following
# attribute settings in the WebLink object are recommended:
#
# label: "Luminosity"::"Sunshine duration [h]"
# title: "Light $data{currval1} ($data{min1}-$data{max1}) and Sunshine hours $data{currval2} @ $data{currdate1}"
### FileLog definition corresponding to this file
# define <filelogname> FileLog /var/log/fhem/KS550_%Y.log <ks550name>:T:.*
### FileLog content
# 2012-01-01_00:00:03 KS550 T: 10.4 H: 97 W: 0 R: 976.45 IR: 0 WD: 40 WDR: 67.5 S: 155 B: 8
# This is the status line, which is printed to the logfile. For each of
# the data there is also a separate line available, which you can select
# using a different regular expression in the FileLog define.
# Try .* as an all quantor to see, which lines are available.
# This is the status line, which is printed to the logfile. For each of
# the data there is also a separate line available, which you can select
# using a different regular expression in the FileLog define.
# Try .* as an all quantor to see, which lines are available.
#
# Field description:
# T: Temperature
# H: Humidity
# W: Wind velocity
# R: Rain quantity
# IR: Rain indicator
# WD: Direction of wind
# WDR: Range of wind directions (67.5 is the maximum range)
# S: Sunshine duration
# B: Brightness (minimum:8, maximum:255)
### Settings
set terminal size <SIZE>
set title '<TL>'
set ylabel '<L1>'
set y2label '<L2>'
set ytics
set y2tics
# Maybe define your own ranges (not really needed):
#set yrange [1:10]
#set y2range [0:300]
### Data extraction
# The following FileLog directives extract the values from the logfile
# lines. If you have only the status lines in the logfile, you do not
# need any regular expression, since the line is valid anyhow.
# Notice the delta-* functions, which are called to compute Rain/h and
# Rain/d values by accumulating the changes.
#FileLog 20::0:
#FileLog 18::0:delta-h
### Data plotting
plot \
axes x1y1 title 'Brightness' with lines,\
axes x1y2 title 'Sunshine' with lines

View File

@@ -0,0 +1,64 @@
###########################################################################
### Display Rain values from a KS550
# This file uses placeholders. For good results the following
# attribute settings in the WebLink object are recommended:
#
# label: "Rain Volume [l/m2]"::"Rain indicator"::"l/hour"::"l/day"::"Rain?"
# title: "Rain $data{currval2} liters @ $data{currdate1}"
### FileLog definition corresponding to this file
# define <filelogname> FileLog /var/log/fhem/KS550_%Y.log <ks550name>:T:.*
### FileLog content
# 2012-01-01_00:00:03 KS550 T: 10.4 H: 97 W: 0 R: 976.45 IR: 0 WD: 40 WDR: 67.5 S: 155 B: 8
# This is the status line, which is printed to the logfile. For each of
# the data there is also a separate line available, which you can select
# using a different regular expression in the FileLog define.
# Try .* as an all quantor to see, which lines are available.
#
# Field description:
# T: Temperature
# H: Humidity
# W: Wind velocity
# R: Rain quantity
# IR: Rain indicator
# WD: Direction of wind
# WDR: Range of wind directions (67.5 is the maximum range)
# S: Sunshine duration
# B: Brightness (minimum:8, maximum:255)
### Settings
set terminal size <SIZE>
set title '<TL>'
set ylabel '<L1>'
set y2label '<L2>'
set ytics
set y2tics
# Maybe define your own ranges (not really needed):
#set yrange [1:10]
#set y2range [0:300]
### Data extraction
# The following FileLog directives extract the values from the logfile
# lines. If you have only the status lines in the logfile, you do not
# need any regular expression, since the line is valid anyhow.
# Notice the delta-* functions, which are called to compute Rain/h and
# Rain/d values by accumulating the changes and the value remapping.
#FileLog 10::0:delta-h
#FileLog 10::0:delta-d
#FileLog 12::0:$fld[11]=~"32768"?0.8:0
### Data plotting
plot \
axes x1y1 title '<L3>' with steps lw 2,\
axes x1y1 title '<L4>' with steps,\
axes x1y2 title '<L5>' with steps

View File

@@ -0,0 +1,61 @@
###########################################################################
### Display Temperature/Humidity values from a KS550
# This file uses placeholders. For good results the following
# attribute settings in the WebLink object are recommended:
#
# label: "Rel. Humidity [%]"::"Temperature [C]"::"Temperature"::"rel. Humidity"
# title: "Temperature $data{currval1} ($data{min1}-$data{max1}), Humidity $data{currval2} ($data{min2}-$data{max2}) @ $data{currdate1}"
### FileLog definition corresponding to this file
# define <filelogname> FileLog /var/log/fhem/KS550_%Y.log <ks550name>:T:.*
### FileLog content
# 2012-01-01_00:00:03 KS550 T: 10.4 H: 97 W: 0 R: 976.45 IR: 0 WD: 40 WDR: 67.5 S: 155 B: 8
# This is the status line, which is printed to the logfile. For each of
# the data there is also a separate line available, which you can select
# using a different regular expression in the FileLog define.
# Try .* as an all quantor to see, which lines are available.
#
# Field description:
# T: Temperature
# H: Humidity
# W: Wind velocity
# R: Rain quantity
# IR: Rain indicator
# WD: Direction of wind
# WDR: Range of wind directions (67.5 is the maximum range)
# S: Sunshine duration
# B: Brightness (minimum:8, maximum:255)
### Settings
set terminal size <SIZE>
set title '<TL>'
set ylabel '<L1>'
set y2label '<L2>'
set ytics
set y2tics
# Maybe define your own ranges (not really needed):
#set yrange [1:10]
#set y2range [0:300]
### Data extraction
# The following FileLog directives extract the values from the logfile
# lines. If you have only the status lines in the logfile, you do not
# need any regular expression, since the line is valid anyhow. No
# defaults are used here either.
#FileLog 4:::
#FileLog 6:::
### Data plotting
plot \
axes x1y2 title '<L3>' with lines,\
axes x1y1 title '<L4>' with lines

View File

@@ -0,0 +1,63 @@
###########################################################################
### Display Wind values from a KS550
# This file uses placeholders. For good results the following
# attribute settings in the WebLink object are recommended:
#
# label: "Wind Speed [km/h]"::"Direction [360]"::"Speed"::"Direction"::"Range (max. 67.5)"
# title: "Wind $data{currval1} ($data{min1}-$data{max1}), Direction $data{currval2} ($data{min2}-$data{max2}) and Range $data{currval3} @ $data{currdate1}"
### FileLog definition corresponding to this file
# define <filelogname> FileLog /var/log/fhem/KS550_%Y.log <ks550name>:T:.*
### FileLog content
# 2012-01-01_00:00:03 KS550 T: 10.4 H: 97 W: 0 R: 976.45 IR: 0 WD: 40 WDR: 67.5 S: 155 B: 8
# This is the status line, which is printed to the logfile. For each of
# the data there is also a separate line available, which you can select
# using a different regular expression in the FileLog define.
# Try .* as an all quantor to see, which lines are available.
#
# Field description:
# T: Temperature
# H: Humidity
# W: Wind velocity
# R: Rain quantity
# IR: Rain indicator
# WD: Direction of wind
# WDR: Range of wind directions (67.5 is the maximum range)
# S: Sunshine duration
# B: Brightness (minimum:8, maximum:255)
### Settings
set terminal size <SIZE>
set title '<TL>'
set ylabel '<L1>'
set y2label '<L2>'
set ytics
set y2tics
# Maybe define your own ranges (not really needed):
#set yrange [1:10]
#set y2range [0:300]
### Data extraction
# The following FileLog directives extract the values from the logfile
# lines. If you have only the status lines in the logfile, you do not
# need any regular expression, since the line is valid anyhow.
# Notice the use ans non-use of default values
#FileLog 8::0:
#FileLog 14:::
#FileLog 16:::
### Data plotting
plot \
axes x1y1 title '<L3>' with lines,\
axes x1y2 title '<L4>' with steps,\
axes x1y2 title '<L5>' with steps

View File

@@ -42,4 +42,10 @@ longpoll()
pollConn.send(null); pollConn.send(null);
} }
window.onload = longpoll; function
delayedStart()
{
setTimeout("longpoll()", 1000);
}
window.onload = delayedStart;