diff --git a/webfrontend/pgm2/01_FHEMWEB.pm b/webfrontend/pgm2/01_FHEMWEB.pm index c6cff5579..9a35838ab 100755 --- a/webfrontend/pgm2/01_FHEMWEB.pm +++ b/webfrontend/pgm2/01_FHEMWEB.pm @@ -32,10 +32,12 @@ sub FW_zoomLink($$$); sub FW_calcWeblink($$); use vars qw($__ME); # webname (fhem), needed by SVG +my $zlib_loaded; ######################### # As we are _not_ multithreaded, it is safe to use global variables. +# Note: for delivering SVG plots we fork my %__icons; # List of icons my $__iconsread; # Timestamp of last icondir check my %__rooms; # hash of all rooms @@ -67,7 +69,8 @@ FHEMWEB_Initialize($) $hash->{DefFn} = "FW_Define"; $hash->{UndefFn} = "FW_Undef"; - $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 webname plotmode:gnuplot,gnuplot-scroll,SVG plotsize refresh"; + $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 webname fwmodpath fwcompress " . + "plotmode:gnuplot,gnuplot-scroll,SVG plotsize refresh"; ############### # Initialize internal structures @@ -75,7 +78,6 @@ FHEMWEB_Initialize($) @__zoom = ("qday", "day","week","month","year"); %__zoom = map { $_, $n++ } @__zoom; - $__dir = "$attr{global}{modpath}/FHEM"; } ##################################### @@ -187,6 +189,8 @@ FW_Read($) #Log(0, "Got: >$hash->{BUF}<"); my @lines = split("[\r\n]", $hash->{BUF}); + my @enc = grep /Accept-Encoding/, @lines; + my ($mode, $arg, $method) = split(" ", $lines[0]); $hash->{BUF} = ""; @@ -203,13 +207,33 @@ FW_Read($) $defs{$name} = $hash; } + if(!$zlib_loaded && FW_getAttr($__wname, "fwcompress", 1)) { + $zlib_loaded = 1; + eval { require Compress::Zlib; }; + if($@) { + Log 1, $@; + Log 1, "$__wname: Can't load Compress::Zlib, deactivating compression"; + $attr{$__wname}{fwcompress} = 0; + } + } + + my $compressed = ""; + if(($__RETTYPE=~m/text/i || $__RETTYPE=~m/svg/i || $__RETTYPE=~m/script/i) && + (int(@enc) == 1 && $enc[0] =~ m/gzip/) && + FW_getAttr($__wname, "fwcompress", 1)) { + + $__RET = Compress::Zlib::memGzip($__RET); + $compressed = "Content-Encoding: gzip\r\n"; + } + my $c = $hash->{CD}; - my $l = length($__RET); - my $e = ($cacheable? ("Expires: ".localtime(time()+900)." GMT\r\n") : ""); - #Log 0, "$arg / RL: $l"; + my $length = length($__RET); + my $expires = ($cacheable? + ("Expires: ".localtime(time()+900)." GMT\r\n") : ""); +#Log 0, "$arg / RL: $length / $__RETTYPE / $compressed"; print $c "HTTP/1.1 200 OK\r\n", - "Content-Length: $l\r\n", - $e, + "Content-Length: $length\r\n", + $expires, $compressed, "Content-Type: $__RETTYPE\r\n\r\n", $__RET; exit if(defined($pid)); @@ -224,6 +248,7 @@ FW_AnswerCall($) $__RET = ""; $__RETTYPE = "text/html; charset=ISO-8859-1"; $__ME = "/" . FW_getAttr($__wname, "webname", "fhem"); + $__dir = FW_getAttr($__wname, "fwmodpath", "$attr{global}{modpath}/FHEM"); # Lets go: if($arg =~ m,^${__ME}/(.*html)$, || $arg =~ m,^${__ME}/(example.*)$,) { @@ -242,7 +267,8 @@ FW_AnswerCall($) $__RETTYPE = "text/css"; return 1; - } elsif($arg =~ m,^$__ME/icons/(.*)$,) { + } elsif($arg =~ m,^$__ME/icons/(.*)$, || + $arg =~ m,^$__ME/(.*.png)$,) { open(FH, "$__dir/$1") || return; binmode (FH); # necessary for Windows pO join("", ); @@ -315,20 +341,24 @@ FW_AnswerCall($) } my $t = FW_getAttr("global", "title", "Home, Sweet Home"); - pO "\n\n$t\n"; + + pO ''; + + pO ''; + pO "\n$t"; my $rf = FW_getAttr($__wname, "refresh", ""); - pO "\n" if($rf); - pO "\n"; - pO "\n\n"; + pO "" if($rf); + pO ""; + pO "\n"; if($__cmdret) { $__detail = ""; $__room = ""; $__cmdret =~ s//>/g; - pO "
\n"; - pO "
$__cmdret
\n"; - pO "
\n"; + pO "
"; + pO "
$__cmdret
"; + pO "
"; } FW_roomOverview($cmd); @@ -417,22 +447,22 @@ FW_makeTable($$$$$$$$) $t = "EM" if($t =~ m/^EM.*$/); # EMWZ,EMEM,etc. $t = "KS300" if($t eq "HMS"); - pO " \n"; + pO "
"; # Header pO " "; foreach my $h (split(",", $header)) { pO ""; } - pO "\n"; + pO ""; if($clist) { - pO "\n"; + pO ""; my @al = map { s/[:;].*//;$_ } split(" ", $clist); pO ""; - pO ""; + pO ""; pO ""; pO FW_hidden("dev.$ccmd$d", $d); - pO "\n"; + pO ""; } my $row = 1; @@ -461,10 +491,10 @@ FW_makeTable($$$$$$$$) pO "" if($cmd); - pO "\n"; + pO ""; } - pO "
$h
" . FW_select("arg.$ccmd$d",\@al,undef) . "" . FW_textfield("val.$ccmd$d", 6) . "" . FW_textfield("val.$ccmd$d", 20) . "" . FW_submit("cmd.$ccmd$d", $ccmd) . "
$cmd
\n"; - pO "
\n"; + pO " "; + pO "
"; } @@ -482,9 +512,9 @@ FW_showArchive($) $fn = FW_getAttr($d, "archivedir", "") . "/" . $fn; my $t = $defs{$d}{TYPE}; - pO "
\n"; - pO "
\n"; - pO "
\n"; + pO "
"; + pO "
"; + pO ""; } - pO "
"; my $row = 0; my $l = FW_getAttr($d, "logtype", undef); @@ -503,9 +533,9 @@ FW_showArchive($) pO "
\n"; - pO "
\n"; - pO "
\n"; + pO "
"; + pO "
"; + pO "
"; } @@ -521,9 +551,9 @@ FW_doDetail($) $__room = FW_getAttr($d, "room", undef); my $t = $defs{$d}{TYPE}; - pO "
\n"; - pO "
\n"; - pO "Delete $d\n"; + pO "
"; + pO "
"; + pO "Delete $d"; my $pgm = "Javascript:" . "s=document.getElementById('edit').style;". @@ -532,7 +562,7 @@ FW_doDetail($) "if(s.display=='none') s.display='block'; else s.display='none';"; pO "Modify $d"; - pO "
\n"; + pO "
"; FW_makeTable($d, $t, "State,Value,Measured", $defs{$d}{READINGS}, getAllSets($d), "set", 0, undef); @@ -542,12 +572,12 @@ FW_doDetail($) "Attribute,Value,Action", $attr{$d}, getAllAttr($d), "attr", 1, $d eq "global" ? "" : "deleteattr"); - pO "
\n"; + pO "
"; FW_showWeblink($d, $defs{$d}{LINK}, $defs{$d}{WLTYPE}) if($t eq "weblink"); - pO "
\n"; - pO "\n"; + pO ""; + pO ""; } @@ -559,19 +589,10 @@ FW_roomOverview($) my ($cmd) = @_; pO "
"; - pO "
\n"; + pO "
"; pO "
"; - pO "Fhem cmd: "; pO FW_textfield("cmd", 30); - if(defined($data{FWEXT})) { - foreach my $k (sort keys %{$data{FWEXT}}) { - my $h = $data{FWEXT}{$k}; - next if($h !~ m/HASH/ || !$h->{LINK} || !$h->{NAME}); - pO " {LINK} . "\">" . $h->{NAME}. ""; - } - } - if($__room) { pO FW_hidden("room", "$__room"); @@ -588,36 +609,48 @@ FW_roomOverview($) } } pO "
"; - pO "
\n"; + pO "
"; + + pO "
"; + pO "

