mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
.gplot editor added to the weblink details screen
git-svn-id: https://svn.fhem.de/fhem/trunk@3130 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
7f9034f883
commit
8425d41508
@ -1,5 +1,6 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII
|
||||
- SVN
|
||||
- feature: weblink details screen can be used to edit .gplot files
|
||||
- feature: eventTypes module added, to help with FileLog details screen
|
||||
- feature: FB_CALLMONITOR: new reverse search provider dasschnelle.at for
|
||||
reverse search of austrian telephone numbers
|
||||
|
@ -72,6 +72,7 @@ use vars qw($FW_cname); # Current connection name
|
||||
use vars qw(%FW_hiddenroom); # hash of hidden rooms, used by weblink
|
||||
use vars qw($FW_plotmode);# Global plot mode (WEB attribute), used by weblink
|
||||
use vars qw($FW_plotsize);# Global plot size (WEB attribute), used by weblink
|
||||
use vars qw(%FW_webArgs); # all arguments specified in the GET
|
||||
|
||||
my $FW_zlib_checked;
|
||||
my $FW_use_zlib = 1;
|
||||
@ -81,7 +82,6 @@ my $FW_use_zlib = 1;
|
||||
# Note: for delivering SVG plots we fork
|
||||
my @FW_httpheader; # HTTP header, line by line
|
||||
my @FW_enc; # Accepted encodings (browser header)
|
||||
my %FW_webArgs; # all arguments specified in the GET
|
||||
my $FW_cmdret; # Returned data by the fhem call
|
||||
my $FW_data; # Filecontent from browser when editing a file
|
||||
my $FW_detail; # currently selected device for detail view
|
||||
@ -454,6 +454,7 @@ FW_answerCall($)
|
||||
#Returns undef if it already sent a HTTP header
|
||||
($FW_RETTYPE, $FW_RET) = &{$h->{FUNC}}($arg);
|
||||
use strict "refs";
|
||||
last if(!$FW_RET);
|
||||
return defined($FW_RETTYPE) ? 0 : -1;
|
||||
}
|
||||
}
|
||||
@ -623,6 +624,7 @@ FW_digestCgi($)
|
||||
$cmd.=" $arg{$c}" if(defined($arg{$c}) &&
|
||||
($arg{$c} ne "state" || $cmd !~ m/^set/));
|
||||
$cmd.=" $val{$c}" if(defined($val{$c}));
|
||||
#Log 1, "GOT:$arg -> CMD:$cmd";
|
||||
return ($cmd, $c);
|
||||
}
|
||||
|
||||
@ -751,8 +753,6 @@ FW_doDetail($)
|
||||
{
|
||||
my ($d) = @_;
|
||||
|
||||
FW_pO "<form method=\"get\" action=\"$FW_ME\">";
|
||||
FW_pO FW_hidden("detail", $d);
|
||||
|
||||
my $h = $defs{$d};
|
||||
my $t = $h->{TYPE};
|
||||
@ -772,6 +772,16 @@ FW_doDetail($)
|
||||
}
|
||||
}
|
||||
FW_pO "<table><tr><td>";
|
||||
|
||||
if($modules{$t}{FW_detailFn}) {
|
||||
no strict "refs";
|
||||
FW_pO &{$modules{$t}{FW_detailFn}}($FW_wname, $d, $FW_room) . "<br>";
|
||||
use strict "refs";
|
||||
}
|
||||
|
||||
FW_pO "<form method=\"get\" action=\"$FW_ME\">";
|
||||
FW_pO FW_hidden("detail", $d);
|
||||
|
||||
FW_makeSelect($d, "set", getAllSets($d), "set");
|
||||
FW_makeTable($d, $h); # Internal values
|
||||
FW_pO "Readings" if($h->{READINGS});
|
||||
@ -794,14 +804,9 @@ FW_doDetail($)
|
||||
push(@dob, $dn);
|
||||
}
|
||||
}
|
||||
FW_pO "</form>";
|
||||
FW_makeTableFromArray("Probably associated with", @dob);
|
||||
|
||||
if($modules{$t}{FW_detailFn}) {
|
||||
no strict "refs";
|
||||
FW_pO &{$modules{$t}{FW_detailFn}}($FW_wname, $d, $FW_room) . "<br>";
|
||||
use strict "refs";
|
||||
}
|
||||
|
||||
FW_pO "</td></tr></table>";
|
||||
|
||||
FW_pH "cmd=style iconFor $d", "Select icon";
|
||||
@ -809,7 +814,6 @@ FW_doDetail($)
|
||||
FW_pH "$FW_ME/docs/commandref.html#${t}", "Device specific help";
|
||||
FW_pO "<br><br>";
|
||||
FW_pO "</div>";
|
||||
FW_pO "</form>";
|
||||
|
||||
}
|
||||
|
||||
@ -819,7 +823,7 @@ FW_makeTableFromArray($@) {
|
||||
my ($txt,@obj) = @_;
|
||||
if (@obj>0) {
|
||||
my $row=1;
|
||||
FW_pO "<br>" if($FW_RET !~ m/<br>$/);
|
||||
FW_pO "<br><br>";
|
||||
FW_pO "$txt";
|
||||
FW_pO '<table class="block wide">';
|
||||
foreach (sort @obj) {
|
||||
@ -1533,7 +1537,6 @@ FW_select($$$$$@)
|
||||
$jSelFn = ($jSelFn ? "onchange=\"$jSelFn\"" : "");
|
||||
$id = ($id ? "id=\"$id\"" : "");
|
||||
my $s = "<select $jSelFn $id name=\"$n\" class=\"$class\">";
|
||||
|
||||
foreach my $v (@{$va}) {
|
||||
if($def && $v eq $def) {
|
||||
$s .= "<option selected=\"selected\" value=\"$v\">$v</option>\n";
|
||||
|
@ -316,7 +316,8 @@ FileLog_fhemwebFn($$$$)
|
||||
$list .= " $dev:" . join(",", sort keys %{$dh{$dev}});
|
||||
push @al, $dev;
|
||||
}
|
||||
$ret .= "<tr><td colspan=\"2\"><form autocomplete=\"off\">";
|
||||
$ret .= "<tr class=\"".(($row++&1)?"odd":"even")."\">";
|
||||
$ret .= "<td colspan=\"2\"><form autocomplete=\"off\">";
|
||||
$ret .= FW_hidden("detail", $d);
|
||||
$ret .= FW_hidden("dev.$d", "$d addRegexpPart");
|
||||
$ret .= FW_submit("cmd.$d", "set", "set");
|
||||
@ -328,8 +329,17 @@ FileLog_fhemwebFn($$$$)
|
||||
"FW_selChange('$al[0]','$list','val.$d')</script>";
|
||||
$ret .= "</form></td></tr>";
|
||||
}
|
||||
|
||||
$ret .= "</table>";
|
||||
|
||||
my $newIdx=1;
|
||||
while($defs{"wl_${d}_$newIdx"}) {
|
||||
$newIdx++;
|
||||
}
|
||||
my $name = "wl_${d}_$newIdx";
|
||||
$ret .= FW_pH("cmd=define $name weblink fileplot $d:template:CURRENT;".
|
||||
"set $name copyGplotFile&detail=$name",
|
||||
"<div class=\"dval\">Create new SVG plot</div>", 0, "dval", 1);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,52 @@ SVG_Initialize($)
|
||||
}
|
||||
|
||||
|
||||
######################
|
||||
# Convert the configuration to a "readable" form -> array to hash
|
||||
sub
|
||||
SVG_digestConf($$)
|
||||
{
|
||||
my ($confp,$plot) = @_;
|
||||
|
||||
my %conf;
|
||||
map { chomp; my @a=split(" ",$_, 3);
|
||||
if($a[0] && $a[0] eq "set") { $conf{lc($a[1])} = $a[2]; }
|
||||
} @{$confp};
|
||||
|
||||
$conf{title} = "" if(!defined($conf{title}));
|
||||
$conf{title} =~ s/'//g;
|
||||
|
||||
######################
|
||||
# Digest grid
|
||||
my $t = ($conf{grid} ? $conf{grid} : "");
|
||||
#$conf{hasxgrid} = ( $t =~ /.*xtics.*/ ? 1 : 0); # Unused
|
||||
$conf{hasygrid} = ( $t =~ /.*ytics.*/ ? 1 : 0);
|
||||
$conf{hasy2grid}= ( $t =~ /.*y2tics.*/ ? 1 : 0);
|
||||
|
||||
# Digest axes/title/etc from $plot (gnuplot) and draw the line-titles
|
||||
my (@lAxis,@lTitle,@lType,@lStyle,@lWidth);
|
||||
my ($i, $pTemp);
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ axes (\w+)/$lAxis[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ title '([^']*)'/$lTitle[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ with (\w+)/$lType[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ ls (\w+)/$lStyle[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ lw (\w+)/$lWidth[$i++]=$1/gse;
|
||||
|
||||
for my $i (0..int(@lType)-1) { # lAxis is optional
|
||||
$lAxis[$i] = "x1y2" if(!$lAxis[$i]);
|
||||
$lStyle[$i] = "class=\"". (defined($lStyle[$i]) ? $lStyle[$i] : "l$i")."\"";
|
||||
$lWidth[$i] = (defined($lWidth[$i]) ?
|
||||
"style=\"stroke-width:$lWidth[$i]\"" :"");
|
||||
}
|
||||
|
||||
$conf{lAxis} = \@lAxis;
|
||||
$conf{lTitle} = \@lTitle;
|
||||
$conf{lType} = \@lType;
|
||||
$conf{lStyle} = \@lStyle;
|
||||
$conf{lWidth} = \@lWidth;
|
||||
return %conf;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
SVG_render($$$$$$$$)
|
||||
@ -50,15 +96,10 @@ SVG_render($$$$$$$$)
|
||||
|
||||
######################
|
||||
# Convert the configuration to a "readable" form -> array to hash
|
||||
my %conf; # gnuplot file settings
|
||||
map { chomp; my @a=split(" ",$_, 3);
|
||||
if($a[0] && $a[0] eq "set") { $conf{lc($a[1])} = $a[2]; } } @{$confp};
|
||||
my %conf = SVG_digestConf($confp, $plot);
|
||||
|
||||
my $ps = "800,400";
|
||||
$ps = $1 if($conf{terminal} =~ m/.*size[ ]*([^ ]*)/);
|
||||
$conf{title} = "" if(!defined($conf{title}));
|
||||
$conf{title} =~ s/'//g;
|
||||
|
||||
my ($ow,$oh) = split(",", $ps); # Original width
|
||||
my ($w, $h) = ($ow-2*$x, $oh-2*$y); # Rect size
|
||||
|
||||
@ -113,16 +154,9 @@ SVG_render($$$$$$$$)
|
||||
"onclick=\"parent.svg_copy(evt)\" " .
|
||||
"class=\"copy\" text-anchor=\"end\"> </text>";
|
||||
|
||||
######################
|
||||
# Digest grid
|
||||
my $t = ($conf{grid} ? $conf{grid} : "");
|
||||
my $hasxgrid = ( $t =~ /.*xtics.*/ ? 1 : 0);
|
||||
my $hasygrid = ( $t =~ /.*ytics.*/ ? 1 : 0);
|
||||
my $hasy2grid = ( $t =~ /.*y2tics.*/ ? 1 : 0);
|
||||
|
||||
######################
|
||||
# Left label = ylabel and right label = y2label
|
||||
$t = ($conf{ylabel} ? $conf{ylabel} : "");
|
||||
my $t = ($conf{ylabel} ? $conf{ylabel} : "");
|
||||
$t =~ s/"//g;
|
||||
if(!$SVG_ss) {
|
||||
($off1,$off2) = (3*$th/4, $oh/2);
|
||||
@ -137,29 +171,14 @@ SVG_render($$$$$$$$)
|
||||
}
|
||||
|
||||
######################
|
||||
# Digest axes/title/etc from $plot (gnuplot) and draw the line-titles
|
||||
my (@lAxis,@lTitle,@lType,@lStyle,@lWidth);
|
||||
my ($i, $pTemp);
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ axes (\w+)/$lAxis[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ title '([^']*)'/$lTitle[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ with (\w+)/$lType[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ ls (\w+)/$lStyle[$i++]=$1/gse;
|
||||
$pTemp = $plot; $i = 0; $pTemp =~ s/ lw (\w+)/$lWidth[$i++]=$1/gse;
|
||||
|
||||
for my $i (0..int(@lType)-1) { # lAxis is optional
|
||||
$lAxis[$i] = "x1y2" if(!$lAxis[$i]);
|
||||
$lStyle[$i] = "class=\"". (defined($lStyle[$i]) ? $lStyle[$i] : "l$i") . "\"";
|
||||
$lWidth[$i] = (defined($lWidth[$i]) ? "style=\"stroke-width:$lWidth[$i]\"" :"");
|
||||
}
|
||||
|
||||
($off1,$off2) = ($ow-$x-$th, $y+$th);
|
||||
|
||||
|
||||
######################
|
||||
# Plot caption (title)
|
||||
for my $i (0..int(@lTitle)-1) {
|
||||
for my $i (0..int(@{$conf{lTitle}})-1) {
|
||||
my $j = $i+1;
|
||||
my $t = $lTitle[$i];
|
||||
my $t = $conf{lTitle}[$i];
|
||||
my $desc = "";
|
||||
if(defined($data{"min$j"}) && $data{"min$j"} ne "undef") {
|
||||
$desc = sprintf("%s: Min:%g Max:%g Last:%g",
|
||||
@ -167,7 +186,8 @@ SVG_render($$$$$$$$)
|
||||
}
|
||||
SVG_pO "<text title=\"$desc\" ".
|
||||
"onclick=\"parent.svg_labelselect(evt)\" line_id=\"line_$i\" " .
|
||||
"x=\"$off1\" y=\"$off2\" text-anchor=\"end\" $lStyle[$i]>$t</text>";
|
||||
"x=\"$off1\" y=\"$off2\" text-anchor=\"end\" ".
|
||||
"$conf{lStyle}[$i]>$t</text>";
|
||||
$off2 += $th;
|
||||
}
|
||||
|
||||
@ -195,7 +215,7 @@ SVG_render($$$$$$$$)
|
||||
}
|
||||
$dpoff = $ndpoff+1;
|
||||
if($l =~ m/^#/) {
|
||||
my $a = $lAxis[$idx];
|
||||
my $a = $conf{lAxis}[$idx];
|
||||
if(defined($a)) {
|
||||
$hmin{$a} = $min if(!defined($hmin{$a}) || $hmin{$a} > $min);
|
||||
$hmax{$a} = $max if(!defined($hmax{$a}) || $hmax{$a} < $max);
|
||||
@ -338,7 +358,7 @@ SVG_render($$$$$$$$)
|
||||
$step = $l/10;
|
||||
last;
|
||||
}
|
||||
if($step == 0.001 && $hmax{$a} == $hmin{$a}) { # Don't want 0.001 range for nil
|
||||
if($step==0.001 && $hmax{$a}==$hmin{$a}) { # Don't want 0.001 range for nil
|
||||
$step = 1;
|
||||
$ma = $mi + $step;
|
||||
}
|
||||
@ -403,7 +423,7 @@ SVG_render($$$$$$$$)
|
||||
#-- tics handling
|
||||
my $tic = $htics{$a};
|
||||
#-- tics as in the config-file
|
||||
if($tic && $tic !~ m/mirror/) {
|
||||
if($tic && $tic !~ m/mirror/) {
|
||||
$tic =~ s/^\((.*)\)$/$1/; # Strip ()
|
||||
foreach my $onetic (split(",", $tic)) {
|
||||
$onetic =~ s/^ *(.*) *$/$1/;
|
||||
@ -416,12 +436,12 @@ SVG_render($$$$$$$$)
|
||||
SVG_pO "<polyline points=\"$off3,$off2 $off4,$off2\" $cll/>";
|
||||
#--grids
|
||||
my $off6 = $x+$w;
|
||||
if( ($a eq "x1y1") && $hasygrid ) {
|
||||
if( ($a eq "x1y1") && $conf{hasygrid} ) {
|
||||
SVG_pO "<polyline points=\"$x,$off2 $off6,$off2\" class=\"vgrid\"/>"
|
||||
if($tvalue > $hmin{$a} && $tvalue < $hmax{$a});
|
||||
}elsif( ($a eq "x1y2") && $conf{hasy2grid} ) {
|
||||
SVG_pO " <polyline points=\"$x,$off2 $off6,$off2\" class=\"vgrid\"/>"
|
||||
if($i > $hmin{$a} && $i < $hmax{$a});
|
||||
}elsif( ($a eq "x1y2") && $hasy2grid ) {
|
||||
SVG_pO " <polyline points=\"$x,$off2 $off6,$off2\" class=\"vgrid\"/>"
|
||||
if($i > $hmin{$a} && $i < $hmax{$a});
|
||||
if($tvalue > $hmin{$a} && $tvalue < $hmax{$a});
|
||||
}
|
||||
$off2 += $th/4;
|
||||
#-- text
|
||||
@ -435,11 +455,11 @@ SVG_render($$$$$$$$)
|
||||
SVG_pO " <polyline points=\"$off3,$off2 $off4,$off2\" $cll/>";
|
||||
#--grids
|
||||
my $off6 = $x+$w;
|
||||
if( ($a eq "x1y1") && $hasygrid ) {
|
||||
if( ($a eq "x1y1") && $conf{hasygrid} ) {
|
||||
my $off6 = $x+$w;
|
||||
SVG_pO " <polyline points=\"$x,$off2 $off6,$off2\" class=\"vgrid\"/>"
|
||||
if($i > $hmin{$a} && $i < $hmax{$a});
|
||||
}elsif( ($a eq "x1y2") && $hasy2grid ) {
|
||||
}elsif( ($a eq "x1y2") && $conf{hasy2grid} ) {
|
||||
SVG_pO " <polyline points=\"$x,$off2 $off6,$off2\" class=\"vgrid\"/>"
|
||||
if($i > $hmin{$a} && $i < $hmax{$a});
|
||||
}
|
||||
@ -456,7 +476,7 @@ SVG_render($$$$$$$$)
|
||||
######################
|
||||
# Second loop over the data: draw the measured points
|
||||
for(my $idx=$#hdx; $idx >= 0; $idx--) {
|
||||
my $a = $lAxis[$idx];
|
||||
my $a = $conf{lAxis}[$idx];
|
||||
|
||||
SVG_pO "<!-- Warning: No axis for data item $idx defined -->" if(!defined($a));
|
||||
next if(!defined($a));
|
||||
@ -470,19 +490,20 @@ SVG_render($$$$$$$$)
|
||||
|
||||
my $yh = $y+$h;
|
||||
#-- Title attributes
|
||||
my $tl = $lTitle[$idx] ? $lTitle[$idx] : "";
|
||||
my $tl = $conf{lTitle}[$idx] ? $conf{lTitle}[$idx] : "";
|
||||
#my $dec = int(log($hmul*3)/log(10)); # perl can be compiled without log() !
|
||||
my $dec = length(sprintf("%d",$hmul*3))-1;
|
||||
$dec = 0 if($dec < 0);
|
||||
my $attributes = "id=\"line_$idx\" decimals=\"$dec\" ".
|
||||
"x_off=\"$fromsec\" x_min=\"$x\" x_mul=\"$tmul\" ".
|
||||
"y_h=\"$yh\" y_min=\"$min\" y_mul=\"$hmul\" title=\"$tl\" ".
|
||||
"onclick=\"parent.svg_click(evt)\" $lWidth[$idx] $lStyle[$idx]";
|
||||
my $isFill = ($lStyle[$idx] =~ m/fill/);
|
||||
"onclick=\"parent.svg_click(evt)\" ".
|
||||
"$conf{lWidth}[$idx] $conf{lStyle}[$idx]";
|
||||
my $isFill = ($conf{lStyle}[$idx] =~ m/fill/);
|
||||
|
||||
my ($lx, $ly) = (-1,-1);
|
||||
|
||||
if($lType[$idx] eq "points" ) {
|
||||
if($conf{lType}[$idx] eq "points" ) {
|
||||
foreach my $i (0..int(@{$dxp})-1) {
|
||||
my ($x1, $y1) = (int($x+$dxp->[$i]),
|
||||
int($y+$h-($dyp->[$i]-$min)*$hmul));
|
||||
@ -493,7 +514,7 @@ SVG_render($$$$$$$$)
|
||||
SVG_pO "<polyline $attributes points=\"$ret\"/>";
|
||||
}
|
||||
|
||||
} elsif($lType[$idx] eq "steps" || $lType[$idx] eq "fsteps" ) {
|
||||
} elsif($conf{lType}[$idx] eq "steps" || $conf{lType}[$idx] eq "fsteps" ) {
|
||||
|
||||
$ret .= sprintf(" %d,%d", $x+$dxp->[0], $y+$h) if($isFill && @{$dxp});
|
||||
if(@{$dxp} == 1) {
|
||||
@ -506,7 +527,7 @@ SVG_render($$$$$$$$)
|
||||
my ($x2, $y2) = ($x+$dxp->[$i], $y+$h-($dyp->[$i] -$min)*$hmul);
|
||||
next if(int($x2) == $lx && int($y1) == $ly);
|
||||
$lx = int($x2); $ly = int($y2);
|
||||
if($lType[$idx] eq "steps") {
|
||||
if($conf{lType}[$idx] eq "steps") {
|
||||
$ret .= sprintf(" %d,%d %d,%d %d,%d", $x1,$y1, $x2,$y1, $x2,$y2);
|
||||
} else {
|
||||
$ret .= sprintf(" %d,%d %d,%d %d,%d", $x1,$y1, $x1,$y2, $x2,$y2);
|
||||
@ -517,7 +538,7 @@ SVG_render($$$$$$$$)
|
||||
|
||||
SVG_pO "<polyline $attributes points=\"$ret\"/>";
|
||||
|
||||
} elsif($lType[$idx] eq "histeps" ) {
|
||||
} elsif($conf{lType}[$idx] eq "histeps" ) {
|
||||
$ret .= sprintf(" %d,%d", $x+$dxp->[0], $y+$h) if($isFill && @{$dxp});
|
||||
if(@{$dxp} == 1) {
|
||||
my $y1 = $y+$h-($dyp->[0]-$min)*$hmul;
|
||||
@ -536,7 +557,7 @@ SVG_render($$$$$$$$)
|
||||
$ret .= sprintf(" %d,%d", $lx, $y+$h) if($isFill && $lx > -1);
|
||||
SVG_pO "<polyline $attributes points=\"$ret\"/>";
|
||||
|
||||
} elsif( $lType[$idx] eq "bars" ) {
|
||||
} elsif( $conf{lType}[$idx] eq "bars" ) {
|
||||
if(@{$dxp} == 1) {
|
||||
my $y1 = $y+$h-($dyp->[0]-$min)*$hmul;
|
||||
$ret .= sprintf(" %d,%d %d,%d %d,%d %d,%d",
|
||||
|
@ -10,6 +10,10 @@ use vars qw(%FW_hiddenroom); # hash of hidden rooms, used by weblink
|
||||
use vars qw($FW_plotmode);# Global plot mode (WEB attribute), used by weblink
|
||||
use vars qw($FW_plotsize);# Global plot size (WEB attribute), used by weblink
|
||||
use vars qw(%FW_pos); # scroll position
|
||||
use vars qw($FW_gplotdir);# gplot directory for web server: the first
|
||||
use vars qw(%FW_webArgs); # all arguments specified in the GET
|
||||
|
||||
use IO::File;
|
||||
|
||||
#####################################
|
||||
sub
|
||||
@ -20,9 +24,11 @@ weblink_Initialize($)
|
||||
$hash->{DefFn} = "weblink_Define";
|
||||
$hash->{AttrList} = "fixedrange plotmode plotsize label ".
|
||||
"title htmlattr plotfunction";
|
||||
$hash->{SetFn} = "weblink_Set";
|
||||
$hash->{FW_summaryFn} = "weblink_FwFn";
|
||||
$hash->{FW_detailFn} = "weblink_FwFn";
|
||||
$hash->{FW_atPageEnd} = 1;
|
||||
$data{FWEXT}{"/weblinkDetails"}{FUNC} = "weblink_WriteGplot";
|
||||
}
|
||||
|
||||
|
||||
@ -44,6 +50,38 @@ weblink_Define($$)
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
weblink_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
my $me = $hash->{NAME};
|
||||
return "no set argument specified" if(int(@a) < 2);
|
||||
my %sets = (copyGplotFile=>0);
|
||||
|
||||
my $cmd = $a[1];
|
||||
return "Unknown argument $cmd, choose one of ".join(" ",sort keys %sets)
|
||||
if(!defined($sets{$cmd}));
|
||||
return "$cmd needs $sets{$cmd} parameter(s)" if(@a-$sets{$cmd} != 2);
|
||||
|
||||
if($cmd eq "copyGplotFile") {
|
||||
return "type is not fileplot" if($hash->{WLTYPE} ne "fileplot");
|
||||
my @a = split(":", $hash->{LINK});
|
||||
my $srcName = "$FW_gplotdir/$a[1].gplot";
|
||||
$a[1] = $hash->{NAME};
|
||||
my $dstName = "$FW_gplotdir/$a[1].gplot";
|
||||
$hash->{LINK} = join(":", @a);
|
||||
$hash->{DEF} = "$hash->{WLTYPE} $hash->{LINK}";
|
||||
open(SFH, $srcName) || return "Can't open $srcName: $!";
|
||||
open(DFH, ">$dstName") || return "Can't open $dstName: $!";
|
||||
while(my $l = <SFH>) {
|
||||
print DFH $l;
|
||||
}
|
||||
close(SFH); close(DFH);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#####################################
|
||||
# FLOORPLAN compat
|
||||
sub
|
||||
@ -143,12 +181,209 @@ weblink_FwFn($$$$)
|
||||
$ret .= "<img src=\"$arg\"/>";
|
||||
}
|
||||
|
||||
$ret .= weblink_FwDetail($d) if(!$FW_hiddenroom{detail} && $pageHash);
|
||||
if(!$pageHash) {
|
||||
$ret .= wl_PEdit($FW_wname,$d,$room,$pageHash)
|
||||
if($wltype eq "fileplot" && $FW_plotmode eq "SVG");
|
||||
$ret .= "<br>";
|
||||
|
||||
} else {
|
||||
$ret .= weblink_FwDetail($d) if(!$FW_hiddenroom{detail});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub
|
||||
wl_cb($$$)
|
||||
{
|
||||
my ($v,$t,$c) = @_;
|
||||
$c = ($c ? " checked" : "");
|
||||
return "<td>$t <input type=\"checkbox\" name=\"$v\" value=\"$v\"$c></td>";
|
||||
}
|
||||
|
||||
sub
|
||||
wl_txt($$$$)
|
||||
{
|
||||
my ($v,$t,$c,$sz) = @_;
|
||||
$c = "" if(!defined($c));
|
||||
$c =~ s/"//g;
|
||||
return "$t <input type=\"text\" name=\"$v\" size=\"$sz\" ".
|
||||
"value=\"$c\"/>";
|
||||
}
|
||||
|
||||
sub
|
||||
wl_sel($$$@)
|
||||
{
|
||||
my ($v,$l,$c,$fnData) = @_;
|
||||
my @al = split(",",$l);
|
||||
return FW_select($v,$v,\@al,$c, "set", $fnData);
|
||||
}
|
||||
|
||||
sub
|
||||
wl_getRegFromFile($)
|
||||
{
|
||||
my ($fName) = @_;
|
||||
my $fh = new IO::File $fName;
|
||||
if(!$fh) {
|
||||
Log 1, "$fName: $!";
|
||||
return (3, "NoFile", "NoFile");
|
||||
}
|
||||
$fh->seek(0, 2); # Go to the end
|
||||
my $sz = $fh->tell;
|
||||
$fh->seek($sz > 65536 ? $sz-65536 : 0, 0);
|
||||
my $data = <$fh>;
|
||||
my $maxcols = 0;
|
||||
my %h;
|
||||
while($data = <$fh>) {
|
||||
my @cols = split(" ", $data);
|
||||
$maxcols = @cols if(@cols > $maxcols);
|
||||
$cols[2] =~ s/:/./g;
|
||||
my $key = "$cols[1].$cols[2]";
|
||||
$h{$key} = $data;
|
||||
}
|
||||
$fh->close();
|
||||
return ($maxcols+1,
|
||||
join(",", sort keys %h),
|
||||
join("<br>", map { $h{$_} } sort keys %h)),
|
||||
close(FH);
|
||||
}
|
||||
|
||||
############################
|
||||
# gnuplot file "editor"
|
||||
sub
|
||||
wl_PEdit($$$$)
|
||||
{
|
||||
my ($FW_wname,$d,$room,$pageHash) = @_;
|
||||
my @a = split(":", $defs{$d}{LINK});
|
||||
my $gp = "$FW_gplotdir/$a[1].gplot";
|
||||
my $file = $defs{$a[0]}{currentlogfile};
|
||||
|
||||
my ($err, $cfg, $plot, $flog) = FW_readgplotfile($d, $gp, $file);
|
||||
($cfg, $plot) = FW_substcfg(1, $d, $cfg, $plot, $file, "<OuT>");
|
||||
my %conf = SVG_digestConf($cfg, $plot);
|
||||
|
||||
my $ret .= "<br><form autocomplete=\"off\" action=\"$FW_ME/weblinkDetails\">";
|
||||
$ret .= FW_hidden("detail", $d);
|
||||
$ret .= FW_hidden("gplotName", $gp);
|
||||
$ret .= "<table class=\"block wide\">";
|
||||
$ret .= "<tr class=\"odd\">";
|
||||
$ret .= "<td>Label</td>";
|
||||
$ret .= "<td>".wl_txt("ylabel", "left", $conf{ylabel}, 16)."</td>";
|
||||
$ret .= "<td>".wl_txt("y2label","right", $conf{y2label}, 16)."</td>";
|
||||
$ret .= "</tr>";
|
||||
$ret .= "<tr class=\"even\">";
|
||||
$ret .= "<td>Tics as (\"Txt\" val, ...)</td>";
|
||||
$ret .= "<td>".wl_txt("ytics", "left", $conf{ytics}, 16)."</td>";
|
||||
$ret .= "<td>".wl_txt("y2tics","right", $conf{y2tics}, 16)."</td>";
|
||||
$ret .= "</tr>";
|
||||
$ret .= "<tr class=\"odd\">";
|
||||
$ret .= "<td>Grid aligned</td>";
|
||||
$ret .= wl_cb("gridy", "left", $conf{hasygrid});
|
||||
$ret .= wl_cb("gridy2","right",$conf{hasy2grid});
|
||||
$ret .= "</tr>";
|
||||
$ret .= "<tr class=\"even\">";
|
||||
$ret .= "<td>Range as [min:max]</td>";
|
||||
$ret .= "<td>".wl_txt("yrange", "left", $conf{yrange}, 16)."</td>";
|
||||
$ret .= "<td>".wl_txt("y2range", "right", $conf{y2range}, 16)."</td>";
|
||||
$ret .= "</tr>";
|
||||
|
||||
$ret .= "<tr class=\"odd\"><td>Label</td>";
|
||||
$ret .= "<td>Column,Regexp,DefaultValue,Function</td>";
|
||||
$ret .=" <td>Y-Axis,Plot-Type,Style</td></tr>";
|
||||
|
||||
my ($colnums, $colregs, $coldata) = wl_getRegFromFile($file);
|
||||
$colnums = join(",", 3..$colnums);
|
||||
my $max = @{$conf{lAxis}}+1;
|
||||
$max = 7 if($max > 7);
|
||||
my $r = 0;
|
||||
for($r=0; $r < $max; $r++) {
|
||||
$ret .= "<tr class=\"".(($r&1)?"odd":"even")."\"><td>";
|
||||
$ret .= wl_txt("title_${r}", "", $conf{lTitle}[$r], 12);
|
||||
$ret .= "</td><td>";
|
||||
my @f = split(":", ($flog->[$r] ? $flog->[$r] : ":::"), 4);
|
||||
$ret .= wl_sel("cl_${r}", $colnums, $f[0]);
|
||||
$ret .= wl_sel("re_${r}", $colregs, $f[1]);
|
||||
$ret .= wl_txt("df_${r}", "", $f[2], 2);
|
||||
$ret .= wl_txt("fn_${r}", "", $f[3], 6);
|
||||
|
||||
$ret .= "</td><td>";
|
||||
my $v = $conf{lAxis}[$r];
|
||||
$ret .= wl_sel("axes_${r}", "left,right",
|
||||
($v && $v eq "x1y1") ? "left" : "right");
|
||||
$ret .= wl_sel("type_${r}", "lines,points,steps,fsteps,histeps,bars",
|
||||
$conf{lType}[$r]);
|
||||
my $ls = $conf{lStyle}[$r];
|
||||
if($ls) {
|
||||
$ls =~ s/class=//g;
|
||||
$ls =~ s/"//g;
|
||||
}
|
||||
$ret .= wl_sel("style_${r}", "l0,l1,l2,l3,l4,l5,l6,l7,l8,".
|
||||
"l0fill,l1fill,l2fill,l3fill,l4fill,l5fill,l6fill", $ls);
|
||||
$ret .= "</td></tr>";
|
||||
}
|
||||
$ret .= "<tr class=\"".(($r++&1)?"odd":"even")."\"><td colspan=\"3\">";
|
||||
$ret .= "Example lines for each regexp:<br>$coldata</td></tr>";
|
||||
|
||||
$ret .= "<tr class=\"".(($r++&1)?"odd":"even")."\"><td colspan=\"3\">";
|
||||
$ret .= FW_submit("submit", "Write .gplot file")."</td></tr>";
|
||||
|
||||
$ret .= "</table></form>";
|
||||
}
|
||||
|
||||
sub
|
||||
weblink_WriteGplot($)
|
||||
{
|
||||
my ($arg) = @_;
|
||||
FW_digestCgi($arg);
|
||||
|
||||
my $fName = $FW_webArgs{gplotName};
|
||||
return if(!$fName);
|
||||
if(!open(FH, ">$fName")) {
|
||||
Log 1, "weblink_WriteGplot: Can't write $fName";
|
||||
return;
|
||||
}
|
||||
print FH "# Created by FHEMWEB, ".TimeNow()."\n";
|
||||
print FH "set terminal png transparent size <SIZE> crop\n";
|
||||
print FH "set output '<OUT>.png'\n";
|
||||
print FH "set xdata time\n";
|
||||
print FH "set timefmt \"%Y-%m-%d_%H:%M:%S\"\n";
|
||||
print FH "set xlabel \" \"\n";
|
||||
print FH "set title '<L1>'\n";
|
||||
print FH "set ytics ".$FW_webArgs{ytics}."\n";
|
||||
print FH "set y2tics ".$FW_webArgs{y2tics}."\n";
|
||||
print FH "set grid".($FW_webArgs{gridy} ? " ytics" :"").
|
||||
($FW_webArgs{gridy2} ? " y2tics":"")."\n";
|
||||
print FH "set ylabel \"$FW_webArgs{ylabel}\"\n";
|
||||
print FH "set y2label \"$FW_webArgs{y2label}\"\n";
|
||||
print FH "set yrange $FW_webArgs{yrange}\n" if($FW_webArgs{yrange});
|
||||
print FH "set y2range $FW_webArgs{yrange}\n" if($FW_webArgs{y2range});
|
||||
print FH "\n";
|
||||
|
||||
my @plot;
|
||||
for(my $i=0; $i <= 8; $i++) {
|
||||
next if(!$FW_webArgs{"title_$i"});
|
||||
print FH "#FileLog ". $FW_webArgs{"cl_$i"} .":".
|
||||
$FW_webArgs{"re_$i"} .":".
|
||||
$FW_webArgs{"df_$i"} .":".
|
||||
$FW_webArgs{"fn_$i"} ."\n";
|
||||
push @plot, "\"<IN>\" using 1:2 axes ".
|
||||
($FW_webArgs{"axes_$i"} eq "right" ? "x1y2" : "x1y1").
|
||||
" title '".$FW_webArgs{"title_$i"} ."'".
|
||||
" ls " .$FW_webArgs{"style_$i"} .
|
||||
" with " .$FW_webArgs{"type_$i"};
|
||||
}
|
||||
print FH "\n";
|
||||
print FH "plot ".join(",\\\n ", @plot)."\n";
|
||||
close(FH);
|
||||
|
||||
#foreach my $k (sort keys %FW_webArgs) {
|
||||
# Log 1, "$k: $FW_webArgs{$k}";
|
||||
#}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
@ -192,7 +427,16 @@ weblink_FwFn($$$$)
|
||||
</ul>
|
||||
|
||||
<a name="weblinkset"></a>
|
||||
<b>Set</b> <ul>N/A</ul><br>
|
||||
<b>Set</b>
|
||||
<ul>
|
||||
<li>copyGplotFile<br>
|
||||
Only applicable to fileplot type weblinks.<br>
|
||||
Copy the currently specified gplot file to a new file, which is named
|
||||
after the weblink (existing files will be overwritten), in order to be
|
||||
able to modify it locally without the problem of being overwritten by
|
||||
update. The weblink definition will be updated.
|
||||
</li>
|
||||
</ul><br>
|
||||
|
||||
<a name="weblinkget"></a>
|
||||
<b>Get</b> <ul>N/A</ul><br>
|
||||
|
23
fhem/www/gplot/template.gplot
Normal file
23
fhem/www/gplot/template.gplot
Normal file
@ -0,0 +1,23 @@
|
||||
############################
|
||||
# Display the power reported by the EM1010
|
||||
# Corresponding FileLog definition:
|
||||
# define ememlog FileLog /var/log/fhem/emem-%Y.log emem:power.*
|
||||
|
||||
set terminal png transparent size <SIZE> crop
|
||||
set output '<OUT>.png'
|
||||
set xdata time
|
||||
set timefmt "%Y-%m-%d_%H:%M:%S"
|
||||
set xlabel " "
|
||||
|
||||
set title '<TL>'
|
||||
set ylabel "Power (KW)"
|
||||
set y2label "Power (KW)"
|
||||
set grid
|
||||
set ytics
|
||||
set y2tics
|
||||
set format y "%.1f"
|
||||
set format y2 "%.1f"
|
||||
|
||||
#FileLog 4::0:
|
||||
|
||||
plot "<IN>" using 1:4 notitle with lines
|
Loading…
Reference in New Issue
Block a user