diff --git a/fhem/CHANGED b/fhem/CHANGED index a8e9ebc70..d079ecc2d 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -404,4 +404,6 @@ - feature: fhem.pl check modules for compiletime errors and do not initialize them - feature: M232 add windows support (thomas 12.05.08) - - feature: add simple ELV IPWE1 support (thomas 12.05.08) \ No newline at end of file + - feature: add simple ELV IPWE1 support (thomas 12.05.08) + - feature: FileLog get to read logfiles. Used heavily by webpgm2 + - feature: webpgm2: gnuplot-scroll mode to navigate/zoom in logfiles diff --git a/fhem/FHEM/92_FileLog.pm b/fhem/FHEM/92_FileLog.pm index ac05b2945..b83719adb 100755 --- a/fhem/FHEM/92_FileLog.pm +++ b/fhem/FHEM/92_FileLog.pm @@ -5,6 +5,8 @@ use strict; use warnings; use IO::File; +sub seekTo($$$$); + ##################################### sub FileLog_Initialize($) @@ -141,35 +143,167 @@ FileLog_Set($@) } ################################### +# We use this function to be able to scroll/zoom in the plots created from the +# logfile. When outfile is specified, it is used with gnuplot post-processing, +# when outfile is "-" it is used to create SVG graphics +# +# Up till now following functions are impemented: +# - int (to cut off % from a number, as for the actuator) +# - delta-h / delta-d to get rain/h and rain/d values from continuous data. + sub FileLog_Get($@) { my ($hash, @a) = @_; - return "Usage: get $a[0] " if(int(@a) != 4); - my $fh = new IO::File $hash->{currentlogfile}; - seekTo($fh, $hash, $a[1]); -# my @arr = - my $data=''; - while(my $l = <$fh>) { - last if($l gt $a[2]); - $data.=$l; - } - close($fh); - return "EOF" if(!defined($data)); + return "Usage: get $a[0] ...\n" . + " where column_spec is ::\n" . + " see the FileLogGrep entries in he .gplot files\n" . + " is without direcory, - means the current file\n" . + " is a prefix, - means stdout\n" + if(int(@a) < 5); - return $data; + shift @a; + my $inf = shift @a; + my $outf = shift @a; + my $from = shift @a; + my $to = shift @a; + + if($inf eq "-") { + $inf = $hash->{currentlogfile}; + } else { + my $linf = "$1/$inf" if($hash->{currentlogfile} =~ m,^(.*)/[^/]*$,); + if(!-f $linf) { + $linf = $attr{$hash->{NAME}}{archivedir} . "/" . $inf; + return "Error: File-not-found" if(!-f $linf); + } + $inf = $linf; + } + my $ifh = new IO::File $inf; + seekTo($inf, $ifh, $hash, $from); + + ############# + # Digest the input. + # last1: first delta value after d/h change + # last2: last delta value recorded (for the very last entry) + # last3: last delta timestamp (d or h) + my (@d, @fname); + for(my $i = 0; $i < int(@a); $i++) { + my @fld = split(":", $a[$i], 3); + + my %h; + if($outf ne "-") { + $fname[$i] = "$outf.$i"; + $h{fh} = new IO::File "> $fname[$i]"; + } + $h{re} = $fld[1]; + $h{fn} = $fld[2]; + $h{didx} = 2 if($fld[2] && $fld[2] eq "delta-d"); + $h{didx} = 3 if($fld[2] && $fld[2] eq "delta-h"); + + if($fld[0] =~ m/"(.*)"/) { + $h{col} = $1; + $h{isfix} = 1; + } else { + $h{col} = $fld[0]-1; + } + $h{ret} = []; + $d[$i] = \%h; + } + + my %lastdate; + while(my $l = <$ifh>) { + last if($l gt $to); + my @fld = split("[ \r\n]+", $l); + for(my $i = 0; $i < int(@a); $i++) { # Process each req. field + my $h = $d[$i]; + my $re = $h->{re}; + next if($re && $l !~ m/$re/); + + my $col = $h->{col}; + my $line = ""; + + if($h->{isfix}) { # Fixed text + $line = "$fld[0] $col"; + + } elsif(!$h->{fn}) { # The column + $line = "$fld[0] $fld[$col]"; + + } elsif($h->{fn} eq "int") { # int function + my $val = $fld[$col]; + $val =~ s/[^\d.]//; + $line = "$fld[0] $val"; + + } elsif($h->{didx}) { # delta-h or delta-d + + my $hd = $h->{didx}; + my @ld = split("[-_:]", $fld[0]); + if(!defined($h->{last1}) || $h->{last3} ne $ld[$hd]) { + if(defined($h->{last1})) { + my @lda = split("[_:]", $lastdate{$hd}); + my $ts = "12:00:00"; # middle timestamp + $ts = "$lda[1]:30:00" if($hd == 3); + $line = sprintf("%s_%s %0.1f", $lda[0],$ts, $fld[$col]-$h->{last1}); + } + $h->{last1} = $fld[$col]; + $h->{last3} = $ld[$hd]; + } + $h->{last2} = $fld[$col]; + $lastdate{$hd} = $fld[0]; + } else { + $line = "$fld[0] " . eval($h->{fn}); + } + + next if(!$line); + + if($outf eq "-") { + push @{$h->{ret}}, $line; + } else { + my $fh = $h->{fh}; + print $fh $line,"\n"; + } + } + } + $ifh->close(); + + my $ret = ""; + for(my $i = 0; $i < int(@a); $i++) { + my $h = $d[$i]; + my $hd = $h->{didx}; + if($hd && $lastdate{$hd}) { + my $val = defined($h->{last1}) ? $h->{last2}-$h->{last1} : 0; + + my @lda = split("[_:]", $lastdate{$hd}); + my $ts = "12:00:00"; # middle timestamp + $ts = "$lda[1]:30:00" if($hd == 3); + my $line = sprintf("%s_%s %0.1f", $lda[0],$ts, $h->{last2}-$h->{last1}); + + if($outf eq "-") { + push @{$h->{ret}}, $line; + } else { + my $fh = $h->{fh}; + print $fh $line,"\n"; + } + } + if($outf eq "-") { + $ret .= join("\n", @{$h->{ret}}) if($h->{ret}); + } else { + $h->{fh}->close(); + } + } + + return ($outf eq "-") ? $ret : join(" ", @fname); } ################################### sub -seekTo($$$) +seekTo($$$$) { - my ($fh, $hash, $ts) = @_; + my ($fname, $fh, $hash, $ts) = @_; # If its cached - if($hash->{pos} && $hash->{pos}{$ts}) { - $fh->seek($hash->{pos}{$ts}, 0); + if($hash->{pos} && $hash->{pos}{"$fname:$ts"}) { + $fh->seek($hash->{pos}{"$fname:$ts"}, 0); return; } @@ -183,17 +317,21 @@ seekTo($$$) if($data !~ m/^20\d\d-\d\d-\d\d_\d\d:\d\d:\d\d /) { $next = $fh->tell; $data = <$fh>; + $next = $last if(!$data); + } + if($next eq $last) { + $fh->seek($next, 0); + last; } - last if($next eq $last); $last = $next; - if($data lt $ts) { + if(!$data || $data lt $ts) { ($lower, $next) = ($next, ($next+$upper)/2); } else { ($upper, $next) = ($next, ($lower+$next)/2); } } - $hash->{pos}{$ts} = $last; + $hash->{pos}{"$fname:$ts"} = $last; } diff --git a/fhem/HISTORY b/fhem/HISTORY index d94f120c1..850b2e975 100644 --- a/fhem/HISTORY +++ b/fhem/HISTORY @@ -284,3 +284,13 @@ - Peter S. Mon Jun 02 00:39 MET 2008 - linux.html: openSUSE 11 contains our changes. + +- Thu Jun 12 07:15:03 MEST 2008 + - feature: FileLog get to read logfiles / webpgm2: gnuplot-scroll mode to + navigate/zoom in logfiles + webpgm2 uses the FileLog get to grep data for a given data range from a + logfile. Using this grep scrolling to a different date range / zooming + to another resolution (day/week/month/year) can be implemented. + The logfiles should be large, as scrolling across logfiles is not + implemented. To speed up the grep, a binary search with seek is used, and + seek positions are cached. diff --git a/fhem/webfrontend/pgm2/01_FHEMWEB.pm b/fhem/webfrontend/pgm2/01_FHEMWEB.pm index e7066effb..c1e180a7e 100755 --- a/fhem/webfrontend/pgm2/01_FHEMWEB.pm +++ b/fhem/webfrontend/pgm2/01_FHEMWEB.pm @@ -35,11 +35,13 @@ sub FHEMWEB_showLogWrapper($); sub FHEMWEB_popup($$$); sub FHEMWEB_textfield($$); sub FHEMWEB_submit($$); -sub __roomOverview(); +sub FHEMWEB_roomOverview(); sub FHEMWEB_fatal($); sub pF($@); sub pO(@); sub FHEMWEB_AnswerCall($); +sub FHEMWEB_zoomLink($$$$); +sub FHEMWEB_calcWeblink($$); ######################### # As we are _not_ multithreaded, it is safe to use global variables. @@ -52,10 +54,15 @@ 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; ##################################### @@ -68,7 +75,7 @@ FHEMWEB_Initialize($) $hash->{DefFn} = "FHEMWEB_Define"; $hash->{UndefFn} = "FHEMWEB_Undef"; - $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 fhemwebdir fhemwebname"; + $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 webdir webname plotmode:gnuplot,gnuplot-scroll,SVG"; } ##################################### @@ -95,6 +102,12 @@ FHEMWEB_Define($$) $hash->{SERVERSOCKET} = "True"; Log(2, "FHEMWEB port $port opened"); + ############### + # Initialize internal structures + my $n = 0; + @__zoom = ("day","week","month","year"); + %__zoom = map { $_, $n++ } @__zoom; + return undef; } @@ -145,10 +158,10 @@ FHEMWEB_Read($) my $name = $hash->{SNAME}; my $ll = GetLogLevel($name,4); - $FHEMWEBdir = ($attr{$name} && $attr{$name}{fhemwebdir}) ? - $attr{$name}{fhemwebdir} : "$attr{global}{modpath}/FHEM"; - $__ME = "/" . (($attr{$name} && $attr{$name}{fhemwebname}) ? - $attr{$name}{fhemwebname} : "fhem"); + $FHEMWEBdir = ($attr{$name} && $attr{$name}{webdir}) ? + $attr{$name}{webdir} : "$attr{global}{modpath}/FHEM"; + $__ME = "/" . (($attr{$name} && $attr{$name}{webname}) ? + $attr{$name}{webname} : "fhem"); $FHEMWEB_reldoc = "$__ME/commandref.html"; $__SF = "
"; @@ -173,16 +186,16 @@ FHEMWEB_Read($) $hash->{BUF} = ""; Log($ll, "HTTP $hash->{NAME} GET $arg"); + $__plotmode = $attr{$name}{plotmode} ? $attr{$name}{plotmode} : "gnuplot"; FHEMWEB_AnswerCall($arg); my $c = $hash->{CD}; my $l = length($__RET); - my $exp = localtime(time()+300) . " GMT"; - +# my $exp = localtime(time()+300) . " GMT"; +# "Expires: $exp\r\n", print $c "HTTP/1.1 200 OK\r\n", "Content-Length: $l\r\n", - "Expires: $exp\r\n", "Content-Type: $__RETTYPE\r\n\r\n", $__RET; } @@ -195,6 +208,7 @@ FHEMWEB_AnswerCall($) %__rooms = (); %__devs = (); + %__wlpos = (); %__types = (); $__room = ""; $__detail = ""; @@ -266,8 +280,8 @@ FHEMWEB_AnswerCall($) pO "\n"; } - __roomOverview(); - FHEMWEB_doDetail($__detail) if($__detail); + FHEMWEB_roomOverview(); + FHEMWEB_doDetail($__detail) if($__detail); FHEMWEB_showRoom() if($__room && !$__detail); FHEMWEB_showLogWrapper($cmd) if($cmd =~ /^showlogwrapper/); FHEMWEB_showArchive($cmd) if($cmd =~ m/^showarchive/); @@ -289,7 +303,7 @@ FHEMWEB_digestCgi($) $pv =~ s/\+/ /g; $pv =~ s/%(..)/chr(hex($1))/ge; my ($p,$v) = split("=",$pv, 2); - $v =~ s/[\r]\n/\\\n/g; + $v =~ s/[\r]\n/\\\n/g; # Multiline: escape the NL for fhem #Log(0, "P: $p, V: $v"); if($p eq "detail") { $__detail = $v; } @@ -299,6 +313,9 @@ FHEMWEB_digestCgi($) if($p =~ m/^val\.(.*)$/) { $val{$1} = $v; } if($p =~ m/^dev\.(.*)$/) { $dev{$1} = $v; } if($p =~ m/^cmd\.(.*)$/) { $cmd = $v; $c= $1; } + if($p eq "wlpos") { %__wlpos = split(/[=;]/, $v); } + + } $cmd.=" $dev{$c}" if($dev{$c}); $cmd.=" $arg{$c}" if($arg{$c}); @@ -514,14 +531,30 @@ FHEMWEB_doDetail($) ############## # Room overview sub -__roomOverview() +FHEMWEB_roomOverview() { pO $__SF; pO "
\n"; + pO "
"; pO "Cmd: "; pO FHEMWEB_textfield("cmd", 30); - pO FHEMWEB_hidden("room", "$__room") if($__room); + $__scrolledweblinkcount = 0; + if($__room) { + pO FHEMWEB_hidden("room", "$__room"); + if(!$__detail) { # Global navigation buttons for weblink >= 2 + FHEMWEB_calcWeblink(undef,undef); + if($__scrolledweblinkcount) { + pO ""; + pO "  "; + FHEMWEB_zoomLink("zoom=-1", "Zoom-in.png", "zoom in", 0); + FHEMWEB_zoomLink("zoom=1", "Zoom-out.png","zoom out", 0); + FHEMWEB_zoomLink("all=-1", "Prev.png", "prev", 0); + FHEMWEB_zoomLink("all=1", "Next.png", "next", 0); + } + } + } + pO "
"; pO "
\n"; pO "
\n"; @@ -717,8 +750,20 @@ FHEMWEB_showRoom() $__devs{$va[0]}{INT}{currentlogfile}{VAL} =~ m,([^/]*)$,; $va[2] = $1; } - pO ""; + pO ""; + pO "
"; + + my $wl = ""; + $__wlpos{$va[0]} = $__wlpos{$d} if($__wlpos{$d}); + $wl = "&wlpos=" . join(";", map { "$_=$__wlpos{$_}" } + grep { /(zoom|all|$va[0])/ } keys %__wlpos); + + pO ""; + pO ""; + + FHEMWEB_zoomLink("$d=-1", "Prev.png", "prev", 1); + FHEMWEB_zoomLink("$d=1", "Next.png", "next", 1); pO "$d
"; } } @@ -756,6 +801,8 @@ FHEMWEB_fileList($) } ###################### +# Show the content of the log (plain text), or an image and offer a link +# to convert it to a weblink sub FHEMWEB_showLogWrapper($) { @@ -782,7 +829,7 @@ FHEMWEB_showLogWrapper($) pO "
\n"; pO "\n"; pO "
\n"; - pO ""; pO "
"; + pO ""; pO "
Convert to weblink
\n"; pO "\n"; @@ -795,28 +842,83 @@ sub FHEMWEB_showLog($) { my ($cmd) = @_; - my (undef, $d, $type, $file) = split(" ", $cmd, 4); - - $__devs{$d}{INT}{logfile}{VAL} =~ m,^(.*)/([^/]*)$,; # Dir and File - my $path = "$1/$file"; - $path = $__devs{$d}{ATTR}{archivedir}{VAL} . "/$file" if(!-f $path); + my (undef, $wl, $d, $type, $file) = split(" ", $cmd, 5); my $gplot_pgm = "$FHEMWEBdir/$type.gplot"; - return FHEMWEB_fatal("Cannot read $gplot_pgm") if(!-r $gplot_pgm); - return FHEMWEB_fatal("Cannot read $path") if(!-r $path); - # Read in the template gnuplot file - 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; + FHEMWEB_calcWeblink($d,$wl); + if($__plotmode eq "gnuplot" || !$__devs{$d}{from}) { + + # Looking for the logfile.... + + $__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); + + 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; + + 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); + + } else { # 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) || 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//$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) { + 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; - close(FH); $__RETTYPE = "image/png"; open(FH, "$FHEMWEB_tmpfile.png"); # read in the result and send it @@ -904,6 +1006,131 @@ FHEMWEB_submit($$) return $s; } +################## +sub +FHEMWEB_zoomLink($$$$) +{ + my ($cmd, $img, $alt, $br) = @_; + + my ($d,$off) = split("=", $cmd, 2); + + return if($__plotmode eq "gnuplot"); + return if($__devs{$d} && $__devs{$d}{ATTR}{fixedrange}); + return if($__devs{$d} && $__devs{$d}{ATTR}{noscroll}); + + my $val = $__wlpos{$d}; + + $cmd = "room=$__room&wlpos="; + if($d eq "zoom") { + + $val = "day" if(!$val); + $val = $__zoom{$val}; + return if(!defined($val) || $val+$off < 0 || $val+$off >= int(@__zoom) ); + $val = $__zoom[$val+$off]; + return if(!$val); + $cmd .= "zoom=$val"; + + } else { + + return if((!$val && $off > 0) || ($val && $val+$off > 0)); # no future + $__wlpos{$d}=($val ? $val+$off : $off); + $cmd .= join(";", map { "$_=$__wlpos{$_}" } sort keys %__wlpos); + + if(!defined($val)) { + delete $__wlpos{$d}; + } else { + $__wlpos{$d} = $val; + } + } + + pO ""; + pO "\"$alt\""; + pO "
" if($br); +} + +################## +# Calculate either the number of scrollable weblinks (for $d = undef) or +# for the device the valid from and to dates for the given zoom and offset +sub +FHEMWEB_calcWeblink($$) +{ + my ($d,$wl) = @_; + + return if($__plotmode eq "gnuplot"); + my $now = time(); + + my $zoom = $__wlpos{zoom}; + $zoom = "day" if(!$zoom); + + if(!$d) { + foreach my $d (sort keys %__devs ) { + next if($__devs{$d}{type} ne "weblink"); + next if(!$__room || ($__room ne "all" && !$__rooms{$__room}{$d})); + next if($__devs{$d}{ATTR} && $__devs{$d}{ATTR}{noscroll}); + next if($__devs{$d}{ATTR} && $__devs{$d}{ATTR}{fixedrange}); + $__scrolledweblinkcount++; + } + return; + } + + return if(!$__devs{$wl}); + return if($__devs{$wl} && $__devs{$wl}{ATTR}{noscroll}); + + if($__devs{$wl} && $__devs{$wl}{ATTR}{fixedrange}) { + my @range = split(" ", $__devs{$wl}{ATTR}{fixedrange}{VAL}); + $__devs{$d}{from} = $range[0]; + $__devs{$d}{to} = $range[1]; + return; + } + + my $off = $__wlpos{$d}; + $off = 0 if(!$off); + $off += $__wlpos{all} if($__wlpos{all}); + + if($zoom eq "day") { + + my $t = $now + $off*86400; + my @l = localtime($t); + $__devs{$d}{from} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]); + $__devs{$d}{to} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]+1); + + } elsif($zoom eq "week") { + + my @l = localtime($now); + my $t = $now - ($l[6]*86400) + ($off*86400)*7; + @l = localtime($t); + $__devs{$d}{from} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]); + + @l = localtime($t+7*86400); + $__devs{$d}{to} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]); + + + } elsif($zoom eq "month") { + + my @l = localtime($now); + while($off < -12) { + $off += 12; $l[5]--; + } + $l[4] += $off; + $l[4] += 12, $l[5]-- if($l[4] < 0); + $__devs{$d}{from} = sprintf("%04d-%02d", $l[5]+1900, $l[4]+1); + + $l[4]++; + $l[4] = 0, $l[5]++ if($l[4] == 12); + $__devs{$d}{to} = sprintf("%04d-%02d", $l[5]+1900, $l[4]+1); + + } elsif($zoom eq "year") { + + my @l = localtime($now); + $l[5] += $off; + $__devs{$d}{from} = sprintf("%04d", $l[5]+1900); + $__devs{$d}{to} = sprintf("%04d", $l[5]+1901); + + } +} + +################## sub pF($@) { @@ -911,12 +1138,14 @@ pF($@) $__RET .= sprintf $fmt, @_; } +################## sub pO(@) { $__RET .= shift; } +################## sub fC($) { diff --git a/fhem/webfrontend/pgm2/98_weblink.pm b/fhem/webfrontend/pgm2/98_weblink.pm index 99c7fe1e9..b459fb73c 100755 --- a/fhem/webfrontend/pgm2/98_weblink.pm +++ b/fhem/webfrontend/pgm2/98_weblink.pm @@ -11,6 +11,7 @@ weblink_Initialize($) my ($hash) = @_; $hash->{DefFn} = "weblink_Define"; + $hash->{AttrList}= "fixedrange noscroll"; } diff --git a/fhem/webfrontend/pgm2/Next.png b/fhem/webfrontend/pgm2/Next.png new file mode 100644 index 000000000..0296c018d Binary files /dev/null and b/fhem/webfrontend/pgm2/Next.png differ diff --git a/fhem/webfrontend/pgm2/Prev.png b/fhem/webfrontend/pgm2/Prev.png new file mode 100644 index 000000000..5b69ba629 Binary files /dev/null and b/fhem/webfrontend/pgm2/Prev.png differ diff --git a/fhem/webfrontend/pgm2/Zoom-in.png b/fhem/webfrontend/pgm2/Zoom-in.png new file mode 100644 index 000000000..0afaaf175 Binary files /dev/null and b/fhem/webfrontend/pgm2/Zoom-in.png differ diff --git a/fhem/webfrontend/pgm2/Zoom-out.png b/fhem/webfrontend/pgm2/Zoom-out.png new file mode 100644 index 000000000..a1395418c Binary files /dev/null and b/fhem/webfrontend/pgm2/Zoom-out.png differ diff --git a/fhem/webfrontend/pgm2/em.gplot b/fhem/webfrontend/pgm2/em.gplot index d3570344d..97bdb1102 100644 --- a/fhem/webfrontend/pgm2/em.gplot +++ b/fhem/webfrontend/pgm2/em.gplot @@ -19,4 +19,6 @@ set y2tics set format y "%.1f" set format y2 "%.1f" +#FileLog 0 4:: + plot "" using 1:4 notitle with lines diff --git a/fhem/webfrontend/pgm2/fht.gplot b/fhem/webfrontend/pgm2/fht.gplot index e7de9cb0a..d3d8d6c69 100644 --- a/fhem/webfrontend/pgm2/fht.gplot +++ b/fhem/webfrontend/pgm2/fht.gplot @@ -17,10 +17,15 @@ set grid xtics y2tics set y2label "temperature (Celsius)" set ylabel "Actuator (%)" +#FileLog 4:measured: +##FileLog 4:desired: +#FileLog 4:actuator.*%:int + +# "< awk '/desired/ {print $1, $4+0}' "\ +# using 1:2 axes x1y2 title 'Desired temperature' with steps,\ + plot \ "< awk '/measured/{print $1, $4}' "\ using 1:2 axes x1y2 title 'Measured temperature' with lines lw 2,\ - "< awk '/desired/ {print $1, $4+0}' "\ - using 1:2 axes x1y2 title 'Desired temperature' with steps,\ "< awk '/actuator/ {print $1, $4+0}' "\ using 1:2 axes x1y1 title 'Actuator (%)' with lines\ diff --git a/fhem/webfrontend/pgm2/fs20.gplot b/fhem/webfrontend/pgm2/fs20.gplot index 2b2da76d2..f61fb723d 100644 --- a/fhem/webfrontend/pgm2/fs20.gplot +++ b/fhem/webfrontend/pgm2/fs20.gplot @@ -17,5 +17,7 @@ set y2range [-0.1:1.1] set ylabel "Pumpe" set y2label "Pumpe" +#FileLog 3::$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 888fbe6b2..6f13092d6 100644 --- a/fhem/webfrontend/pgm2/ks300_1.gplot +++ b/fhem/webfrontend/pgm2/ks300_1.gplot @@ -20,6 +20,10 @@ 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 + plot "" using 1:4 axes x1y2 title 'Temperature' with lines lw 2,\ " | perl -ane '\ @a = split(\"[_:]\", $F[0]);\ diff --git a/fhem/webfrontend/pgm2/ks300_2.gplot b/fhem/webfrontend/pgm2/ks300_2.gplot index c8fff205c..a71b1c4de 100644 --- a/fhem/webfrontend/pgm2/ks300_2.gplot +++ b/fhem/webfrontend/pgm2/ks300_2.gplot @@ -15,5 +15,9 @@ set grid set ylabel "Wind (Km/h)" set y2label "Humidity (%)" + +#FileLog 8:IR: +#FileLog 6:IR: + 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 a2ce53716..43b5f55f2 100644 --- a/fhem/webfrontend/pgm2/ks300_3.gplot +++ b/fhem/webfrontend/pgm2/ks300_3.gplot @@ -16,5 +16,8 @@ set grid set ylabel "Temperature (Celsius)" set y2label "Rain (l/m2)" +#FileLog 5:avg_day: +#FileLog 11:avg_day: + 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 4021c4eb6..9acd56cca 100644 --- a/fhem/webfrontend/pgm2/mpiri.gplot +++ b/fhem/webfrontend/pgm2/mpiri.gplot @@ -15,6 +15,12 @@ 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] +#FileLog "0.8":sz: +#FileLog "0.6":flo: +#FileLog "0.4":flu: +#FileLog "0.2":wz1: +#FileLog "0.0":wz2: + plot\ "< awk '/sz/ {print $1, 0.8; }' " using 1:2 notitle with points,\ "< awk '/flo/{print $1, 0.6; }' " using 1:2 notitle with points,\ diff --git a/fhem/webfrontend/pgm2/piri.gplot b/fhem/webfrontend/pgm2/piri.gplot index f9112f477..5cf9d0347 100644 --- a/fhem/webfrontend/pgm2/piri.gplot +++ b/fhem/webfrontend/pgm2/piri.gplot @@ -13,5 +13,7 @@ set title '' set grid set yrange [-0.2:1.2] +#FileLog "1"::: + 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 new file mode 100644 index 000000000..a3abfaa33 --- /dev/null +++ b/fhem/webfrontend/pgm2/style.css @@ -0,0 +1,145 @@ +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; +}