"; + pO " "; + pO "
"; + pO " "; + + if(defined($data{FWEXT})) { + foreach my $k (sort keys %{$data{FWEXT}}) { + my $h = $data{FWEXT}{$k}; + next if($h !~ m/HASH/ || !$h->{LINK} || !$h->{NAME}); + pO ""; + } + pO ""; + } - pO "
\n"; - pO "
{LINK} . "\">" + . $h->{NAME}. "
\n"; - pO " "; + pO " \n"; - pO "
\n"; - pO " \n"; $__room = "" if(!$__room); foreach my $r (sort keys %__rooms) { next if($r eq "hidden"); pF " ", $r eq $__room ? " class=\"sel\"" : ""; - pO "\n"; + pO ""; } pF " ", "all" eq $__room ? " class=\"sel\"" : ""; - pO ""; - pO "
$r"; - pO "
$r
All together
\n"; - pO "
\n"; - pO " \n"; - pO " \n"; - pO " \n"; - pO " \n"; + pO " "; + pO "
Howto
FAQ
Details
All together
"; + + pO "
"; + pO " "; + pO " "; + pO " "; + pO " "; my $sel = ($cmd =~ m/examples/) ? " class=\"sel\"" : ""; - pO " \n"; + pO " "; $sel = ($cmd =~ m/list/) ? " class=\"sel\"" : ""; - pO " \n"; - pO "
Howto
FAQ
Details
Examples
Examples
Edit files
\n"; - pO "
\n"; - pO "\n"; - pO "\n"; + pO "
Edit files
"; + pO " "; + pO " "; + pO "
"; + pO ""; } @@ -642,8 +675,8 @@ FW_showRoom() } pO "
"; - pO "
\n"; - pO " \n
\n"; # Need for equal width of subtables + pO "
"; + pO "
"; # Need for equal width of subtables foreach my $type (sort keys %__types) { @@ -659,25 +692,25 @@ FW_showRoom() # Print the table headers my $t = $type; $t = "EM" if($t =~ m/^EM.*$/); - pO " \n"; - my $h; + my $th; + my $id = "class=\"block\""; if($type eq "FS20") { - $h = "FS20 dev.\n" if($h); + pO "
StateSet to"; + $th = "FS20 dev.StateSet to"; } elsif($type eq "FHT") { - $h = "FHT dev.MeasuredSet to"; - } elsif($type eq "at") { $h = "Scheduled commands (at)"; - } elsif($type eq "FileLog") { $h = "Logs"; - } elsif($type eq "_internal_") { $h = "Global variables"; - } elsif($type eq "weblink") { $h = ""; + $th = "FHT dev.MeasuredSet to"; + } elsif($type eq "at") { $th = "Scheduled commands (at)"; + } elsif($type eq "FileLog") { $th = "Logs"; + } elsif($type eq "_internal_") { $th = "Global variables"; + } elsif($type eq "weblink") { $th = ""; $id = ""; } else { - $h = $type; + $th = $type; } - pO "
$h
"; + pO " " if($th); my $row=1; foreach my $d (sort keys %{$__types{$type}} ) { - next if($__room && $__room ne "all" && !$__rooms{$__room}{$d}); @@ -737,7 +770,7 @@ FW_showRoom() } elsif($type eq "FileLog") { - pO "\n"; + pO ""; if(defined(FW_getAttr($d, "archivedir", undef))) { pO ""; } @@ -759,17 +792,17 @@ FW_showRoom() } else { - pO "\n"; + pO ""; } - pO " \n"; + pO " "; } - pO "
$th
$d$v$d$varchive$d$v$d$v
\n"; - pO "
\n"; # Empty line + pO "
"; + pO "
"; # Empty line } - pO "
\n"; - pO "
\n"; - pO "
\n"; + pO " \n"; + pO ""; + pO ""; } ################# @@ -807,7 +840,7 @@ FW_logWrapper($) $path = FW_getAttr($d,"archivedir","") . "/$file" if(!-f $path); if(!open(FH, $path)) { - pO "
$path: $!
\n"; + pO "
$path: $!
"; return; } binmode (FH); # necessary for Windows @@ -816,15 +849,15 @@ FW_logWrapper($) $cnt =~ s//>/g; - pO "
\n"; - pO "
$cnt
\n"; - pO "
\n"; + pO "
"; + pO "
$cnt
"; + pO "
"; } else { - pO "
\n"; - pO "
\n"; - pO "
\n"; + pO "
"; + pO "
"; + pO ""; - pO "
"; pO ""; my $arg = "$__ME?cmd=showlog undef $d $type $file"; if(FW_getAttr($d,"plotmode",$__plotmode) eq "SVG") { @@ -832,13 +865,13 @@ FW_logWrapper($) pO "\n"; } else { - pO "\n"; + pO ""; } pO "
Convert to weblink
\n"; - pO "
\n"; - pO "
\n"; + pO "
"; + pO "
"; + pO "
"; } } @@ -1020,7 +1053,7 @@ FW_showLog($) } $ret = fC("get $d $file INT $f $t " . join(" ", @{$flog})); ($cfg, $plot) = FW_substcfg(1, $wl, $cfg, $plot, $file, ""); - SVG_render($f, $t, $cfg, $internal_data, $plot); + SVG_render($wl, $f, $t, $cfg, $internal_data, $plot); $__RETTYPE = "image/svg+xml"; } @@ -1082,13 +1115,8 @@ FW_makeEdit($$$$) my $eval = $val; $eval =~ s,\\\n,\n,g; - if($type eq "at" || $type eq "notify") { - pO ""; - } else { - pO ""; - } pO "
" . FW_submit("cmd.${cmd}$name", "$cmd $name"); pO ""; $eval = "
$eval
" if($eval =~ m/\n/); @@ -1280,36 +1308,36 @@ FW_style($$) push(@fl, "
"); push(@fl, FW_fileList("$__dir/.*html")); - pO "
\n"; - pO "
\n"; - pO " $msg

\n" if($msg); - pO " \n"; + pO "
"; + pO "
"; + pO " $msg

" if($msg); + pO " "; my $row = 0; foreach my $file (@fl) { pO ""; pO ""; $row = ($row+1)%2; } - pO "
$file
\n"; - pO "
\n"; - pO "\n"; + pO "
"; + pO " "; + pO "
"; } elsif($a[1] eq "examples") { my @fl = FW_fileList("$__dir/example.*"); - pO "
\n"; - pO "
\n"; - pO " $msg

\n" if($msg); - pO " \n"; + pO "
"; + pO "
"; + pO " $msg

" if($msg); + pO " "; my $row = 0; foreach my $file (@fl) { pO ""; pO ""; $row = ($row+1)%2; } - pO "
$file
\n"; - pO "
\n"; - pO "\n"; + pO "
"; + pO " "; + pO "
"; } elsif($a[1] eq "edit") { @@ -1323,14 +1351,14 @@ FW_style($$) my $data = join("", ); close(FH); - pO "
\n"; + pO "
"; pO "
"; pO FW_submit("save", "Save $f") . "

"; pO FW_hidden("cmd", "style save $a[2]"); pO ""; pO "
"; - pO "
\n"; + pO "
"; } elsif($a[1] eq "save") { @@ -1359,6 +1387,7 @@ sub pO(@) { $__RET .= shift; + $__RET .= "\n"; } ################## @@ -1397,10 +1426,10 @@ FW_showWeblink($$$) my ($d, $v, $t) = @_; if($t eq "link") { - pO "$d\n"; + pO "$d"; } elsif($t eq "image") { - pO "
$d\n"; + pO "
$d"; } elsif($t eq "fileplot") { my @va = split(":", $v, 3); @@ -1421,7 +1450,7 @@ FW_showWeblink($$$) pO "\n"; } else { - pO "\n"; + pO ""; } pO ""; diff --git a/webfrontend/pgm2/98_SVG.pm b/webfrontend/pgm2/98_SVG.pm index cac3cb411..11ffaf359 100755 --- a/webfrontend/pgm2/98_SVG.pm +++ b/webfrontend/pgm2/98_SVG.pm @@ -8,7 +8,7 @@ use POSIX; -sub SVG_render($$$$$); +sub SVG_render($$$$$$); sub time_to_sec($); sub fmtTime($$); @@ -24,9 +24,16 @@ SVG_Initialize($) ##################################### sub -SVG_render($$$$$) +SVG_render($$$$$$) { - my ($from, $to, $confp, $dp, $plot) = @_; + my $name = shift; # e.g. wl_8 + my $from = shift; # e.g. 2008-01-01 + my $to = shift; # e.g. 2009-01-01 + my $confp = shift; # lines from the .gplot file, w/o FileLog and plot + my $dp = shift; # pointer to data (one string) + my $plot = shift; # Plot lines from the .gplot file + + return "" if(!defined($dp)); my $th = 16; # "Font" height my ($x, $y) = (3*$th, 1.2*$th); # Rect offset @@ -47,15 +54,22 @@ SVG_render($$$$$) pO "\n"; pO "\n"; pO "\n"; - pO "\n"; + pO "\n"; +# pO "