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