mirror of
https://github.com/skaringa/water-counter.git
synced 2024-11-21 17:04:25 +01:00
Website added
This commit is contained in:
parent
8a3a787351
commit
b41b81c9f4
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*~
|
||||
*.bak
|
||||
*.rrd
|
||||
nohup.out
|
||||
*.gif
|
||||
minicom.cap
|
2
graph.sh
2
graph.sh
@ -2,7 +2,7 @@
|
||||
rrdtool graph counter.gif \
|
||||
-s 'now -1 day' -e 'now' \
|
||||
-w 800 -h 600 \
|
||||
-X 0 -A \
|
||||
-A -Y \
|
||||
DEF:counter=water.rrd:counter:LAST \
|
||||
VDEF:lastcount=counter,LAST \
|
||||
"GPRINT:lastcount:%6.3lf m³" \
|
||||
|
119
www/graph.pl
Executable file
119
www/graph.pl
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# CGI script to create image using RRD graph
|
||||
use CGI qw(:all);
|
||||
use RRDs;
|
||||
use POSIX qw(locale_h);
|
||||
|
||||
$ENV{'LANG'}='de_DE.UTF-8';
|
||||
setlocale(LC_ALL, 'de_DE.UTF-8');
|
||||
|
||||
# path to database
|
||||
$rrd='../../water-counter/water.rrd';
|
||||
|
||||
# force to always create image from rrd
|
||||
#$force=1;
|
||||
|
||||
$query=new CGI;
|
||||
#$query=new CGI("type=consumweek&size=small");
|
||||
|
||||
$size=$query->param('size');
|
||||
$type=$query->param('type');
|
||||
if ($size eq 'big') {
|
||||
$width=900;
|
||||
$height=700;
|
||||
$size="b";
|
||||
} else {
|
||||
$width=500;
|
||||
$height=160;
|
||||
$size="s";
|
||||
}
|
||||
die "invalid type\n" unless $type =~ /(count|consum)(day|week|month|year)/;
|
||||
$ds=$1;
|
||||
$range=$2;
|
||||
$filename="/tmp/em${type}_${size}.png";
|
||||
|
||||
# create new image if existing file is older than rrd file
|
||||
my $maxdiff = 10;
|
||||
if ((mtime($rrd) - mtime($filename) > $maxdiff) or $force) {
|
||||
$tmpfile="/tmp/wai${type}_${size}_$$.png";
|
||||
# call sub to create image according to type
|
||||
&$ds($range);
|
||||
# check error
|
||||
my $err=RRDs::error;
|
||||
die "$err\n" if $err;
|
||||
rename $tmpfile, $filename;
|
||||
}
|
||||
|
||||
# feed image to stdout
|
||||
open(IMG, $filename) or die "can't open $filename";
|
||||
print header('image/png');
|
||||
print <IMG>;
|
||||
close IMG;
|
||||
|
||||
# end MAIN
|
||||
|
||||
# Return modification date of file
|
||||
sub mtime {
|
||||
my $file=shift;
|
||||
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$fsize,
|
||||
$atime,$mtime,$ctime,$blksize,$blocks)
|
||||
= stat($file);
|
||||
return $mtime;
|
||||
}
|
||||
|
||||
sub count {
|
||||
my $range = shift;
|
||||
my @opts=(
|
||||
"-w", $width,
|
||||
"-h", $height,
|
||||
"-s", "now - 1 $range",
|
||||
"-e", "now",
|
||||
"-D",
|
||||
"-Y",
|
||||
"-A");
|
||||
RRDs::graph($tmpfile,
|
||||
@opts,
|
||||
"DEF:counter=$rrd:counter:LAST",
|
||||
"LINE2:counter#000000:Zähler",
|
||||
"VDEF:countlast=counter,LAST",
|
||||
"GPRINT:countlast:%.3lf m³"
|
||||
);
|
||||
}
|
||||
|
||||
sub consum {
|
||||
my $range = shift;
|
||||
my @opts=(
|
||||
"-w", $width,
|
||||
"-h", $height,
|
||||
"-D",
|
||||
"-Y",
|
||||
"-A",
|
||||
"-e", "now",
|
||||
"-s"
|
||||
);
|
||||
if ($range eq 'month') {
|
||||
push(@opts, "now - 30 days");
|
||||
} else {
|
||||
push(@opts, "now - 1 $range");
|
||||
}
|
||||
|
||||
if ($range eq 'day') {
|
||||
RRDs::graph($tmpfile,
|
||||
@opts,
|
||||
"DEF:consum=$rrd:consum:AVERAGE",
|
||||
"CDEF:conlpmin=consum,60000,*",
|
||||
"CDEF:conlpd=conlpmin,60,*,24,*",
|
||||
"VDEF:conlpdtotal=conlpd,AVERAGE",
|
||||
"GPRINT:conlpdtotal:Total %4.0lf l/d",
|
||||
"LINE2:conlpmin#00FF00:Verbrauch [l/min]"
|
||||
);
|
||||
} else {
|
||||
RRDs::graph($tmpfile,
|
||||
@opts,
|
||||
"DEF:consum=$rrd:consum:AVERAGE",
|
||||
"CDEF:conlpd=consum,60000,*,60,*,24,*",
|
||||
"LINE2:conlpd#00FF00:l/d"
|
||||
);
|
||||
}
|
||||
}
|
105
www/index.html
Normal file
105
www/index.html
Normal file
@ -0,0 +1,105 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<meta name="viewport" content="initial-scale=1, minimum-scale=0.75, width=device-width"/>
|
||||
<title>Wasserverbrauch</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
// <![CDATA[
|
||||
|
||||
// open table popup window
|
||||
function table(href) {
|
||||
window.open(href, 'table', 'width=400,height=500,scrollbars=yes');
|
||||
return false;
|
||||
}
|
||||
// open graph popup window
|
||||
function graph(href) {
|
||||
window.open(href, 'graph', 'width=950,height=750,scrollbars=no');
|
||||
return false;
|
||||
}
|
||||
// initialize the page
|
||||
function init() {
|
||||
// reload after 5 min
|
||||
window.setTimeout("window.location.reload(true)", 5 * 60 * 1000);
|
||||
}
|
||||
// ]]>
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
body, table, form {
|
||||
font: 10px/16px verdana, arial, helvetica, sans-serif;
|
||||
background-color: white;
|
||||
}
|
||||
h2 {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.datatable {
|
||||
width: 500px;
|
||||
border: 0px;
|
||||
}
|
||||
img.graph {
|
||||
width: 500px;
|
||||
height: 160px;
|
||||
}
|
||||
td {
|
||||
border-width: 0px 0px 1px 0px;
|
||||
border-style: solid;
|
||||
border-color: #998DB3;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body onload="init()">
|
||||
|
||||
<table class="datatable">
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Wasserverbrauch</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Zählerstand (24 h)" id="i0l" class="graph" src="graph.pl?type=countday" title="Zählerstand (24 h)"/>
|
||||
<br/>
|
||||
<a href="graph.pl?type=countday&size=big" onclick="return graph(this.href);">Vergrößern</a>
|
||||
| <a href="table.pl?type=countday" onclick="return table(this.href);" target="table">Tabelle</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Verbrauch (24 h)" id="i1l" class="graph" src="graph.pl?type=consumday" title="Verbrauch (24 h)"/>
|
||||
<br/>
|
||||
<a href="graph.pl?type=consumday&size=big" onclick="return graph(this.href);" >Vergrößern</a>
|
||||
| <a href="table.pl?type=consumday" onclick="return table(this.href);" target="table">Tabelle</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Verbrauch (Woche)" id="i2l" class="graph" src="graph.pl?type=consumweek" title="Verbrauch (Woche)"/>
|
||||
<br/>
|
||||
<a href="graph.pl?type=consumweek&size=big" onclick="return graph(this.href);" >Vergrößern</a>
|
||||
| <a href="table.pl?type=consumweek" onclick="return table(this.href);" target="table">Tabelle</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Verbrauch (Monat)" id="i3l" class="graph" src="graph.pl?type=consummonth" title="Verbrauch (Monat)"/>
|
||||
<br/>
|
||||
<a href="graph.pl?type=consummonth&size=big" onclick="return graph(this.href);" >Vergrößern</a>
|
||||
| <a href="table.pl?type=consummonth" onclick="return table(this.href);" target="table">Tabelle</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Verbrauch (Jahr)" id="i4l" class="graph" src="graph.pl?type=consumyear" title="Verbrauch (Jahr)"/>
|
||||
<br/>
|
||||
<a href="graph.pl?type=consumyear&size=big" onclick="return graph(this.href);" >Vergrößern</a>
|
||||
| <a href="table.pl?type=consumyear" onclick="return table(this.href);" target="table">Tabelle</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
150
www/table.pl
Executable file
150
www/table.pl
Executable file
@ -0,0 +1,150 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# CGI script to create a table of values from RRD
|
||||
use CGI qw(:all *table *Tr);
|
||||
use RRDs;
|
||||
use POSIX qw(strftime);
|
||||
use POSIX qw(locale_h);
|
||||
|
||||
$ENV{'LANG'}='de_DE.UTF-8';
|
||||
setlocale(LC_TIME, 'de_DE.UTF-8');
|
||||
|
||||
# path to database
|
||||
$rrdb='../../water-counter/water.rrd';
|
||||
|
||||
$query=new CGI;
|
||||
#$query=new CGI("type=consumweek");
|
||||
|
||||
print header(-charset=>"utf-8");
|
||||
|
||||
$type=$query->param('type');
|
||||
if ($type !~ /(count|consum)(day|week|month|year)/) {
|
||||
print "Invalid type\n";
|
||||
exit;
|
||||
}
|
||||
$sensor=$1;
|
||||
$range=$2;
|
||||
|
||||
#print "Sensor: $sensor Range: $range\n";
|
||||
|
||||
$timeformat="%a, %d. %b %Y";
|
||||
$resolution=24*60*60;
|
||||
if ($range eq 'day') {
|
||||
$resolution=60*60;
|
||||
$timeformat="%a, %d. %b %Y %H:%M";
|
||||
} elsif ($range eq 'year') {
|
||||
$resolution=7*24*60*60;
|
||||
$timeformat="Wo %d. %b %Y";
|
||||
}
|
||||
|
||||
if ($range eq 'day') {
|
||||
@factors = (1.0, 60000.0); # consumption in l/min
|
||||
@headings = ('m³', 'l/min');
|
||||
@formats = ('%7.3f', '%3.1f');
|
||||
} else {
|
||||
@factors = (1.0, 60000.0*60*24); # consumption l/day
|
||||
@headings = ('m³', 'l/d');
|
||||
@formats = ('%7.3f', '%4.0f');
|
||||
}
|
||||
|
||||
($laststart,$laststep,$lastnames,$lastdata) = getdata($rrdb, 'LAST', $resolution, $range);
|
||||
($avrstart,$avrstep,$avrnames,$avrdata) = getdata($rrdb, 'AVERAGE', $resolution, $range);
|
||||
# print result
|
||||
|
||||
# print heading
|
||||
$style=<<END;
|
||||
<!--
|
||||
body {
|
||||
font: 10px/16px verdana, arial, helvetica, sans-serif;
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
th, td {
|
||||
border-width: 1px 1px 0px 0px;
|
||||
border-style: solid;
|
||||
border-color: #998DB3;
|
||||
text-align: right;
|
||||
width: 50px;
|
||||
}
|
||||
th {
|
||||
background-color: lightgreen;
|
||||
font-weight: normal;
|
||||
}
|
||||
thead {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
background-color: white;
|
||||
z-index: 1;
|
||||
}
|
||||
tbody {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
z-index: -1;
|
||||
}
|
||||
.mindata {
|
||||
color: blue;
|
||||
}
|
||||
.maxdata {
|
||||
color: red;
|
||||
}
|
||||
.time {
|
||||
color: black;
|
||||
text-align: left;
|
||||
width: 100px;
|
||||
}
|
||||
-->
|
||||
END
|
||||
|
||||
print start_html(-title=>"Wasserverbrauch",
|
||||
-style=>{-code=>$style},
|
||||
-meta=>{"viewport"=>"initial-scale=1, minimum-scale=0.75, width=device-width"}
|
||||
);
|
||||
print start_table();
|
||||
print "\n";
|
||||
print thead(Tr(th({-class=>'time'}, ' '), th([@headings])));
|
||||
print "\n";
|
||||
|
||||
# print data
|
||||
$avrstart -= 12*60*60 unless $timeformat =~ / %H:%M$/;
|
||||
for $avrline (@$avrdata) {
|
||||
$lastline = shift(@$lastdata);
|
||||
print start_Tr({-class=>'avrdata'});
|
||||
print td({-class=>'time'}, strftime($timeformat, localtime($avrstart)));
|
||||
print formatline(@$lastline[0], @$avrline[1]);
|
||||
print end_Tr;
|
||||
print "\n";
|
||||
|
||||
$avrstart += $avrstep;
|
||||
}
|
||||
print end_table();
|
||||
print end_html;
|
||||
|
||||
sub getdata {
|
||||
my ($db, $cf, $resolution, $range) = @_;
|
||||
|
||||
my $sarg = "now -1 $range";
|
||||
if ($range eq 'month') {
|
||||
$sarg = "now - 30 days";
|
||||
}
|
||||
my ($start,$step,$names,$data) = RRDs::fetch($db, $cf, '-r', $resolution, '-s', $sarg, '-e', 'now');
|
||||
|
||||
# check error
|
||||
my $err=RRDs::error;
|
||||
print "$err\n" if $err;
|
||||
exit if $err;
|
||||
return ($start,$step,$names,$data);
|
||||
}
|
||||
|
||||
sub formatline {
|
||||
my $str = '';
|
||||
my $i = 0;
|
||||
for $val (@_) {
|
||||
if (defined $val) {
|
||||
$str .= td(sprintf $formats[$i], $val * $factors[$i]);
|
||||
} else {
|
||||
$str .= td;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
return $str;
|
||||
}
|
Loading…
Reference in New Issue
Block a user