mirror of https://github.com/lumapu/ahoy.git
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							192 lines
						
					
					
						
							8.5 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							192 lines
						
					
					
						
							8.5 KiB
						
					
					
				| <!doctype html> | |
| <html> | |
|     <head> | |
|         <title>{#NAV_HISTORY}</title> | |
|         {#HTML_HEADER} | |
|         <meta name="apple-mobile-web-app-capable" content="yes"> | |
|         <meta name="format-detection" content="telephone=no"> | |
| 
 | |
|     </head> | |
| 
 | |
|     <body> | |
|         {#HTML_NAV} | |
|         <div id="wrapper"> | |
|             <div id="content"> | |
|                 <h3>{#TOTAL_POWER}</h3> | |
|                 <div class="chartDiv" id="pwrChart"></div> | |
|                 <h3>{#TOTAL_POWER_DAY}</h3> | |
|                 <div class="chartDiv" id="pwrDayChart"></div> | |
|                 <!--IF_ENABLE_HISTORY_YIELD_PER_DAY--> | |
|                 <h3>{#TOTAL_YIELD_PER_DAY}</h3> | |
|                 <div class="chartDiv" id="ydChart"></div> | |
|                 <!--ENDIF_ENABLE_HISTORY_YIELD_PER_DAY--> | |
|                 <!--IF_ENABLE_HISTORY_LOAD_DATA--> | |
|                 <h4 style="margin-bottom:0px;">Insert data into Yield per day history</h4> | |
|                 <fieldset style="padding: 1px;"> | |
|                     <legend class="des" style="margin-top: 0px;">Insert data (*.json) i.e. from a saved "/api/yieldDayHistory" call | |
|                     </legend> | |
|                     <form id="form" method="POST" action="/api/addYDHist" enctype="multipart/form-data" | |
|                         accept-charset="utf-8"> | |
|                         <input type="button" class="btn my-4" style="padding: 3px;margin: 3px;" value="Insert" onclick="submit()"> | |
|                         <input type="file" name="insert" style="width: 80%;"> | |
|                     </form> | |
|                 </fieldset> | |
|                 <!--ENDIF_ENABLE_HISTORY_LOAD_DATA--> | |
|             </div> | |
|         </div> | |
|         {#HTML_FOOTER} | |
| 
 | |
|         <script type="text/javascript"> | |
|             const height = 250 | |
|             var once = true | |
| 
 | |
|             function calcScale(obj) { | |
|                 let s = {} | |
|                 s.x_mul = 60 | |
|                 s.ts_dur = obj.refresh * obj.value.length | |
|                 s.ts_start = obj.lastValueTs - s.ts_dur | |
|                 while(s.x_mul * 10 <= s.ts_dur) | |
|                     s.x_mul += (s.x_mul == 60) ? 240 : ((s.x_mul < 1800) ? 300 : 1800) | |
| 
 | |
|                 s.y_mul = 10 | |
|                 while(s.y_mul * 10 <= obj.max) | |
|                     s.y_mul += (s.y_mul < 100) ? 10 : 100 | |
|                 s.y_step = Math.ceil(obj.max / s.y_mul) | |
|                 s.y_max = s.y_mul * s.y_step | |
|                 return s | |
|             } | |
| 
 | |
|             function setupSvg(id, obj) { | |
|                 let scale = calcScale(obj) | |
|                 let n = obj.value.length | |
|                 return mlNs("svg", {class: "container", id: id+"_svg", viewBox: "0 0 "+String(n*2+50)+" "+String(height+20), width: "100%", height: "100%"}, [ | |
|                     mlNs("defs", {}, [ | |
|                         mlNs("linearGradient", {id: "gLine", x1: 0, y1: 0, x2: 0, y2: "100%"}, [ | |
|                             mlNs("stop", {offset: 0, "stop-color": "#006ec0"}), | |
|                             mlNs("stop", {offset: "80%", "stop-color": "#5050ff"}), | |
|                             mlNs("stop", {offset: "100%", "stop-color": "gray"}) | |
|                         ]), | |
|                         mlNs("linearGradient", {id: "gFill", x1: 0, y1: 0, x2: 0, y2: "100%"}, [ | |
|                             mlNs("stop", {offset: 0, "stop-color": "#006ec0"}), | |
|                             mlNs("stop", {offset: "50%", "stop-color": "#0034c0"}), | |
|                             mlNs("stop", {offset: "100%", "stop-color": "#e0e0e0"}) | |
|                         ]) | |
|                     ]), | |
|                     ...gridText(n*2, scale), | |
|                     mlNs("g", {transform: "translate(30, 5)"}, [ | |
|                         ...grid(n*2, scale), | |
|                         ...poly(n*2, obj, scale) | |
|                     ]) | |
|                 ]) | |
|             } | |
| 
 | |
|             function gridText(x2, scale) { | |
|                 let g = [] | |
|                 let div = height / scale.y_max | |
|                 for(let i = 0; i <= scale.y_max; i += scale.y_mul) { | |
|                     g.push(mlNs("text", {x: 0, y: height-(i*div)+9}, String(i))) | |
|                 } | |
|                 div = x2 / scale.ts_dur | |
|                 for(let i = 0; i < scale.ts_dur; i++) { | |
|                     if((i + scale.ts_start) % scale.x_mul == 0) { | |
|                         let d = new Date((scale.ts_start + i) * 1000) | |
|                         g.push(mlNs("text", {x: (i*div)+17, y: height+20}, ("0"+d.getHours()).slice(-2) + ":" + ("0"+d.getMinutes()).slice(-2))) | |
|                     } | |
|                 } | |
|                 return g | |
|             } | |
| 
 | |
|             function grid(x2, scale) { | |
|                 let g = [] | |
|                 let div = height / scale.y_max | |
|                 for(let i = 0; i <= scale.y_max; i += scale.y_mul) { | |
|                     g.push(mlNs("line", {x1: 0, x2: x2, y1: height-i*div, y2: height-i*div, "stroke-width": 1, "stroke-dasharray": "1,3", stroke: "#aaa"})) | |
|                 } | |
|                 div = x2 / scale.ts_dur | |
|                 for(let i = 0; i <= scale.ts_dur; i++) { | |
|                     if((i + scale.ts_start) % scale.x_mul == 0) { | |
|                         g.push(mlNs("line", {x1: (i*div), x2: (i*div), y1: 0, y2: height, "stroke-width": 1, "stroke-dasharray": "1,3", stroke: "#aaa"})) | |
|                     } | |
|                 } | |
|                 return g | |
|             } | |
| 
 | |
|             function poly(x2, obj, scale) { | |
|                 let pts = "" | |
|                 let i = 0, first = -1, last = -1, lastVal = 0 | |
|                 let div = scale.y_max / height | |
|                 if(div == 0) | |
|                     div = 1 | |
|                 for (val of obj.value) { | |
|                     if(val > 0) { | |
|                         lastVal = val | |
|                         pts += " " + String(i) + "," + String(height - val / div) | |
|                         if(first < 0) | |
|                             first = i | |
|                         last = i | |
|                     } | |
|                     i += 2 | |
|                 } | |
|                 let pts2 = pts + " " + String(last) + "," + String(height) | |
|                 pts2 += " " + String(first) + "," + String(height) | |
|                 elm = [ | |
|                     mlNs("polyline", {stroke: "url(#gLine)", fill: "none", points: pts}), | |
|                     mlNs("polyline", {stroke: "none", fill: "url(#gFill)", points: pts2}), | |
|                     mlNs("text", {x: i*.8, y: 10}, "{#MAXIMUM}: " + String(obj.max) + "W"), | |
|                     mlNs("text", {x: i*.8, y: 25}, "{#LAST_VALUE}: " + String(lastVal) + "W") | |
|                 ] | |
| 
 | |
|                 if(undefined !== obj.yld) | |
|                     elm.push(mlNs("text", {x: i*.8, y: 40}, "{#YIELD_DAY}: " + String(obj.yld) + "kWh")) | |
| 
 | |
|                 return elm; | |
|             } | |
| 
 | |
| 
 | |
|             function parsePowerHistory(obj){ | |
|                 if(once) { | |
|                     once = false | |
|                     parseNav(obj.generic) | |
|                     parseESP(obj.generic) | |
|                     parseRssi(obj.generic) | |
|                     parseTitle(obj.generic) | |
|                     window.setInterval("getAjax('/api/powerHistory', parsePowerHistory)", obj.refresh * 1000) | |
|                     setTimeout(() => { | |
|                         window.setInterval("getAjax('/api/powerHistoryDay', parsePowerHistoryDay)", obj.refresh * 1000) | |
|                     }, 200) | |
|                     /*IF_ENABLE_HISTORY_YIELD_PER_DAY*/ | |
|                     setTimeout(() => { | |
|                         window.setInterval("getAjax('/api/yieldDayHistory', parseYieldDayHistory)", obj.refresh * 1000) | |
|                     }, 400) | |
|                     /*ENDIF_ENABLE_HISTORY_YIELD_PER_DAY*/ | |
|                 } | |
|                 if (null != obj) { | |
|                     let svg = setupSvg("ph", obj); | |
|                     document.getElementById("pwrChart").replaceChildren(svg); | |
|                     setTimeout(() => { getAjax("/api/powerHistoryDay", parsePowerHistoryDay) }, 50); | |
|                 } | |
|             } | |
| 
 | |
|             function parsePowerHistoryDay(obj) { | |
|                 if (null != obj) { | |
|                     let svg = setupSvg("phDay", obj); | |
|                     document.getElementById("pwrDayChart").replaceChildren(svg); | |
|                     /*IF_ENABLE_HISTORY_YIELD_PER_DAY*/ | |
|                     setTimeout(() => { getAjax("/api/yieldDayHistory", parseYieldDayHistory) }, 50); | |
|                     /*ENDIF_ENABLE_HISTORY_YIELD_PER_DAY*/ | |
|                 } | |
|             } | |
| 
 | |
|             /*IF_ENABLE_HISTORY_YIELD_PER_DAY*/ | |
|             function parseYieldDayHistory(obj) { | |
|                 if (null != obj) { | |
|                     let svg = setupSvg("phDay", obj); | |
|                     document.getElementById("pwrDayChart").replaceChildren(svg); | |
|                 } | |
|             } | |
|             /*ENDIF_ENABLE_HISTORY_YIELD_PER_DAY*/ | |
| 
 | |
|             getAjax("/api/powerHistory", parsePowerHistory); | |
|         </script> | |
|     </body> | |
| </html>
 | |
| 
 |