1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4 <html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
12 var tmin, tmax, tfact;
13 var xzero = 20, yzero = 20;
14 var cold_d = [], hot_d = [];
16 function showdate(utime) {
17 var dt = new Date(utime*1000);
18 return dt.toLocaleDateString() + " " + dt.toLocaleTimeString();
21 function getcomb(lo, hi) {
22 var comb = [], lb = [];
24 var ord = Math.pow(10, Math.floor(Math.log10(d)));
25 var scl = Math.floor(d / ord);
26 var inc, inc2, first, x, lb;
28 if (scl < 2) { inc = 0.1; inc2 = 0.5; }
29 else if (scl < 5) { inc = 0.2; inc2 = 1; }
30 else { inc = 0.5; inc2 = 2; }
33 first = (Math.floor(lo / inc) + 1) * inc;
34 for (x = 0; x < (d / inc) - 1.5; x++)
35 comb.push(first + inc * x);
36 first = (Math.floor(lo / inc2) + 1) * inc2;
37 for (x = 0; x < (d / inc2) - 1.5; x++)
38 lb.push(first + inc2 * x);
39 //dbg.innerHTML = "ord=" + ord + "<br>inc=" + inc + "<br>"
40 // + comb + "<br>" + lb;
45 return xzero + ((x - tmin) * tfact);
49 return wh - yzero - (y * hfact);
54 ctx.moveTo(px(tmin), py(0));
55 ctx.lineTo(px(tmax), py(0));
56 ctx.strokeStyle = "black";
59 ctx.fillStyle = "black";
60 ctx.font = "bold 8px Courier";
61 ctx.textAlign = "left";
62 ctx.fillText(showdate(tmin), px(tmin), py(0) + 16);
63 ctx.textAlign = "right";
64 ctx.fillText(showdate(tmax), px(tmax), py(0) + 16);
68 var comb = getcomb(0, hmax);
72 for (i = 0; comb[0][i]; i++) {
73 ctx.moveTo(px(tmin) - 5, py(comb[0][i]));
74 ctx.lineTo(px(tmax), py(comb[0][i]));
76 ctx.strokeStyle = "lightgray";
80 ctx.moveTo(px(tmin), py(0));
81 ctx.lineTo(px(tmin), py(hmax));
82 ctx.strokeStyle = "black";
85 ctx.fillStyle = "black";
86 ctx.font = "bold 8px Courier";
87 ctx.textAlign = "right";
88 ctx.fillText(0, px(tmin) - 2, py(0));
89 for (i = 0; comb[1][i]; i++) {
90 ctx.fillText(comb[1][i], px(tmin) - 2, py(comb[1][i]));
92 ctx.textAlign = "left";
93 ctx.fillText("l/h", px(tmin) + 2, py(hmax) + 8);
96 /* @ updates global var `hmax` */
97 function differentiate(times) {
101 for (i = 0; i < times.length - 1; i++) {
102 dv = times[i+1][1] - times[i][1];
103 dt = times[i+1][0] - times[i][0];
104 if (dt != 0 && dv != 0) {
105 v = (dv / dt) * 360 ; /* Litres per hour */
106 if (hmax < v) hmax = v;
107 res.push([times[i][0], v]);
110 if (i) res.push([times[i][0], v]);
115 function drawplot(data, color) {
119 ctx.moveTo(px(data[0][0]), py(data[0][1]));
120 for (i = 1; i < data.length; i++) {
121 ctx.lineTo(px(data[i][0]), py(data[i - 1][1]));
122 ctx.lineTo(px(data[i][0]), py(data[i][1]));
124 ctx.strokeStyle = color;
128 function showloading() {
129 ctx.fillStyle = "green";
130 ctx.font = "bold 16px Courier";
131 ctx.textAlign="center";
132 ctx.fillText("...loading...", (ww / 2) , (wh / 2) + 8);
135 function showempty() {
136 ctx.fillStyle = "red";
137 ctx.font = "bold 24px Courier";
138 ctx.textAlign="center";
139 ctx.fillText("No data for the requested time interval",
140 (ww / 2) , (wh / 2) + 8);
143 function clearplot() {
144 ctx.clearRect(0, 0, ww, wh);
149 if (cold_d.length || hot_d.length) {
150 tfact = (ww - xzero) / (tmax - tmin);
151 hfact = (wh - yzero) / hmax;
154 drawplot(cold_d, "blue");
155 drawplot(hot_d, "red");
161 function gotdata(data) {
162 document.getElementById("cold").innerHTML =
163 (data.current.cold / 100).toFixed(2);
164 document.getElementById("hot").innerHTML =
165 (data.current.hot / 100).toFixed(2);
166 tmin = data.range.lo;
167 tmax = data.range.hi;
168 //dbg.innerHTML = "from " + tmin + " to " + tmax
169 // + "<br>from " + showdate(tmin) + " to " + showdate(tmax);
170 /* differetiate() updates hmax */
172 cold_d = differentiate(data.cold);
173 hot_d = differentiate(data.hot);
174 //dbg.innerHTML = "hmax=" + hmax + " hfact=" + hfact + "<br>"
175 // + cold_d + "<br>" + hot_d;
179 function iso2qu(idate) {
180 return idate.replace("T", "+").replace("0Z", "");
183 function sendquery(lo, hi) {
184 var url = "query.cgi" + "?lo=" + iso2qu(lo) + "&hi=" + iso2qu(hi);
186 //dbg.innerHTML = url;
187 xmlhttp.onreadystatechange = function() {
188 if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
189 // dbg.innerHTML = xmlhttp.responseText;
190 var myData = JSON.parse(xmlhttp.responseText);
194 xmlhttp.open("GET", url, true);
201 ww = window.innerWidth - 4;
202 if (ww > window.innerHeight) ww = window.innerHeight;
206 canvas.style.width = ww + "px";
207 canvas.style.height = wh + "px";
211 function daystart(date) {
212 date.setMilliseconds(0);
219 function prevweek() {
220 var tdy = daystart(new Date());
221 var dow = tdy.getDay();
224 wstart = new Date(1*tdy - 86400000 * (dow + 7));
225 wend = new Date(1*wstart + 86400000 * 7);
226 xmlhttp = new XMLHttpRequest();
227 sendquery(wstart.toISOString(), wend.toISOString());
230 function thisweek() {
231 var tdy = daystart(new Date());
232 var dow = tdy.getDay();
235 wstart = new Date(1*tdy - 86400000 * dow);
236 wend = new Date(1*wstart + 86400000 * 7);
237 xmlhttp = new XMLHttpRequest();
238 sendquery(wstart.toISOString(), wend.toISOString());
241 function beforeyesterday() {
242 var tdy = daystart(new Date());
243 var ytd = new Date(1*tdy - 86400000);
244 var byd = new Date(1*ytd - 86400000);
245 xmlhttp = new XMLHttpRequest();
246 sendquery(byd.toISOString(), ytd.toISOString());
249 function yesterday() {
250 var tdy = daystart(new Date());
251 var ytd = new Date(1*tdy - 86400000);
252 xmlhttp = new XMLHttpRequest();
253 sendquery(ytd.toISOString(), tdy.toISOString());
257 var tdy = daystart(new Date());
258 var tmr = new Date(1*tdy + 86400000);
259 xmlhttp = new XMLHttpRequest();
260 sendquery(tdy.toISOString(), tmr.toISOString());
263 function initialize() {
264 dbg = document.getElementById("debug");
265 canvas = document.getElementById("plot");
266 ctx = canvas.getContext("2d");
270 document.getElementById("today").onclick = today;
271 document.getElementById("yesterday").onclick = yesterday;
272 document.getElementById("beforeyesterday").onclick = beforeyesterday;
273 document.getElementById("thisweek").onclick = thisweek;
274 document.getElementById("prevweek").onclick = prevweek;
278 if(window.attachEvent) {
279 window.attachEvent('onload', initialize);
280 window.attachEvent('onresize', resize);
282 window.onload = initialize;
283 window.onresize = resize;
288 font-family: PipeDream;
289 src: url('PIPED.TTF') format('truetype');
290 /* Free to use font from http://www.mlink.net/~paterson/jpfonts.htm */
295 font-family: PipeDream;
298 background-color: lightgray;
314 border: solid 1px black;
319 background-color: #d0e0ff;
323 background-color: #ffd0e0;
331 /*border: solid 1px black;*/
340 display: inline-block;
343 border: solid 1px black;
344 background-color: lightgray;
346 vertical-align: middle;
349 display: inline-block;
350 vertical-align: middle; /* does not work for some reason */
356 <title>Water Meters</title>
358 <h1>WATER METERS</h1>
359 <div id="currentvals">
361 <div class="current" id="cold">cold</div>
362 <div class="current" id="hot">hot</div>
365 <canvas id="plot" width="640" height = "320"></canvas>
368 <div class="query" id="prevweek"><span class="query">PREVIOUS WEEK</span></div>
369 <div class="query" id="beforeyesterday"><span class="query">DAY
370 BEFORE YESTERDAY</span></div>
371 <div class="query" id="yesterday"><span class="query">YESTERDAY</span></div>
372 <div class="query" id="today"><span class="query">TODAY</span></div>
373 <div class="query" id="thisweek"><span class="query">THIS WEEK</span></div>
376 <div id="debug"></div>