diff --git a/fhem/webfrontend/pgm2/01_FHEMWEB.pm b/fhem/webfrontend/pgm2/01_FHEMWEB.pm index c1e180a7e..ab8e92c0e 100755 --- a/fhem/webfrontend/pgm2/01_FHEMWEB.pm +++ b/fhem/webfrontend/pgm2/01_FHEMWEB.pm @@ -9,7 +9,7 @@ use IO::Socket; ################### # Config -my $__ME; +use vars qw($__ME); my $FHEMWEBdir; my $FHEMWEB_tmpfile = "/tmp/file.$$"; my $FHEMWEB_reldoc; @@ -27,15 +27,16 @@ sub FHEMWEB_digestCgi($); sub FHEMWEB_doDetail($); sub FHEMWEB_fileList($); sub FHEMWEB_makeTable($$$$$$$$); -sub FHEMWEB_parseXmlList(); +sub FHEMWEB_parseXmlList($); sub FHEMWEB_showRoom(); sub FHEMWEB_showArchive($); sub FHEMWEB_showLog($); sub FHEMWEB_showLogWrapper($); -sub FHEMWEB_popup($$$); +sub FHEMWEB_select($$$); sub FHEMWEB_textfield($$); sub FHEMWEB_submit($$); -sub FHEMWEB_roomOverview(); +sub FHEMWEB_style($$); +sub FHEMWEB_roomOverview($); sub FHEMWEB_fatal($); sub pF($@); sub pO(@); @@ -45,24 +46,28 @@ sub FHEMWEB_calcWeblink($$); ######################### # As we are _not_ multithreaded, it is safe to use global variables. -my %__icons; -my $__iconsread; -my %__rooms; -my %__devs; -my %__types; -my $__room; -my $__detail; -my $__title; -my $__cmdret; -my $__scrolledweblinkcount; -my %__wlpos; -my $__RET; -my $__RETTYPE; -my $__SF; -my $__ti; # Tabindex for all input fields -my @__zoom; -my %__zoom; -my $__plotmode; +my %__icons; # List of icons +my $__iconsread; # Timestamp of last icondir check +my %__rooms; # hash of all rooms +my %__devs; # hash of all devices ant their attributes +my %__types; # device types, for sorting +my $__room; # currently selected room +my $__detail; # durrently selected device for detail view +my $__title; # Page title +my $__cmdret; # Returned data by the fhem call +my $__scrolledweblinkcount; # Number of scrolled weblinks +my %__wlpos; # WebLink scroll position +my $__RET; # Returned data (html) +my $__RETTYPE; # image/png or the like +my $__SF; # Short for submit form +my $__ti; # Tabindex for all input fields +my @__zoom; # "day","week","month","year" +my %__zoom; # the same as @__zoom +my $__plotmode; # Current plotmode +my $__plotsize; # Size for a plot +my $__data; # Filecontent from browser when editing a file +my $__svgloaded; # Do not load the SVG twice +my $__lastxmllist; # last time xmllist was parsed ##################################### @@ -75,7 +80,7 @@ FHEMWEB_Initialize($) $hash->{DefFn} = "FHEMWEB_Define"; $hash->{UndefFn} = "FHEMWEB_Undef"; - $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 webdir webname plotmode:gnuplot,gnuplot-scroll,SVG"; + $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 webname plotmode:gnuplot,gnuplot-scroll,SVG plotsize"; } ##################################### @@ -158,8 +163,7 @@ FHEMWEB_Read($) my $name = $hash->{SNAME}; my $ll = GetLogLevel($name,4); - $FHEMWEBdir = ($attr{$name} && $attr{$name}{webdir}) ? - $attr{$name}{webdir} : "$attr{global}{modpath}/FHEM"; + $FHEMWEBdir = "$attr{global}{modpath}/FHEM"; $__ME = "/" . (($attr{$name} && $attr{$name}{webname}) ? $attr{$name}{webname} : "fhem"); $FHEMWEB_reldoc = "$__ME/commandref.html"; @@ -186,18 +190,20 @@ FHEMWEB_Read($) $hash->{BUF} = ""; Log($ll, "HTTP $hash->{NAME} GET $arg"); - $__plotmode = $attr{$name}{plotmode} ? $attr{$name}{plotmode} : "gnuplot"; + $__plotmode = $attr{$name}{plotmode} ? $attr{$name}{plotmode} : "SVG"; + $__plotsize = $attr{$name}{plotsize} ? $attr{$name}{plotsize} : "800,200"; - FHEMWEB_AnswerCall($arg); + my $cacheable = FHEMWEB_AnswerCall($arg); my $c = $hash->{CD}; my $l = length($__RET); -# my $exp = localtime(time()+300) . " GMT"; -# "Expires: $exp\r\n", - print $c "HTTP/1.1 200 OK\r\n", - "Content-Length: $l\r\n", - "Content-Type: $__RETTYPE\r\n\r\n", - $__RET; + my $e = ($cacheable? ("Expires: ".localtime(time()+900)." GMT\r\n") : ""); + #Log 0, "$arg / RL: $l"; + print $c "HTTP/1.1 200 OK\r\n", + "Content-Length: $l\r\n", + $e, + "Content-Type: $__RETTYPE\r\n\r\n", + $__RET; } @@ -206,50 +212,55 @@ FHEMWEB_AnswerCall($) { my ($arg) = @_; - %__rooms = (); - %__devs = (); %__wlpos = (); - %__types = (); $__room = ""; $__detail = ""; - $__title = ""; $__cmdret = ""; $__RET = ""; $__RETTYPE = "text/html; charset=ISO-8859-1"; $__ti = 1; # Lets go: - if($arg =~ m/^$FHEMWEB_reldoc/) { - open(FH, "$FHEMWEBdir/commandref.html") || return; + if($arg =~ m,^${__ME}/(.*html)$, || $arg =~ m,^${__ME}/(.*svg)$,) { + my $f = $1; + open(FH, "$FHEMWEBdir/$f") || return; pO join("", ); close(FH); - return; - } elsif($arg =~ m,^$__ME/style.css,) { - open(FH, "$FHEMWEBdir/style.css") || return; + $__RETTYPE = "text/html; charset=ISO-8859-1" if($f =~ m/\.*html$/); + return 1; + } elsif($arg =~ m,^$__ME/(.*).css,) { + open(FH, "$FHEMWEBdir/$1.css") || return; pO join("", ); close(FH); $__RETTYPE = "text/css"; - return; + return 1; } elsif($arg =~ m,^$__ME/icons/(.*)$,) { open(FH, "$FHEMWEBdir/$1") || return; pO join("", ); close(FH); - $__RETTYPE = "image/gif"; - return; + $__RETTYPE = "image/*"; + return 1; } elsif($arg !~ m/^$__ME(.*)/) { Log(5, "Unknown document $arg requested"); - return; + return 0; } my $cmd = FHEMWEB_digestCgi($1); + my $docmd = 0; + $docmd = 1 if($cmd && + $cmd !~ /^showlog/ && + $cmd !~ /^toweblink/ && + $cmd !~ /^showarchive/ && + $cmd !~ /^style / && + $cmd !~ /^edit/); - $__cmdret = fC($cmd) if($cmd && - $cmd !~ /^showlog/ && - $cmd !~ /^toweblink/ && - $cmd !~ /^showarchive/ && - $cmd !~ /^edit/); - FHEMWEB_parseXmlList(); - return FHEMWEB_showLog($cmd) if($cmd =~ m/^showlog /); + + $__cmdret = fC($cmd) if($docmd); + FHEMWEB_parseXmlList($docmd); + if($cmd =~ m/^showlog /) { + FHEMWEB_showLog($cmd); + return 0; + } if($cmd =~ m/^toweblink (.*)$/) { my @aa = split(":", $1); @@ -262,13 +273,13 @@ FHEMWEB_AnswerCall($) $__cmdret = fC("define wl_$max weblink fileplot $aa[0]:$aa[1]:$aa[2]"); if(!$__cmdret) { $__detail = "wl_$max"; - FHEMWEB_parseXmlList() + FHEMWEB_parseXmlList(1); } } - pO "$__title"; - pO ""; - pO "\n"; + pO "\n\n$__title\n"; + pO "\n"; + pO "\n\n"; if($__cmdret) { $__detail = ""; @@ -280,12 +291,14 @@ FHEMWEB_AnswerCall($) pO "\n"; } - FHEMWEB_roomOverview(); + FHEMWEB_roomOverview($cmd); + FHEMWEB_style($cmd,undef) if($cmd =~ m/^style /); FHEMWEB_doDetail($__detail) if($__detail); FHEMWEB_showRoom() if($__room && !$__detail); FHEMWEB_showLogWrapper($cmd) if($cmd =~ /^showlogwrapper/); FHEMWEB_showArchive($cmd) if($cmd =~ m/^showarchive/); pO ""; + return 0; } @@ -303,7 +316,9 @@ FHEMWEB_digestCgi($) $pv =~ s/\+/ /g; $pv =~ s/%(..)/chr(hex($1))/ge; my ($p,$v) = split("=",$pv, 2); - $v =~ s/[\r]\n/\\\n/g; # Multiline: escape the NL for fhem + + # Multiline: escape the NL for fhem + $v =~ s/[\r]\n/\\\n/g if($v && $p && $p ne "data"); #Log(0, "P: $p, V: $v"); if($p eq "detail") { $__detail = $v; } @@ -314,7 +329,7 @@ FHEMWEB_digestCgi($) if($p =~ m/^dev\.(.*)$/) { $dev{$1} = $v; } if($p =~ m/^cmd\.(.*)$/) { $cmd = $v; $c= $1; } if($p eq "wlpos") { %__wlpos = split(/[=;]/, $v); } - + if($p eq "data") { $__data = $v; } } $cmd.=" $dev{$c}" if($dev{$c}); @@ -326,9 +341,22 @@ FHEMWEB_digestCgi($) ##################### # Get the data and parse it. We are parsing XML in a non-scientific way :-) sub -FHEMWEB_parseXmlList() +FHEMWEB_parseXmlList($) { + my $docmd = shift; my $name; + + if(!$docmd && $__lastxmllist && (time() - $__lastxmllist) < 2) { + $__room = $__devs{$__detail}{ATTR}{room}{VAL} if($__detail); + return; + } + + $__lastxmllist = time(); + %__rooms = (); + %__devs = (); + %__types = (); + $__title = ""; + foreach my $l (split("\n", fC("xmllist"))) { ####### Device @@ -343,7 +371,7 @@ FHEMWEB_parseXmlList() ####### INT, ATTR & STATE if($l =~ m,^\t\t\t<(.*) key="(.*)" value="([^"]*)"(.*)/>,) { my ($t, $n, $v, $m) = ($1, $2, $3, $4); - $v =~ s/<br>/
/g; + $v =~ s,<br>,
,g; $__devs{$name}{$t}{$n}{VAL} = $v; if($m) { $m =~ m/measured="(.*)"/; @@ -411,12 +439,13 @@ FHEMWEB_makeTable($$$$$$$$) } pO "\n"; if($clist) { + pO "\n"; my @al = map { s/[:;].*//;$_ } split(" ", $clist); - pO "" . FHEMWEB_popup("arg.$ccmd$d",\@al,undef) . ""; + pO "" . FHEMWEB_select("arg.$ccmd$d",\@al,undef) . ""; pO "" . FHEMWEB_textfield("val.$ccmd$d", 6) . ""; pO "" . FHEMWEB_submit("cmd.$ccmd$d", $ccmd) . ""; pO FHEMWEB_hidden("dev.$ccmd$d", $d); - pO "\n"; + pO "\n"; } my $row = 1; @@ -436,13 +465,13 @@ FHEMWEB_makeTable($$$$$$$$) } pO "$hash->{$v}{TIM}" if($hash->{$v}{TIM}); - pO "$cmd" + pO "$cmd" if($cmd); pO "\n"; } pO " \n"; - pO "
\n"; + pO "
\n"; } @@ -531,13 +560,14 @@ FHEMWEB_doDetail($) ############## # Room overview sub -FHEMWEB_roomOverview() +FHEMWEB_roomOverview($) { + my ($cmd) = @_; pO $__SF; pO "
\n"; pO "\n"; } pO "
"; - pO "Cmd: "; + pO "Fhem cmd: "; pO FHEMWEB_textfield("cmd", 30); $__scrolledweblinkcount = 0; if($__room) { @@ -558,8 +588,8 @@ FHEMWEB_roomOverview() pO "\n"; pO "
\n"; - pO " "; if($iname) { @@ -698,6 +735,7 @@ FHEMWEB_showRoom() } elsif($type eq "FHT") { $v = $__devs{$d}{STATE}{"measured-temp"}{VAL}; + $v = "" if(!defined($v)); $v =~ s/ .*//; pO ""; @@ -709,7 +747,7 @@ FHEMWEB_showRoom() pO FHEMWEB_hidden("arg.$d", "desired-temp"); pO FHEMWEB_hidden("dev.$d", $d); pO ""; } elsif($type eq "FileLog") { @@ -723,8 +761,10 @@ FHEMWEB_showRoom() my %h = ("VAL" => "text"); $l = \%h; } + my @fl = FHEMWEB_fileList($__devs{$d}{INT}{logfile}{VAL}); - foreach my $f (FHEMWEB_fileList($__devs{$d}{INT}{logfile}{VAL})) { + foreach my $f (@fl) { + pF " "; pF " ", $row?"odd":"even"; $row = ($row+1)%2; foreach my $ln (split(",", $l->{VAL})) { @@ -732,7 +772,6 @@ FHEMWEB_showRoom() $name = $lt if(!$name); pO ""; } - pO ""; } } elsif($type eq "weblink") { @@ -752,17 +791,25 @@ FHEMWEB_showRoom() } pO "
\n"; # Need for "right" compatibility - pO " \n"; + pO "
\n"; + pO " \n"; pO "
\n"; + pO " \n"; $__room = "" if(!$__room); foreach my $r (sort keys %__rooms) { next if($r eq "hidden"); @@ -567,12 +597,18 @@ FHEMWEB_roomOverview() pO "\n"; } - pF " ", "all" eq $__room ? " class=\"sel\"" : ""; - pO ""; - pO " \n"; - + pO ""; pO "
$r"; pO "
All together
All together
\n"; + pO "
\n"; + pO " \n"; + pO " \n"; + pO " \n"; + my $sel = ($cmd =~ m/^style/) ? " class=\"sel\"" : ""; + pO " \n"; + pO "
Howto
Details
Misc. files
\n"; + pO "
\n"; pO "\n"; pO "\n"; @@ -580,7 +616,7 @@ FHEMWEB_roomOverview() ################# # Read in the icons - sub +sub FHEMWEB_checkDirs() { return if($__iconsread && (time() - $__iconsread) < 5); @@ -623,7 +659,7 @@ FHEMWEB_showRoom() next if(!$havedev); } - my $rf = ($__room ? "&room=$__room" : ""); + my $rf = ($__room ? "&room=$__room" : ""); ############################ @@ -682,6 +718,7 @@ FHEMWEB_showRoom() $iname = $__icons{"$d"} if($__icons{"$d"}); $iname = $__icons{"$d.$iv"} if($__icons{"$d.$iv"}); } + $v = "" if(!defined($v)); pO "
$d$d" . - FHEMWEB_popup("val.$d",\@tv,$v) . + FHEMWEB_select("val.$d",\@tv,$v) . FHEMWEB_submit("cmd.$d", "set") . "
$f$name
"; + pO "$d"; pO "
"; - my $wl = ""; $__wlpos{$va[0]} = $__wlpos{$d} if($__wlpos{$d}); - $wl = "&wlpos=" . join(";", map { "$_=$__wlpos{$_}" } - grep { /(zoom|all|$va[0])/ } keys %__wlpos); - - pO ""; + + my $wl = "&wlpos=" . join(";", map { "$_=$__wlpos{$_}" } + grep { /(zoom|all|$va[0])/ } keys %__wlpos); + + my $arg="$__ME?cmd=showlog $d $va[0] $va[1] $va[2]$wl"; + if($__plotmode eq "SVG") { + my ($w, $h) = split(",", $__plotsize); + pO "\n"; + } else { + pO "\n"; + } + pO ""; FHEMWEB_zoomLink("$d=-1", "Prev.png", "prev", 1); FHEMWEB_zoomLink("$d=1", "Next.png", "next", 1); - pO "$d
"; } @@ -774,7 +821,7 @@ FHEMWEB_showRoom() pO "
\n"; - pO "
\n"; # Empty line + pO "
\n"; # Empty line } pO " \n\n"; pO "
\n"; @@ -782,6 +829,7 @@ FHEMWEB_showRoom() } ################# +# return a sorted list of actual files for a given FileLog type string sub FHEMWEB_fileList($) { @@ -827,10 +875,19 @@ FHEMWEB_showLogWrapper($) } else { pO "
\n"; - pO "\n"; - pO "
\n"; - pO ""; + pO "
"; - pO "
Convert to weblink
\n"; + pO ""; pO "
\n"; + pO ""; + my $arg = "$__ME?cmd=showlog undef $d $type $file"; + if($__plotmode eq "SVG") { + my ($w, $h) = split(",", $__plotsize); + pO "\n"; + } else { + pO "\n"; + } + + pO "
Convert to weblink
\n"; pO "
\n"; pO "
\n"; @@ -838,6 +895,7 @@ FHEMWEB_showLogWrapper($) } ###################### +# Generate an image from the log via gnuplot sub FHEMWEB_showLog($) { @@ -846,42 +904,92 @@ FHEMWEB_showLog($) my $gplot_pgm = "$FHEMWEBdir/$type.gplot"; return FHEMWEB_fatal("Cannot read $gplot_pgm") if(!-r $gplot_pgm); - FHEMWEB_calcWeblink($d,$wl); - if($__plotmode eq "gnuplot" || !$__devs{$d}{from}) { - # Looking for the logfile.... + if($__plotmode =~ m/gnuplot/) { + if($__plotmode eq "gnuplot" || !$__devs{$d}{from}) { - $__devs{$d}{INT}{logfile}{VAL} =~ m,^(.*)/([^/]*)$,; # Dir and File - my $path = "$1/$file"; - $path = $__devs{$d}{ATTR}{archivedir}{VAL} . "/$file" if(!-f $path); - return FHEMWEB_fatal("Cannot read $path") if(!-r $path); + # Looking for the logfile.... - open(FH, $gplot_pgm) || FHEMWEB_fatal("$gplot_pgm: $!"); - my $gplot_script = join("", ); - close(FH); - $gplot_script =~ s//$FHEMWEB_tmpfile/g; - $gplot_script =~ s//$path/g; - $gplot_script =~ s//$file/g; + $__devs{$d}{INT}{logfile}{VAL} =~ m,^(.*)/([^/]*)$,; # Dir and File + my $path = "$1/$file"; + $path = $__devs{$d}{ATTR}{archivedir}{VAL} . "/$file" if(!-f $path); + return FHEMWEB_fatal("Cannot read $path") if(!-r $path); - if($__devs{$wl} && $__devs{$wl}{ATTR}{fixedrange}) { - my $fr = $__devs{$wl}{ATTR}{fixedrange}{VAL}; - $fr =~ s/ /\":\"/; - $fr = "set xrange [\"$fr\"]\n"; - $gplot_script =~ s/(set timefmt ".*")/$1\n$fr/; + open(FH, $gplot_pgm) || return FHEMWEB_fatal("$gplot_pgm: $!"); + my $gplot_script = join("", ); + close(FH); + + $gplot_script =~ s//$FHEMWEB_tmpfile/g; + $gplot_script =~ s//$__plotsize/g; + $gplot_script =~ s//$path/g; + $gplot_script =~ s//$file/g; + + if($__devs{$wl} && $__devs{$wl}{ATTR}{fixedrange}) { + my $fr = $__devs{$wl}{ATTR}{fixedrange}{VAL}; + $fr =~ s/ /\":\"/; + $fr = "set xrange [\"$fr\"]\n"; + $gplot_script =~ s/(set timefmt ".*")/$1\n$fr/; + } + + open(FH, "|gnuplot > /dev/null");# feed it to gnuplot + print FH $gplot_script; + close(FH); + + } elsif($__plotmode eq "gnuplot-scroll") { + + ############################ + # Read in the template gnuplot file. Digest the #FileLog lines. Replace + # the plot directive with our own, as we offer a file for each line + my (@filelog, @data, $plot); + open(FH, $gplot_pgm) || return FHEMWEB_fatal("$gplot_pgm: $!"); + while(my $l = ) { + if($l =~ m/^#FileLog (.*)$/) { + push(@filelog, $1); + } elsif($l =~ "^plot" || $plot) { + $plot .= $l; + } else { + push(@data, $l); + } + } + close(FH); + + my $gplot_script = join("", @data); + $gplot_script =~ s//$FHEMWEB_tmpfile/g; + $gplot_script =~ s//$__plotsize/g; + $gplot_script =~ s//$file/g; + + my ($f,$t)=($__devs{$d}{from}, $__devs{$d}{to}); + + my @path = split(" ", fC("get $d $file $FHEMWEB_tmpfile $f $t " . + join(" ", @filelog))); + my $i = 0; + $plot =~ s/\".*?using 1:[^ ]+ /"\"$path[$i++]\" using 1:2 "/gse; + my $xrange = "set xrange [\"$f\":\"$t\"]\n"; + foreach my $p (@path) { # If the file is empty, write a 0 line + next if(!-z $p); + open(FH, ">$p"); + print FH "$f 0\n"; + close(FH); + } + + open(FH, "|gnuplot > /dev/null");# feed it to gnuplot + print FH $gplot_script, $xrange, $plot; + close(FH); + foreach my $p (@path) { + unlink($p); + } } - - open(FH, "|gnuplot > /dev/null");# feed it to gnuplot - print FH $gplot_script; + $__RETTYPE = "image/png"; + open(FH, "$FHEMWEB_tmpfile.png"); # read in the result and send it + pO join("", ); close(FH); + unlink("$FHEMWEB_tmpfile.png"); - } else { # gnuplot-scroll + } elsif($__plotmode eq "SVG") { - ############################ - # Read in the template gnuplot file. Digest the #FileLog lines. Replace - # the plot directive with our own, as we offer a file for each line my (@filelog, @data, $plot); - open(FH, $gplot_pgm) || FHEMWEB_fatal("$gplot_pgm: $!"); + open(FH, $gplot_pgm) || return FHEMWEB_fatal("$gplot_pgm: $!"); while(my $l = ) { if($l =~ m/^#FileLog (.*)$/) { push(@filelog, $1); @@ -892,41 +1000,21 @@ FHEMWEB_showLog($) } } close(FH); - - my $gplot_script = join("", @data); - $gplot_script =~ s//$FHEMWEB_tmpfile/g; - $gplot_script =~ s//$file/g; - my ($f,$t)=($__devs{$d}{from}, $__devs{$d}{to}); + $f = 0 if(!$f); # From the beginning of time... + $t = 9 if(!$t); # till the end - my @path = split(" ", fC("get $d $file $FHEMWEB_tmpfile $f $t " . - join(" ", @filelog))); - my $i = 0; - $plot =~ s/\".*?using 1:[^ ]+ /"\"$path[$i++]\" using 1:2 "/gse; - my $xrange = "set xrange [\"$f\":\"$t\"]\n"; - foreach my $p (@path) { - next if(!-z $p); - open(FH, ">$p"); - print FH "$f 0\n"; - close(FH); - } + my $ret = fC("get $d $file - $f $t " . join(" ", @filelog)); + SVG_render($file, $__plotsize, $f, $t, \@data, \$ret, $plot); + $__RETTYPE = "image/svg+xml"; - open(FH, "|gnuplot > /dev/null");# feed it to gnuplot - print FH $gplot_script, $xrange, $plot; - close(FH); - foreach my $p (@path) { - unlink($p); - } } - $__RETTYPE = "image/png"; - open(FH, "$FHEMWEB_tmpfile.png"); # read in the result and send it - pO join("", ); - close(FH); - unlink("$FHEMWEB_tmpfile.png"); } + + ################## sub FHEMWEB_fatal($) @@ -944,8 +1032,9 @@ FHEMWEB_hidden($$) } ################## +# Generate a select field with option list sub -FHEMWEB_popup($$$) +FHEMWEB_select($$$) { my ($n, $va, $def) = @_; my $s = ""; @@ -989,7 +1081,7 @@ FHEMWEB_makeEdit($$$$) "tabindex=\"$__ti\" value=\"$eval\"/>"; } $__ti++; - pO "
" . FHEMWEB_submit("cmd.${cmd}$name", "$cmd $name"); + pO "
" . FHEMWEB_submit("cmd.${cmd}$name", "$cmd $name"); pO ""; $eval = "
$eval
" if($eval =~ m/\n/); pO "
$eval
"; @@ -1007,6 +1099,7 @@ FHEMWEB_submit($$) } ################## +# Generate the zoom and scroll images with links if appropriate sub FHEMWEB_zoomLink($$$$) { @@ -1020,7 +1113,7 @@ FHEMWEB_zoomLink($$$$) my $val = $__wlpos{$d}; - $cmd = "room=$__room&wlpos="; + $cmd = "room=$__room&wlpos="; if($d eq "zoom") { $val = "day" if(!$val); @@ -1046,7 +1139,7 @@ FHEMWEB_zoomLink($$$$) pO ""; pO "\"$alt\""; - pO "
" if($br); + pO "
" if($br); } ################## @@ -1131,6 +1224,62 @@ FHEMWEB_calcWeblink($$) } ################## +# List/Edit/Save css and gnuplot files +sub +FHEMWEB_style($$) +{ + my ($cmd, $msg) = @_; + my @a = split(" ", $cmd); + + if($a[1] eq "list") { + + my @fl = FHEMWEB_fileList("$FHEMWEBdir/.*.css"); + push(@fl, "
"); + push(@fl, FHEMWEB_fileList("$FHEMWEBdir/.*.gplot")); + push(@fl, "
"); + push(@fl, FHEMWEB_fileList("$FHEMWEBdir/.*html")); + pO "
\n"; + pO "
\n"; + pO " $msg

\n" if($msg); + pO " \n"; + my $row = 0; + foreach my $file (@fl) { + pO ""; + pO ""; + $row = ($row+1)%2; + } + pO "
$file
\n"; + pO "
\n"; + pO "
\n"; + + } elsif($a[1] eq "edit") { + + open(FH, "$FHEMWEBdir/$a[2]") || return FHEMWEB_fatal("$a[2]: $!"); + my $data = join("", ); + close(FH); + + pO "
\n"; + pO "
"; + pO FHEMWEB_submit("save", "Save $a[2]") . "

"; + pO FHEMWEB_hidden("cmd", "style save $a[2]"); + pO ""; + pO "
"; + pO "
\n"; + + } elsif($a[1] eq "save") { + + open(FH, ">$FHEMWEBdir/$a[2]") || return FHEMWEB_fatal("$a[2]: $!"); + print FH $__data; + close(FH); + FHEMWEB_style("style list", "Saved file $a[2]"); + + } + +} + +################## +# print formatted sub pF($@) { @@ -1139,6 +1288,7 @@ pF($@) } ################## +# print output sub pO(@) { @@ -1146,12 +1296,14 @@ pO(@) } ################## +# fhem command sub fC($) { my ($cmd) = @_; + #Log 0, "Calling $cmd"; my $oll = $attr{global}{verbose}; - $attr{global}{verbose} = 0; + $attr{global}{verbose} = 0 if($cmd ne "save"); my $ret = AnalyzeCommand(undef, $cmd); if($cmd !~ m/attr.*global.*verbose/) { $attr{global}{verbose} = $oll; diff --git a/fhem/webfrontend/pgm2/98_SVG.pm b/fhem/webfrontend/pgm2/98_SVG.pm new file mode 100755 index 000000000..d85d9cafe --- /dev/null +++ b/fhem/webfrontend/pgm2/98_SVG.pm @@ -0,0 +1,380 @@ +############################################## +package main; + +use strict; +use warnings; +use POSIX; + +sub SVG_render($$$$$$$); +sub time_to_sec($); +sub fmtTime($$); + +my ($__lt, $__ltstr); + +##################################### +sub +SVG_Initialize($) +{ + my ($hash) = @_; +} + + +##################################### +sub +SVG_render($$$$$$$) +{ + my ($file, $wh, $from, $to, $confp, $dp, $plot) = @_; + + my ($ow,$oh) = split(",", $wh); # Original width + my $th = 16; # "Font" height + my ($x, $y) = (3*$th, 1.5*$th); # Rect offset + my ($w, $h) = ($ow-2*$x, $oh-2*$y); # Rect size + my %conf; # gnuplot file settings + + # Convert the configuration to a "readable" form -> array to hash + map { chomp; my @a=split(" ",$_, 3); + if($a[0] && $a[0] eq "set") { $conf{$a[1]} = $a[2]; } } @{$confp}; + + # Html Header + pO "\n"; + pO "\n"; + pO "\n"; + pO "\n"; + + # Rectangle + pO "\n"; + + my ($off1,$off2) = ($ow/2, 3*$y/4); + pO "$file\n"; + + my $t = ($conf{ylabel} ? $conf{ylabel} : ""); + $t =~ s/"//g; + ($off1,$off2) = (3*$th/4, $oh/2); + pO "$t\n"; + + $t = ($conf{y2label} ? $conf{y2label} : ""); + $t =~ s/"//g; + ($off1,$off2) = ($ow-$th/4, $oh/2); + pO "$t\n"; + + # Digest axes/title/type from $plot (gnuplot) and draw the line-titles + my (@axes,@ltitle,@type); + my $i; + $i = 0; $plot =~ s/ axes (\w+)/$axes[$i++]=$1/gse; + $i = 0; $plot =~ s/ title '([^']*)'/$ltitle[$i++]=$1/gse; + $i = 0; $plot =~ s/ with (\w+)/$type[$i++]=$1/gse; + + for my $i (0..int(@type)-1) { # axes is optional + $axes[$i] = "x1y2" if(!$axes[$i]); + } + + ($off1,$off2) = ($ow-$x-$th, $y+$th); + for my $i (0..int(@ltitle)-1) { + pO "$ltitle[$i]\n"; + $off2 += $th; + } + + + # Loop over the input, digest dates, calculate min/max values + my ($fromsec, $tosec); + $fromsec = time_to_sec($from) if($from ne "0"); # 0 is special + $tosec = time_to_sec($to) if($to ne "9"); # 9 is special + my $tmul; + $tmul = $w/($tosec-$fromsec) if($tosec && $fromsec); + + my ($min, $max, $idx) = (99999999, -99999999, 0); + my (%hmin, %hmax, @hdx, @hdy); + my ($dxp, $dyp) = (\(), \()); + + my ($d, $v); + foreach my $l (split("\n", $$dp)) { + if($l =~ m/^#/) { + my $a = $axes[$idx]; + $hmin{$a} = $min if(!defined($hmin{$a}) || $hmin{$a} > $min); + $hmax{$a} = $max if(!defined($hmax{$a}) || $hmax{$a} < $max); + ($min, $max) = (99999999, -99999999); + $hdx[$idx] = $dxp; $hdy[$idx] = $dyp; + ($dxp, $dyp) = (\(), \()); + $idx++; + + } else { + ($d, $v) = split(" ", $l); + push @{$dxp}, ($tmul ? int((time_to_sec($d)-$fromsec)*$tmul) : $d); + push @{$dyp}, $v; + $min = $v if($min > $v); + $max = $v if($max < $v); + + } + } + + $dxp = $hdx[0]; + if(int(@{$dxp}) < 2 && !$tosec) { # not enough data and no range... + pO "\n"; + return; + } + + if(!$tmul) { # recompute the x data if no range sepcified + $fromsec = time_to_sec($dxp->[0]) if(!$fromsec); + $tosec = time_to_sec($dxp->[int(@{$dxp})-1]) if(!$tosec); + $tmul = $w/($tosec-$fromsec); + + for my $i (0..@hdx-1) { + $dxp = $hdx[$i]; + for my $i (0..@{$dxp}-1) { + $dxp->[$i] = int((time_to_sec($dxp->[$i])-$fromsec)*$tmul); + } + } + } + + + # Compute & draw vertical tics, grid and labels + my $ddur = ($tosec-$fromsec)/86400; + my ($first_tag, $tag, $step, $tstep, $aligntext, $aligntics); + if($ddur <= 1) { + $first_tag=". 2 1"; $tag=": 3 4"; $step = 4*3600; $tstep = 3600; + } elsif ($ddur <= 7) { + $first_tag=". 6"; $tag=". 2 1"; $step = 24*3600; $tstep = 6*3600; + } elsif ($ddur <= 31) { + $first_tag=". 6"; $tag=". 2 1"; $step = 7*24*3600; $tstep = 24*3600; + $aligntext = 1; + } else { + $first_tag=". 6"; $tag=". 1"; $step = 28*24*3600; $tstep = 28*24*3600; + $aligntext = 2; $aligntics = 2; + } + + # First the tics + $off2 = $y+4; + my ($off3, $off4) = ($y+$h-4, $y+$h); + my $initoffset = $tstep; + $initoffset = int(($tstep/2)/86400)*86400 if($aligntics); + for(my $i = $fromsec+$initoffset; $i < $tosec; $i += $tstep) { + $i = time_align($i,$aligntics); + $off1 = int($x+($i-$fromsec)*$tmul); + pO "\n"; + pO "\n"; + } + + # then the text and the grid + $off1 = $x; + $off2 = $y+$h+$th; + $t = fmtTime($first_tag, $fromsec); + pO "$t"; + $initoffset = $step; + $initoffset = int(($step/2)/86400)*86400 if($aligntext); + for(my $i = $fromsec+$initoffset; $i < $tosec; $i += $step) { + $i = time_align($i,$aligntext); + $off1 = int($x+($i-$fromsec)*$tmul); + pO "\n"; + $t = fmtTime($tag, $i); + pO "$t"; + } + + + # Left and right axis tics / text / grid + $hmin{x1y1}=$hmin{x1y2}, $hmax{x1y1}=$hmax{x1y2} if(!defined($hmin{x1y1})); + $hmin{x1y2}=$hmin{x1y1}, $hmax{x1y2}=$hmax{x1y1} if(!defined($hmin{x1y2})); + + + for my $axis ("x1y1", "x1y2") { + + # Round values, compute a nice step + my $dh = $hmax{$axis} - $hmin{$axis}; + my ($step, $mi, $ma); + my @limit = (1,2,5,10,20,50,100,200,500,1000,2000,5000,10000); + for my $li (0..int(@limit)-1) { + my $l = $limit[$li]; + next if($dh > $l); + $ma = doround($hmax{$axis}, $l/10, 1); + $mi = doround($hmin{$axis}, $l/10, 0); + + if(($ma-$mi)/($l/10) >= 7) { # If more then 7 steps, then choose next + $l = $limit[$li+1]; + $ma = doround($hmax{$axis}, $l/10, 1); + $mi = doround($hmin{$axis}, $l/10, 0); + } + $step = $l/10; + last; + } + + # yrange handling + my $yr = ($axis eq "x1y1" ? "yrange" : "y2range"); + if($conf{$yr} && $conf{$yr} =~ /\[(.*):(.*)\]/) { + $mi = $1 if($1 ne ""); + $ma = $2 if($2 ne ""); + } + $hmax{$axis} = $ma; + $hmin{$axis} = $mi; + + # Draw the horizontal values and grid + my $hmul = $h/($ma-$mi); + $off1 = ($axis eq "x1y1" ? $x-$th*0.3 : $x+$w+$th*0.3); + $off3 = ($axis eq "x1y1" ? $x : $x+$w-5); + $off4 = $off3+5; + + $yr = ($axis eq "x1y1" ? "ytics" : "y2tics"); + my $tic = $conf{$yr}; + if($tic && $tic !~ m/mirror/) { # Tics specified in the configfile + $tic =~ s/^\((.*)\)$/$1/; # Strip () + foreach my $onetic (split(",", $tic)) { + $onetic =~ s/^ *(.*) *$/$1/; + my ($tlabel, $tvalue) = split(" ", $onetic); + $tlabel =~ s/^"(.*)"$/$1/; + + $off2 = int($y+($ma-$tvalue)*$hmul); + pO "\n"; + $off2 += $th/4; + my $align = ($axis eq "x1y1" ? " text-anchor=\"end\"" : ""); + pO " + $tlabel"; + } + + } else { # Auto-tic + + for(my $i = $mi; $i <= $ma; $i += $step) { + $off2 = int($y+($ma-$i)*$hmul); + pO "\n"; + if($axis eq "x1y2") { + my $o6 = $x+$w; + pO "\n"; + } + $off2 += $th/4; + my $align = ($axis eq "x1y1" ? " text-anchor=\"end\"" : ""); + pO "$i"; + } + } + + } + + + # Second loop over the data: draw the measured points + for my $idx (0..int(@hdx)-1) { + my $a = $axes[$idx]; + $min = $hmin{$a}; + $hmax{$a} += 1 if($min == $hmax{$a}); # Else division by 0 in the next line + my $hmul = $h/($hmax{$a}-$min); + my $ret = ""; + my ($dxp, $dyp) = ($hdx[$idx], $hdy[$idx]); + + if($type[$idx] eq "points" ) { + + foreach my $i (0..int(@{$dxp})-1) { + my ($x1, $y1) = ($x+$dxp->[$i], $y+$h-($dyp->[$i]-$min)*$hmul); + $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); + pO "\n"; + } + + } elsif($type[$idx] eq "steps" ) { + + if(@{$dxp} == 1) { + my $y1 = $y+$h-($dyp->[0]-$min)*$hmul; + $ret .= sprintf(" %d,%d %d,%d %d,%d %d,%d", + $x,$y+$h, $x,$y1, $x+$w,$y1, $x+$w,$y+$h); + } else { + foreach my $i (1..int(@{$dxp})-1) { + my ($x1, $y1) = ($x+$dxp->[$i-1], $y+$h-($dyp->[$i-1]-$min)*$hmul); + my ($x2, $y2) = ($x+$dxp->[$i], $y+$h-($dyp->[$i] -$min)*$hmul); + $ret .= sprintf(" %d,%d %d,%d %d,%d", $x1,$y1, $x2,$y1, $x2,$y2); + } + } + pO "\n"; + + } elsif($type[$idx] eq "histeps" ) { + + if(@{$dxp} == 1) { + my $y1 = $y+$h-($dyp->[0]-$min)*$hmul; + $ret .= sprintf(" %d,%d %d,%d %d,%d %d,%d", + $x,$y+$h, $x,$y1, $x+$w,$y1, $x+$w,$y+$h); + } else { + foreach my $i (1..int(@{$dxp})-1) { + my ($x1, $y1) = ($x+$dxp->[$i-1], $y+$h-($dyp->[$i-1]-$min)*$hmul); + my ($x2, $y2) = ($x+$dxp->[$i], $y+$h-($dyp->[$i] -$min)*$hmul); + $ret .= sprintf(" %d,%d %d,%d %d,%d %d,%d", + $x1,$y1, ($x1+$x2)/2,$y1, ($x1+$x2)/2,$y2, $x2,$y2); + } + } + pO "\n"; + + } else { # lines and everything else + foreach my $i (0..int(@{$dxp})-1) { + $ret .= sprintf(" %d,%d", $x + $dxp->[$i], + $y + $h-($dyp->[$i]-$min)*$hmul); + } + pO "\n"; + } + + } + + pO "\n"; +} + +sub +time_to_sec($) +{ + my ($str) = @_; + my ($y,$m,$d,$h,$mi,$s) = split("[-_:]", $str); + $s = 0 if(!$s); + $mi= 0 if(!$mi); + $h = 0 if(!$h); + $d = 1 if(!$d); + $m = 1 if(!$m); + + if(!$__ltstr || $__ltstr ne "$y-$m-$d") { # 2.5x faster + $__lt = mktime(0,0,0,$d,$m-1,$y-1900,0,0,-1); + $__ltstr = "$y-$m-$d"; + } + return $s+$mi*60+$h*3600+$__lt; +} + +sub +fmtTime($$) +{ + my ($sepfmt, $sec) = @_; + my @tarr = split("[ :]+", localtime($sec)); + my ($sep, $fmt) = split(" ", $sepfmt, 2); + my $ret = ""; + for my $f (split(" ", $fmt)) { + $ret .= $sep if($ret); + $ret .= $tarr[$f]; + } + return $ret; +} + +sub +time_align($$) +{ + my ($v,$align) = @_; + return $v if(!$align); + if($align == 1) { # Look for the beginning of the week + for(;;) { + my @a = localtime($v); + return $v if($a[6] == 0); + $v += 86400; + } + } + if($align == 2) { # Look for the beginning of the month + for(;;) { + my @a = localtime($v); + return $v if($a[3] == 1); + $v += 86400; + } + } +} + +sub +doround($$$) +{ + my ($v, $step, $isup) = @_; + if($v >= 0) { + return (int($v/$step))*$step+($isup ? $step : 0); + } else { + return (int($v/$step))*$step+($isup ? 0 : -$step); + } +} +1; diff --git a/fhem/webfrontend/pgm2/HOWTO.html b/fhem/webfrontend/pgm2/HOWTO.html new file mode 100644 index 000000000..35bcb3aa9 --- /dev/null +++ b/fhem/webfrontend/pgm2/HOWTO.html @@ -0,0 +1,48 @@ + + + FHEMWEB Howto + + +

FHEMWEB Howto

+ + Starting
+ + +

Starting

+ + For a start create a minimal fhem config file fhem.cfg, like the + following:
+ +
+    attr global logfile /tmp/fhem.log
+    attr global modpath /usr/local/lib
+    attr global port 7072 global
+    attr global statefile /tmp/fhem.state
+
+    define WEB FHEMWEB 8083 global
+ + It is important that the modpath contains a directory called FHEM, where + all the necessary modules and other files are present, these modules should + not be found directly in modepath. Usually these are all the files + from the fhem package FHEM directory and webfrontend/pgm2 directory, and + some files from the contrib directory.
+ + + The logfile and the statefile should be changed from /tmp to a more stable directory, e.g. /var/log/FHEM or alike.
+ + Now you can start fhem via:
+      perl fhem.pl fhem.cfg
+ The logfile should look like: +
+      2008.06.15 16:17:03 2: FHEMWEB port 8083 opened
+      2008.06.15 16:17:03 0: Server started (version ...)
+    
+ You can connect to the server either via telnet (type a return after you get + the connection):

+ + telnet localhost 7072

+ or a little bit nicer via an internet browser:

+ " using 1:4 notitle with lines diff --git a/fhem/webfrontend/pgm2/fht.gplot b/fhem/webfrontend/pgm2/fht.gplot index d3d8d6c69..319114340 100644 --- a/fhem/webfrontend/pgm2/fht.gplot +++ b/fhem/webfrontend/pgm2/fht.gplot @@ -3,7 +3,7 @@ # FileLog definition: # define FileLog fhtlog1 fht1:.*(temp|actuator).* /var/log/fht1-%Y-%U.log # -set terminal png transparent size 800,200 crop +set terminal png transparent size crop set output '.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" @@ -17,9 +17,9 @@ set grid xtics y2tics set y2label "temperature (Celsius)" set ylabel "Actuator (%)" -#FileLog 4:measured: -##FileLog 4:desired: -#FileLog 4:actuator.*%:int +#FileLog 4:measured:0: +##FileLog 4:desired:0: +#FileLog 4:actuator.*[0-9]+%:0:int # "< awk '/desired/ {print $1, $4+0}' "\ # using 1:2 axes x1y2 title 'Desired temperature' with steps,\ diff --git a/fhem/webfrontend/pgm2/fs20.gplot b/fhem/webfrontend/pgm2/fs20.gplot index f61fb723d..05db463a4 100644 --- a/fhem/webfrontend/pgm2/fs20.gplot +++ b/fhem/webfrontend/pgm2/fs20.gplot @@ -3,7 +3,7 @@ # FileLog definition: # define FileLog fs20log fs20dev /var/log/fs20dev-%Y-%U.log # -set terminal png transparent size 800,200 crop +set terminal png transparent size crop set output '.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" @@ -17,7 +17,7 @@ set y2range [-0.1:1.1] set ylabel "Pumpe" set y2label "Pumpe" -#FileLog 3::$fld[2]eq"on"?1:0 +#FileLog 3::0:$fld[2]eq"on"?1:0 plot "< awk '{print $1, $3==\"on\"? 1 : 0; }' "\ using 1:2 notitle with steps diff --git a/fhem/webfrontend/pgm2/ks300_1.gplot b/fhem/webfrontend/pgm2/ks300_1.gplot index 6f13092d6..c12570937 100644 --- a/fhem/webfrontend/pgm2/ks300_1.gplot +++ b/fhem/webfrontend/pgm2/ks300_1.gplot @@ -3,7 +3,7 @@ # FileLog definition: # define FileLog ks300log ks300:.*H:.* /var/log/ks300-%Y-%U.log # -set terminal png transparent size 800,200 crop +set terminal png transparent size crop set output '.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" @@ -13,16 +13,16 @@ set y2tics set title '' set grid -set y2label "Temperature (Celsius)" +set y2label "Temperature in C°" set format y "%0.1f" set ylabel "Rain (l/m2)" set yrange [0:] # Computing Rain/h and Rain/d values by accumulating the changes. -#FileLog 4:IR: -#FileLog 10:IR:delta-h -#FileLog 10:IR:delta-d +#FileLog 4:IR:0: +#FileLog 10:IR:0:delta-h +#FileLog 10:IR:0:delta-d plot "" using 1:4 axes x1y2 title 'Temperature' with lines lw 2,\ " | perl -ane '\ diff --git a/fhem/webfrontend/pgm2/ks300_2.gplot b/fhem/webfrontend/pgm2/ks300_2.gplot index a71b1c4de..a3533e03b 100644 --- a/fhem/webfrontend/pgm2/ks300_2.gplot +++ b/fhem/webfrontend/pgm2/ks300_2.gplot @@ -3,7 +3,7 @@ # FileLog definition: # define FileLog ks300log ks300:.*H:.* /var/log/ks300-%Y-%U.log # -set terminal png transparent size 800,200 crop +set terminal png transparent size crop set output '.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" @@ -16,8 +16,8 @@ set grid set ylabel "Wind (Km/h)" set y2label "Humidity (%)" -#FileLog 8:IR: -#FileLog 6:IR: +#FileLog 8:IR:0: +#FileLog 6:IR:0: plot "" using 1:8 axes x1y1 title 'Wind' with lines,\ "" using 1:6 axes x1y2 title 'Rel. Humidity (%)' with lines diff --git a/fhem/webfrontend/pgm2/ks300_3.gplot b/fhem/webfrontend/pgm2/ks300_3.gplot index 43b5f55f2..4f1e6c7ca 100644 --- a/fhem/webfrontend/pgm2/ks300_3.gplot +++ b/fhem/webfrontend/pgm2/ks300_3.gplot @@ -3,7 +3,7 @@ # FileLog definition: # define FileLog ks300log ks300:.*H:.* /var/log/ks300-%Y-%U.log # -set terminal png transparent size 800,200 crop +set terminal png transparent size crop set output '.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" @@ -13,11 +13,11 @@ set y2tics set title '' set grid -set ylabel "Temperature (Celsius)" +set ylabel "Temperature in C°" set y2label "Rain (l/m2)" -#FileLog 5:avg_day: -#FileLog 11:avg_day: +#FileLog 5:avg_day:0: +#FileLog 11:avg_day:0: plot "" using 1:5 axes x1y1 title 'Temperature' with lines,\ "" using 1:11 axes x1y2 title 'Rain' with histeps diff --git a/fhem/webfrontend/pgm2/mpiri.gplot b/fhem/webfrontend/pgm2/mpiri.gplot index 9acd56cca..51c26e4e9 100644 --- a/fhem/webfrontend/pgm2/mpiri.gplot +++ b/fhem/webfrontend/pgm2/mpiri.gplot @@ -3,7 +3,7 @@ # define pirilog FileLog /var/log/piri-%Y-%m-%d.log piri.* # The devices are called piri.sz, piri.flo, piri.flu, prir.wz1 and piri.wz2 # -set terminal png transparent size 800,200 crop +set terminal png transparent size crop set output '.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" @@ -14,12 +14,13 @@ set title '' set ytics ("Sz" 0.8, "FlO" 0.6, "FlU" 0.4, "Wz1" 0.2, "Wz2" 0.0) set y2tics ("Sz" 0.8, "FlO" 0.6, "FlU" 0.4, "Wz1" 0.2, "Wz2" 0.0) set yrange [-0.1:0.9] +set y2range [-0.1:0.9] -#FileLog "0.8":sz: -#FileLog "0.6":flo: -#FileLog "0.4":flu: -#FileLog "0.2":wz1: -#FileLog "0.0":wz2: +#FileLog "0.8":sz:0.8: +#FileLog "0.6":flo:0.6: +#FileLog "0.4":flu:0.4: +#FileLog "0.2":wz1:0.2: +#FileLog "0.0":wz2:0.0: plot\ "< awk '/sz/ {print $1, 0.8; }' " using 1:2 notitle with points,\ diff --git a/fhem/webfrontend/pgm2/piri.gplot b/fhem/webfrontend/pgm2/piri.gplot index 5cf9d0347..0530504d8 100644 --- a/fhem/webfrontend/pgm2/piri.gplot +++ b/fhem/webfrontend/pgm2/piri.gplot @@ -3,7 +3,7 @@ # FileLog definition: # define FileLog fs20log fs20dev /var/log/fs20dev-%Y-%U.log # -set terminal png transparent size 800,200 crop +set terminal png transparent size crop set output '.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" @@ -13,7 +13,7 @@ set title '' set grid set yrange [-0.2:1.2] -#FileLog "1"::: +#FileLog "1"::0: plot "< awk '{print $1, $3==\"on\"? 1 : 0; }' "\ using 1:2 title 'On/Off' with impulses diff --git a/fhem/webfrontend/pgm2/style.css b/fhem/webfrontend/pgm2/style.css index a3abfaa33..05a9526df 100644 --- a/fhem/webfrontend/pgm2/style.css +++ b/fhem/webfrontend/pgm2/style.css @@ -1,145 +1,146 @@ -body { - color: black; - background: #FFFFD7; -} - -table.room { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #D7FFFF; -} - -table.room tr.sel { - background: #A0FFFF; -} - -table.FS20 { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #C0FFFF; -} - -table.FS20 tr.odd { - background: #D7FFFF; -} - -table.FHT { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #FFC0C0; -} - -table.FHT tr.odd { - background: #FFD7D7; -} - -table.KS300 { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #C0FFC0; -} - -table.KS300 tr.odd { - background: #A7FFA7; -} - -table.FileLog { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #FFC0C0; -} - -table.FileLog tr.odd { - background: #FFD7D7; -} - -table.at { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #FFFFC0; -} - -table.at tr.odd { - background: #FFFFD7; -} - -table.notify { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #D7D7A0; -} - -table.notify tr.odd { - background: #FFFFC0; -} - -table.FHZ { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #C0C0C0; -} - -table.FHZ tr.odd { - background: #D7D7D7; -} - -table.EM { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #E0E0E0; -} - -table.EM tr.odd { - background: #F0F0F0; -} - -table._internal_ { - border: solid; - border-width: thin; - width: 100%; - -moz-border-radius:8px; - background: #C0C0C0; -} - -table._internal_ tr.odd { - background: #D7D7D7; -} - -#hdr { - position:absolute; - top:10px; - left:10px; -} - -#left { - position:absolute; - top:50px; - left:10px; - width:130px; -} - -#right { - position:absolute; - top:50px; - left:160px; - bottom:10px; - overflow:auto; -} +body { + color: black; + background: #FFFFD7; +} + +table.room { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #D7FFFF; +} + +table.room tr.sel { + background: #A0FFFF; +} + +table.FS20 { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #C0FFFF; +} + +table.FS20 tr.odd { + background: #D7FFFF; +} + +table.FHT { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #FFC0C0; +} + +table.FHT tr.odd { + background: #FFD7D7; +} + +table.KS300 { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #C0FFC0; +} + +table.KS300 tr.odd { + background: #A7FFA7; +} + +table.FileLog { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #FFC0C0; +} + +table.FileLog tr.odd { + background: #FFD7D7; +} + +table.at { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #FFFFC0; +} + +table.at tr.odd { + background: #FFFFD7; +} + +table.notify { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #D7D7A0; +} + +table.notify tr.odd { + background: #FFFFC0; +} + +table.FHZ { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #C0C0C0; +} + +table.FHZ tr.odd { + background: #D7D7D7; +} + +table.EM { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #E0E0E0; +} + +table.EM tr.odd { + background: #F0F0F0; +} + +table._internal_ { + border: solid; + border-width: thin; + width: 100%; + -moz-border-radius:8px; + background: #C0C0C0; +} + +table._internal_ tr.odd { + background: #D7D7D7; +} + +#hdr { + position:absolute; + top:10px; + left:10px; +} + +#left { + position:absolute; + top:50px; + left:10px; + width:130px; +} + +#right { + position:absolute; + top:50px; + left:160px; + right:10px; + bottom:10px; + overflow:auto; +} diff --git a/fhem/webfrontend/pgm2/svg_style.css b/fhem/webfrontend/pgm2/svg_style.css new file mode 100644 index 000000000..5a7c7f659 --- /dev/null +++ b/fhem/webfrontend/pgm2/svg_style.css @@ -0,0 +1,15 @@ +text { font-family:Times; font-size:12px; } +text.title { font-size:16px; } + +rect.border { stroke:black; stroke-width:1px; fill:none; } + +polyline { stroke:black; stroke-width:1px; fill:none; } + +.vgrid { stroke-dasharray:2,6; stroke:gray; } +.hgrid { stroke-dasharray:2,6; stroke:gray; } + +.l0 { stroke:red; } text.l0 { stroke:none; fill:red; } +.l1 { stroke:green; } text.l1 { stroke:none; fill:green; } +.l2 { stroke:blue; } text.l2 { stroke:none; fill:blue; } +.l3 { stroke:magenta; } text.l3 { stroke:none; fill:magenta; } +.l4 { stroke:cyan; } text.l4 { stroke:none; fill:cyan; }