fix main graph history slurping
[dweather.git] / templates / index.html.ep
1 % my $url = url_for 'weather';
2 % my $s;
3 <!DOCTYPE html>
4 <html>
5         <head>
6                 <title>DWeather</title>
7                 <meta charset="utf-8">
8                 <meta http-equiv="X-UA-Compatible" content="IE=edge">
9                 <meta name="viewport" content="width=device-width, initial-scale=1">
10
11                 <!-- Latest compiled and minified CSS -->
12                 <link rel="stylesheet" href="css/bootstrap.min.css">
13
14                 <!-- Optional theme -->
15                 <link rel="stylesheet" href="css/bootstrap-theme.min.css">
16
17         </head>
18         <body>
19                 <center><h1>High View Weather</h1></center>
20
21                 <script>
22                 var ws;
23                 var daychart;
24                 var daychart_days = <%= $main::histdays %>;
25                 var windrose;
26                 var windrose_mins = <%= $main::windmins %>;
27                 var windspeed;
28                 var winddir;
29
30                 var h = new Object();
31
32                 function do_debug(text) {
33                         document.getElementById("do_debug").innerHTML = text;
34                 }
35
36                 function update_h(key, value) {
37                         h[key] = value;
38                 }
39
40                 function fill_html(key,value) {
41                         var d = document.getElementById(key);
42                         if (d !== null) {
43                                 d.innerHTML = value;
44                         }
45                 }
46
47                 function traverse(o, func) {
48                         console.log(o);
49                         for (var i in o) {
50                                 if (o[i] !== null && typeof(o[i])==="object") {
51                                         traverse(o[i], func);
52                                 } else {
53                                         func(i, o[i]);
54                                 }
55                         }
56                 }
57
58                 var lastwind = 0;
59                 var lastdir = 0;
60                 var lastt = 0;
61
62                 function startws() {
63                         ws = new WebSocket('<%= $url->to_abs %>');
64
65                         if (typeof(ws) !== null) {
66                                 ws.onmessage = function (event) {
67                                         var js = JSON.parse(event.data);
68                                         if (js !== null && typeof(js) === 'object') {
69                                                 traverse(js, fill_html);
70 //                                              traverse(js, update_h);
71 //                                              document.getElementById("hh").innerHTML = JSON.stringify(h);
72                                                 if ("h" in js) {
73                                                         fill_daychart(js, daychart_days);
74                                                 }
75                                                 if ("r" in js) {
76 //                                                      if (js.t > lastt + 15) {
77                                                                 if ("Wind" in js.r) {
78                                                                         lastwind = js.r.Wind;
79                                                                 } else {
80                                                                         js.r.Wind = lastwind;
81                                                                 }
82                                                                 if ("Dir" in js.r) {
83                                                                         lastdir = js.r.dir;
84                                                                 } else {
85                                                                         js.r.Dir = lastdir;
86                                                                 }
87                                                                 lastt = js.t;
88                                                                 fill_windrose(js, windrose_mins * 24);
89 //                                                      }
90                                                         fill_windspeed(js);
91                                                         fill_winddir(js);
92                                                 }
93                                         }
94                                 };
95                                 ws.onopen = function (event) {
96                                         document.getElementById("wsconnect").innerHTML = 'ws connected to: <%= $url->to_abs %>';
97                                         ws.send('WebSocket support works!');
98                                 };
99                                 ws.onclose = function(event) {
100                                         document.getElementById("wsconnect").innerHTML = 'ws disconnected, refresh to restart';
101                                         ws = null;
102                                 }
103                         } else {
104                                 document.body.innerHTML += 'Webserver only works with Websocket aware browsers';
105                         }
106                 }
107
108                 function start_daychart() {
109                         daychart = new Highcharts.Chart({
110                                 chart: {
111                                         renderTo: 'daychart',
112                                         zoomType: 'xy'
113                                 },
114                                 title: {
115                                         text: 'Five Day Chart'
116                                 },
117                                 xAxis: [{
118                                         type: 'datetime',
119 //                                      categories: [],
120                                         crosshair: true
121                                 }],
122                                 yAxis: [{ // Primary yAxis
123                                         labels: {
124                                                 format: '{value}°C',
125                                                 style: {
126                                                         color: Highcharts.getOptions().colors[2]
127                                                 }
128                                         },
129                                         title: {
130                                                 text: 'Temperature',
131                                                 style: {
132                                                         color: Highcharts.getOptions().colors[2]
133                                                 }
134                                         },
135                                         opposite: true
136
137                                 }, { // Secondary yAxis
138                                         gridLineWidth: 0,
139                                         title: {
140                                                 text: 'Rainfall',
141                                                 style: {
142                                                         color: Highcharts.getOptions().colors[0]
143                                                 }
144                                         },
145                                         labels: {
146                                                 format: '{value} mm',
147                                                 style: {
148                                                         color: Highcharts.getOptions().colors[0]
149                                                 }
150                                         }
151
152                                 }, { // Tertiary yAxis
153                                         gridLineWidth: 0,
154                                         title: {
155                                                 text: 'Sea-Level Pressure',
156                                                 style: {
157                                                         color: Highcharts.getOptions().colors[1]
158                                                 }
159                                         },
160                                         labels: {
161                                                 format: '{value} mb',
162                                                 style: {
163                                                         color: Highcharts.getOptions().colors[1]
164                                                 }
165                                         },
166                                         opposite: true
167                                 }],
168                                 tooltip: {
169                                         shared: true
170                                 },
171                                 legend: {
172                                         layout: 'vertical',
173                                         align: 'left',
174                                         x: 80,
175                                         verticalAlign: 'top',
176                                         y: 55,
177                                         floating: true,
178                                         backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'
179                                 },
180                                 exporting: {
181                                         buttons: {
182                                                 contextButton: {
183                                                         enabled: false
184                                                 }
185                                         }
186                                 }, 
187                                 series: [{
188                                         name: 'Rainfall',
189                                         type: 'column',
190                                         yAxis: 1,
191                                         data: [ 
192                                             <% $s = "";
193                                                    for (@main::last5daysh) { 
194                                                       my $r = $main::json->decode($_);
195                                                       $s .=  "[" . $r->{t}*1000 . "," . $r->{h}->{Rain_1h} . "]," if $r && exists $r->{t} && exists $r->{h}->{Rain_1h};
196                                                    }
197                                                    chop $s if length $s; 
198                                                 %><%= $s %>
199                                         ],
200                                         tooltip: {
201                                                 valueSuffix: ' mm'
202                                         }
203
204                                 }, {
205                                         name: 'Sea-Level Pressure',
206                                         type: 'spline',
207                                         yAxis: 2,
208                                         data: [
209                                                 <% $s = "";
210                                                    for (@main::last5daysh) { 
211                                                       my $r = $main::json->decode($_);
212                                                       $s .=  "[" . $r->{t}*1000 . "," . $r->{h}->{Pressure} . "]," if $r && exists $r->{t} && exists $r->{h}->{Pressure};
213                                                    }
214                                                    chop $s if length $s; 
215                                                 %><%= $s %>
216                                         ],
217                                         marker: {
218                                                 enabled: false
219                                         },
220                                         dashStyle: 'shortdot',
221                                         tooltip: {
222                                                 valueSuffix: ' mb'
223                                         }
224
225                                 }, {
226                                         name: 'Temperature',
227                                         type: 'spline',
228                                         data: [
229                                                 <% $s = "";
230                                                    for (@main::last5daysh) { 
231                                                       my $r = $main::json->decode($_);
232                                                       $s .=  "[" . $r->{t}*1000 . "," . $r->{h}->{Temp_Out} . "]," if $r && exists $r->{t} && exists $r->{h}->{Temp_Out};
233                                                    }
234                                                    chop $s if length $s; 
235                                                 %><%= $s %>
236                                         ],
237                                         tooltip: {
238                                                 valueSuffix: ' °C'
239                                         }
240                                 }]
241                         });
242                 }
243
244                 function start_windrose() {
245
246                         // Load the fonts
247                         Highcharts.createElement('link', {
248                                 href: '//fonts.googleapis.com/css?family=Dosis:400,600',
249                                 rel: 'stylesheet',
250                                 type: 'text/css'
251                         }, null, document.getElementsByTagName('head')[0]);
252
253                         Highcharts.theme = {
254                                 colors: ["#7cb5ec", "#f7a35c", "#90ee7e", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
255                                         "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
256                                 chart: {
257                                         backgroundColor: null,
258                                         style: {
259                                                 fontFamily: "Dosis, sans-serif"
260                                         }
261                                 },
262                                 title: {
263                                         style: {
264                                                 fontSize: '16px',
265                                                 fontWeight: 'bold',
266                                                 textTransform: 'uppercase'
267                                         }
268                                 },
269                                 tooltip: {
270                                         borderWidth: 0,
271                                         backgroundColor: 'rgba(219,219,216,0.8)',
272                                         shadow: false
273                                 },
274                                 legend: {
275                                         itemStyle: {
276                                                 fontWeight: 'bold',
277                                                 fontSize: '13px'
278                                         }
279                                 },
280                                 xAxis: {
281                                         gridLineWidth: 1,
282                                         labels: {
283                                                 style: {
284                                                         fontSize: '12px'
285                                                 }
286                                         }
287                                 },
288                                 yAxis: {
289                                         minorTickInterval: 'auto',
290                                         title: {
291                                                 style: {
292                                                         textTransform: 'uppercase'
293                                                 }
294                                         },
295                                         labels: {
296                                                 style: {
297                                                         fontSize: '12px'
298                                                 }
299                                         }
300                                 },
301                                 plotOptions: {
302                                         candlestick: {
303                                                 lineColor: '#404048'
304                                         }
305                                 },
306
307
308                                 // General
309                                 background2: '#F0F0EA'
310                                 
311                         };
312
313                         // Apply the theme
314                         Highcharts.setOptions(Highcharts.theme);
315
316                         windrose = new Highcharts.Chart({
317                                 chart: {
318                                         polar: true,
319                                         renderTo: 'windrose'
320                                 },
321                                 
322                                 title: {
323                                         text: 'Wind Rose'
324                                 },
325                                 
326                                 pane: {
327                                         startAngle: 0,
328                                         endAngle: 360
329                                 },
330
331                                 xAxis: {
332                                         tickInterval: 15,
333                                         min: 0,
334                                         max: 360,
335                                         labels: {
336                                                 formatter: function () {
337                                                         return this.value + '°';
338                                                 }
339                                         }
340                                 },
341
342                                 yAxis: {
343                                         min: 0
344                                 },
345
346                                 plotOptions: {
347                                         series: {
348                                                 pointStart: 0,
349                                                 pointInterval: 15
350                                         },
351                                         column: {
352                                                 pointPadding: 0,
353                                                 groupPadding: 0
354                                         }
355                                 },
356                                 exporting: {
357                                         buttons: {
358                                                 contextButton: {
359                                                         enabled: false
360                                                 }
361                                         }
362                                 }, 
363
364                                 series: [ {
365                                         type: 'column',
366                                         name: 'Wind mph',
367                                         data: [
368                                                 <% my ($d, $w);
369                                                    $s = "";
370                                                    $d = 0; $w = 0;
371                                                for (@main::last10minsr) {
372                                                       my $r = $main::json->decode($_);
373                                                           if ($r) {
374                                                                   $r->{r}->{Dir} ||= $d;
375                                                                   $r->{r}->{Wind} ||= $w;
376                                                                   $s .=  "[" . $r->{r}->{Dir} . "," . main::nearest(0.1, $r->{r}->{Wind}*2.23694) . "],";
377                                                                   $d = $r->{r}->{Dir};
378                                                                   $w = $r->{r}->{Wind};
379                                                           }
380                                                    } 
381                                                    chop $s if length $s; 
382                                                 %><%= $s %>
383                                         ]
384                                 }]
385                         });
386                 }
387
388                 function start_windspeed() {
389                         windspeed = new Highcharts.Chart({
390                                 chart: {
391                                         type: 'gauge',
392                                         renderTo: 'windspeed',
393                                         plotBackgroundColor: null,
394                                         plotBackgroundImage: null,
395                                         plotBorderWidth: 0,
396                                         plotShadow: false
397                                 },
398
399                                 title: {
400                                         text: 'Wind Speed'
401                                 },
402
403                                 pane: {
404                                         startAngle: -150,
405                                         endAngle: 150,
406                                         background: [{
407                                                 backgroundColor: {
408                                                         linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
409                                                         stops: [
410                                                                 [0, '#FFF'],
411                                                                 [1, '#333']
412                                                         ]
413                                                 },
414                                                 borderWidth: 0,
415                                                 outerRadius: '109%'
416                                         }, {
417                                                 backgroundColor: {
418                                                         linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
419                                                         stops: [
420                                                                 [0, '#333'],
421                                                                 [1, '#FFF']
422                                                         ]
423                                                 },
424                                                 borderWidth: 1,
425                                                 outerRadius: '107%'
426                                         }, {
427                                                 // default background
428                                         }, {
429                                                 backgroundColor: '#DDD',
430                                                 borderWidth: 0,
431                                                 outerRadius: '105%',
432                                                 innerRadius: '103%'
433                                         }]
434                                 },
435
436                                 // the value axis
437                                 yAxis: {
438                                         min: 0,
439                                         max: 50,
440
441                                         minorTickInterval: 'auto',
442                                         minorTickWidth: 1,
443                                         minorTickLength: 10,
444                                         minorTickPosition: 'inside',
445                                         minorTickColor: '#666',
446
447                                         tickPixelInterval: 30,
448                                         tickWidth: 2,
449                                         tickPosition: 'inside',
450                                         tickLength: 10,
451                                         tickColor: '#666',
452                                         labels: {
453                                                 step: 2,
454                                                 rotation: 'auto'
455                                         },
456                                         title: {
457                                                 text: 'mph'
458                                         },
459                                         plotBands: [{
460                                                 from: 0,
461                                                 to: 15,
462                                                 color: '#55BF3B' // green
463                                         }, {
464                                                 from: 16,
465                                                 to: 29,
466                                                 color: '#DDDF0D' // yellow
467                                         }, {
468                                                 from: 30,
469                                                 to: 50,
470                                                 color: '#DF5353' // red
471                                         }]
472                                 },
473                                 exporting: {
474                                         buttons: {
475                                                 contextButton: {
476                                                         enabled: false
477                                                 }
478                                         }
479                                 }, 
480
481                                 series: [{
482                                         name: 'Speed',
483                                         data: [0],
484                                         tooltip: {
485                                                 valueSuffix: ' mph'
486                                         }
487                                 }]
488                         });
489                 }
490
491                 function start_winddir() {
492                         winddir = new Highcharts.Chart({
493                                 chart: {
494                                         type: 'gauge',
495                                         renderTo: 'winddir',
496                                         plotBackgroundColor: null,
497                                         plotBackgroundImage: null,
498                                         plotBorderWidth: 0,
499                                         plotShadow: false
500                                 },
501
502                                 title: {
503                                         text: 'Wind Direction'
504                                 },
505
506                                 pane: {
507                                         startAngle: 0,
508                                         endAngle: 359,
509                                         background: [{
510                                                 backgroundColor: {
511                                                         linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
512                                                         stops: [
513                                                                 [0, '#FFF'],
514                                                                 [1, '#333']
515                                                         ]
516                                                 },
517                                                 borderWidth: 0,
518                                                 outerRadius: '109%'
519                                         }, {
520                                                 backgroundColor: {
521                                                         linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
522                                                         stops: [
523                                                                 [0, '#333'],
524                                                                 [1, '#FFF']
525                                                         ]
526                                                 },
527                                                 borderWidth: 1,
528                                                 outerRadius: '107%'
529                                         }, {
530                                                 // default background
531                                         }, {
532                                                 backgroundColor: '#DDD',
533                                                 borderWidth: 0,
534                                                 outerRadius: '105%',
535                                                 innerRadius: '103%'
536                                         }]
537                                 },
538
539                                 // the value axis
540                                 yAxis: {
541                                         min: 0,
542                                         max: 360,
543
544                                         minorTickInterval: 'auto',
545                                         minorTickWidth: 1,
546                                         minorTickLength: 10,
547                                         minorTickPosition: 'inside',
548                                         minorTickColor: '#666',
549
550                                         tickPixelInterval: 15,
551                                         tickWidth: 2,
552                                         tickPosition: 'inside',
553                                         tickLength: 10,
554                                         tickColor: '#666',
555                                         labels: {
556                                                 step: 2,
557                                                 rotation: 'auto'
558                                         },
559                                         title: {
560                                                 text:  '° deg'
561                                         },
562                                 },
563                                 exporting: {
564                                         buttons: {
565                                                 contextButton: {
566                                                         enabled: false
567                                                 }
568                                         }
569                                 }, 
570
571                                 series: [{
572                                         name: 'Direction',
573                                         data: [0],
574                                         tooltip: {
575                                                 valueSuffix: ' ° deg'
576                                         }
577                                 }]
578                         });
579                 }
580
581                 function fill_daychart(js, days) {
582                         var rainfall = daychart.series[0].data.length > (days * 48);
583                         var pressure = daychart.series[1].data.length > (days * 48);
584                         var temp = daychart.series[2].data.length > (days * 48);
585
586                         var hr = js.h;
587                         var t = js.t * 1000;
588                         var ra = [t, hr.Rain_1h];
589                         var pr = [t, hr.Pressure];
590                         var te = [t, hr.Temp_Out];
591                                 
592 //                      do_debug(js.tm + " " + t + " " + te + "<br>"); 
593                         daychart.series[0].addPoint(ra, true, rainfall);
594                         daychart.series[1].addPoint(pr, true, pressure);
595                         daychart.series[2].addPoint(te, true, temp);
596                 }
597
598                 var conv = 2.23694;
599
600                 function fill_windrose(js, points) {
601                         var p = windrose.series[0].data.length > points;
602                         var rr = js.r;
603                         windrose.series[0].addPoint([rr.Dir, Math.round(rr.Wind*conv)], true, p);
604                 }
605
606                 function fill_windspeed(js) {
607                         var rr = js.r;
608                         var point = windspeed.series[0].points[0];
609                         point.update(Math.round(rr.Wind*conv));
610                 }
611
612                 function fill_winddir(js) {
613                         var rr = js.r;
614                         var point = winddir.series[0].points[0];
615                         point.update(rr.Dir);
616                 }
617
618                 window.onload = function() {
619                         startws();
620                         start_daychart();
621                         start_windrose();
622                         start_windspeed();
623                         start_winddir();
624                         window.setInterval(function() {
625                                 if (ws === null)
626                                         startws();
627                         }, 15000);
628                 }
629
630                 </script>
631
632                 <div id="container">
633                         <div id="daychart" style="min-width: 400px; height: 400px; margin: 0 auto"> </div>
634                 </div>
635
636                 <div id="container">
637                         <table border="0" align="center">
638                                 <tr>
639                                         <td id="windrose" style="min-width: 350px; max-width: 400px; height: 330px; margin: 0 auto"> </td>
640                                         <td id="windspeed" style="min-width: 280px; max-width: 400px; height: 270px; margin: 0 auto"> </td>
641                                         <td id="winddir" style="min-width: 280px; max-width: 400px; height: 270px; margin: 0 auto"> </td>
642                                 </tr>
643                         </table>
644                 </div>
645
646                 <div id="container">
647                         <div id="start-template">
648                                 <br><br>
649                                 <table border=1 width=80% align="center">
650                                         <tr>
651                                                 <th>Time:</th><td><span id="tm"> </span></td>
652                                                 <th>Sunrise:</th><td><span id="Sunrise"> </span></td>
653                                                 <th>Sunset:</th><td><span id="Sunset"> </span></td>
654                                                 <th>Console Volts:</th><td><span id="Batt_Console"> </span></td>
655                                                 <th>TX Battery OK:</th><td><span id="Batt_TX_OK"> </span></td>
656                                         </tr>
657                                         <tr>
658                                                 <th>Pressure:</th><td><span id="Pressure"> </span></td>
659                                                 <th>Trend:</th><td><span id="Pressure_Trend_txt"> </span></td>
660                                         </tr>
661                                         <tr>
662                                                 <th>Temperature in:</th><td> <span id="Temp_In"> </span></td>
663                                                 <th>Humidity:</th><td> <span id="Humidity_In"> </span></td>
664                                         </tr>
665                                         <tr>
666                                                 <th>Min:</th><td> <span id="Temp_Out_Min"> </span> @ <span id="Temp_Out_Min_T"> </span></td>
667                                                 <th>Max:</th><td> <span id="Temp_Out_Max"> </span> @ <span id="Temp_Out_Max_T"> </span></td>
668                                                 <th>Humidity:</th><td> <span id="Humidity_Out"> </span></td>
669                                                 <th>Dew Point:</th><td> <span id="Dew_Point"> </span></td>
670                                         </tr>
671                                         <tr>
672                                                 <th>Wind Dir Minute Avg:</th><td> <span id="Dir_1m">  </span></td>
673                                                 <th>Wind Speed Minute Avg:</th><td> <span id="Wind_1m">  </span></td>
674                                         </tr>
675                                         <tr>
676                                                 <th>Rain 30mins:</th><td> <span id="Rain_1h"> </span></td>
677                                                 <th>Day:</th><td> <span id="Rain_Day"> </span></td>
678                                                 <th>24hrs:</th><td> <span id="Rain_24h"> </span></td>
679                                                 <th>Month:</th><td> <span id="Rain_Month"> </span></td>
680                                                 <th>Year:</th><td> <span id="Rain_Year"> </span></td>
681                                         </tr>
682                                 </table>
683                         </div>
684                 </div>
685
686
687                 <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
688                 <script src="js/jquery.min.js"></script>
689                 <!-- Latest compiled and minified JavaScript -->
690                 <script src="js/bootstrap.min.js"></script>
691                 <!-- High Chart stuff -->
692                 <script src="js/highcharts.js"></script>
693                 <script src="js/highcharts-more.js"></script>
694                 <script src="js/modules/exporting.js"></script>
695
696         </body>
697 </html>