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.
 
 
 
 
 
 

377 lines
16 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>
{#LAST} <span id="pwrNumValues"></span> {#VALUES}
<div class="chartDivContainer">
<div class="chartDiv" id="pwrChart"> </div>
<p>
{#LAST_VALUE}: <span id="pwrLast"></span> W.<br />
{#MAXIMUM}: <span id="pwrMax"></span> W.
{#UPDATED} <span id="pwrRefresh"></span> {#SECONDS}
</p>
</div>
<h3>{#TOTAL_POWER_DAY}</h3>
<div class="chartDivContainer">
<div class="chartDiv" id="pwrDayChart"> </div>
<p>
{#MAX_DAY}: <span id="pwrDayMaxDay"></span> W. <br />
{#UPDATED} <span id="pwrDayRefresh"></span> {#SECONDS}
</p>
</div>
<!--
<h3>{#TOTAL_YIELD_PER_DAY}</h3>
<div class="chartDivContainer">
<div class="chartDiv" id="ydChart"> </div>
<p>
{#MAXIMUM}: <span id="ydMax"></span> Wh<br />
</p>
</div>
<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>
-->
</div>
</div>
{#HTML_FOOTER}
<script type="text/javascript">
var powerHistObj = null;
var powerHistDayObj = null;
var ydHistObj = null;
Number.prototype.pad = function (size) {
var s = String(this);
while (s.length < (size || 2)) { s = "0" + s; }
return s;
}
class powChart {
static objcnt = 0; // to give each object elemets a unique name prefix
constructor(namePrefix) {
// configurable vars
this.mChartHight = 250;
this.datapoints = 256;
this.xGridDist = 50;
this.yGridDist = 100;
// info vars
this.maxValue = 0;
this.mLastValue = 0;
// intern vars
this.svg = null;
this.refreshIntervall = 30; // seconds
this.lastValueTs = 0; // Timestmp of last value
++this.objcnt;
if (namePrefix === undefined)
this.namePrefix = "powChart" + this.objcnt;
else
this.namePrefix = namePrefix;
}
init(numDatapoints) {
this.datapoints = numDatapoints;
// generate svg
const svgns = "http://www.w3.org/2000/svg";
this.svg = document.createElementNS(svgns, "svg");
this.svg.setAttribute("class", "container");
this.svg.setAttribute("id", this.namePrefix + "_svg");
this.svg.setAttribute("viewBox", "0 0 " + String(this.datapoints * 2 + 50) + " " + String(this.mChartHight + 20));
this.svg.setAttribute("width", "100%");
this.svg.setAttribute("height", "100%");
// Gradient Line
let defLgLine = document.createElementNS(svgns, "defs");
{
let lg = document.createElementNS(svgns, "linearGradient")
lg.setAttribute("id", "verlVertLine");
lg.setAttribute("x1", "0%");
lg.setAttribute("y1", "0%");
lg.setAttribute("x2", "0%");
lg.setAttribute("y2", "100%");
let s1 = document.createElementNS(svgns, "stop")
s1.setAttribute("offset", "0%");
s1.setAttribute("stop-color", "blue");
let s2 = document.createElementNS(svgns, "stop")
s2.setAttribute("offset", "80%");
s2.setAttribute("stop-color", "#5050FF");
let s3 = document.createElementNS(svgns, "stop")
s3.setAttribute("offset", "100%");
s3.setAttribute("stop-color", "gray");
lg.appendChild(s1);
lg.appendChild(s2);
lg.appendChild(s3);
defLgLine.appendChild(lg);
}
this.svg.appendChild(defLgLine);
// Gradient Fill
let defLg = document.createElementNS(svgns, "defs");
{
let lg = document.createElementNS(svgns, "linearGradient")
lg.setAttribute("id", "verlVertFill");
lg.setAttribute("x1", "0%");
lg.setAttribute("y1", "0%");
lg.setAttribute("x2", "0%");
lg.setAttribute("y2", "100%");
let s1 = document.createElementNS(svgns, "stop")
s1.setAttribute("offset", "0%");
s1.setAttribute("stop-color", "#A0A0FF");
let s2 = document.createElementNS(svgns, "stop")
s2.setAttribute("offset", "50%");
s2.setAttribute("stop-color", "#C0C0FF");
let s3 = document.createElementNS(svgns, "stop")
s3.setAttribute("offset", "100%");
s3.setAttribute("stop-color", "#E0E0F0");
lg.appendChild(s1);
lg.appendChild(s2);
lg.appendChild(s3);
defLgLine.appendChild(lg);
}
this.svg.appendChild(defLg);
let chartFrame = document.createElementNS(svgns, "rect");
chartFrame.setAttribute("id", this.namePrefix + "_chartFrame");
chartFrame.setAttribute("class", "chartFrame");
chartFrame.setAttribute("x", "0");
chartFrame.setAttribute("y", "0");
chartFrame.setAttribute("width", String(this.datapoints * 2));
chartFrame.setAttribute("height", String(this.mChartHight));
this.svg.appendChild(chartFrame);
// Group chart content
let chartContent = document.createElementNS(svgns, "g");
chartContent.setAttribute("id", this.namePrefix + "_svgChartContent");
chartFrame.setAttribute("transform", "translate(29, 5)");
chartContent.setAttribute("transform", "translate(30, 5)");
// Graph values in a polyline
let poly = document.createElementNS(svgns, "polyline");
poly.setAttribute("id", this.namePrefix + "Poly");
poly.setAttribute("stroke", "url(#verlVertLine)");
poly.setAttribute("fill", "none");
chartContent.appendChild(poly);
// hidden polyline for fill
let polyFill = document.createElementNS(svgns, "polyline");
polyFill.setAttribute("id", this.namePrefix + "PolyFill");
polyFill.setAttribute("stroke", "none");
polyFill.setAttribute("fill", "url(#verlVertFill)");
chartContent.appendChild(polyFill);
// X-grid lines
let numXGridLines = (this.mChartHight / this.xGridDist);
for (let i = 0; i < numXGridLines; i++) {
let line = document.createElementNS(svgns, "line");
line.setAttribute("id", this.namePrefix + "XGrid" + i);
line.setAttribute("x1", String(0));
line.setAttribute("x2", String(this.datapoints * 2));
line.setAttribute("y1", String(this.mChartHight - (i + 1) * this.xGridDist));
line.setAttribute("y2", String(this.mChartHight - (i + 1) * this.xGridDist));
line.setAttribute("stroke-width", "1");
line.setAttribute("stroke-dasharray", "1,1");
line.setAttribute("stroke", "#A0A0A0");
chartContent.appendChild(line);
let text = document.createElementNS(svgns, "text");
text.setAttribute("id", this.namePrefix + "XGridText" + i);
text.setAttribute("x", "0");
text.setAttribute("y", String(this.mChartHight + 10 - (i + 1) * this.xGridDist));
text.innerHTML = (i + 1) * this.xGridDist;
this.svg.appendChild(text);
}
// Y-grid lines
let numYGridLines = (this.datapoints / this.yGridDist) * 2;
for (let i = numYGridLines; i > 0; i--) {
let line = document.createElementNS(svgns, "line");
line.setAttribute("id", this.namePrefix + "YGrid" + i);
line.setAttribute("x1", String((i) * this.yGridDist) - 1);
line.setAttribute("x2", String((i) * this.yGridDist) - 1);
line.setAttribute("y1", String(0));
line.setAttribute("y2", String(this.mChartHight));
line.setAttribute("stroke-width", "1");
line.setAttribute("stroke-dasharray", "1,3");
line.setAttribute("stroke", "#A0A0A0");
chartContent.appendChild(line);
let text = document.createElementNS(svgns, "text");
text.setAttribute("id", this.namePrefix + "YGridText" + i);
text.setAttribute("x", String((i) * this.yGridDist + 15));
text.setAttribute("y", String(this.mChartHight + 17));
text.innerHTML = "";
this.svg.appendChild(text);
}
//
this.svg.appendChild(chartContent);
};
getContainer() { return this.svg; };
setXScale(refreshIntervall, lastValueTs) {
this.refreshIntervall = refreshIntervall;
this.lastValueTs = lastValueTs;
}
update(values, maxVal) {
if (maxVal === undefined) {
this.maxValue = 0;
for (let val in values)
if (val > this.maxValue) this.maxValue = val;
}
else
this.maxValue = maxVal;
// normalize data to chart
let divider = this.maxValue / this.mChartHight;
if (divider == 0)
divider = 1;
let firstValPos = -1; // position of first value >0 W
let lastValPos = -1; // position of last value >0 W
let points = "";
for (let i = 0; i < this.datapoints; i++) {
let val = values[i];
if (val > 0) {
this.mLastValue = val;
lastValPos = i;
if (firstValPos < 0)
firstValPos = i;
val = val / divider;
points += ' ' + String(i * 2) + ',' + String(this.mChartHight - val);
}
}
let poly = document.getElementById(this.namePrefix + "Poly");
poly.setAttribute("points", points);
// "close" polyFill-line down to the x-axis
points += ' ' + +String(lastValPos * 2) + ',' + String(this.mChartHight);
points += ' ' + +String(firstValPos * 2) + ',' + String(this.mChartHight);
let polyFill = document.getElementById(this.namePrefix + "PolyFill");
polyFill.setAttribute("points", points);
// X-Grid lines
let numXGridLines = (this.mChartHight / this.xGridDist);
let dist = (this.maxValue / numXGridLines);
for (let i = 0; i < numXGridLines; i++) {
let tex = document.getElementById(this.namePrefix + "XGridText" + i);
tex.innerHTML = ((i + 1) * dist).toFixed(0);
}
// Y-Grid lines
if (isNaN(this.lastValueTs) || this.lastValueTs == 0)
this.lastValueTs = Date.now();
let date = new Date(this.lastValueTs);
let numYGridLines = (this.datapoints / this.yGridDist) * 2;
for (let i = numYGridLines; i > 0; i--) {
let tex = document.getElementById(this.namePrefix + "YGridText" + i);
if (this.refreshIntervall > 8600) // Display date
tex.innerHTML = date.getDate() + "." + (date.getMonth() + 1).pad(2);
else // Display time
tex.innerHTML = date.getHours() + ":" + date.getMinutes().pad(2);
date = new Date(date.getTime() - (this.refreshIntervall * (this.yGridDist / 2) * 1000));
}
};
}// class powChart
function parsePowerHistory(obj){
if (null != obj) {
let refresh = obj.refresh
let maximum = obj.max;
let addNextChart=false;
if (powerHistObj == null) {
powerHistObj = new powChart("ph");
powerHistObj.init(obj.value.length);
document.getElementById("pwrChart").appendChild(powerHistObj.getContainer());
// Regular update:
window.setInterval("getAjax('/api/powerHistory', parsePowerHistory)", refresh * 1000);
// one after the other
addNextChart=true;
}
powerHistObj.setXScale(refresh, obj.lastValueTs * 1000);
powerHistObj.update(obj.value, maximum);
document.getElementById("pwrLast").innerHTML = powerHistObj.mLastValue;
//document.getElementById("pwrMaxDay").innerHTML = obj.maxDay;
document.getElementById("pwrMax").innerHTML = maximum;
document.getElementById("pwrRefresh").innerHTML = refresh;
document.getElementById("pwrNumValues").innerHTML = obj.value.length;
if (addNextChart)
setTimeout(() => { getAjax("/api/powerHistoryDay", parsePowerHistoryDay); }, 50);
}
}
function parsePowerHistoryDay(obj) {
if (null != obj) {
let refresh = obj.refresh
if (refresh<30)
refresh = 30;
let maximum = obj.max;
let addNextChart = false;
if (powerHistDayObj == null) {
powerHistDayObj = new powChart("phDay");
powerHistDayObj.init(obj.value.length);
document.getElementById("pwrDayChart").appendChild(powerHistDayObj.getContainer());
// Regular update:
window.setInterval("getAjax('/api/powerHistoryDay', parsePowerHistoryDay)", refresh * 1000);
// one after the other
addNextChart = false; // if true: add YieldDayHistory
}
powerHistDayObj.setXScale(refresh, obj.lastValueTs * 1000);
powerHistDayObj.update(obj.value, maximum);
//document.getElementById("pwrDayLast").innerHTML = powerHistDayObj.mLastValue;
document.getElementById("pwrDayMaxDay").innerHTML = obj.maxDay;
//document.getElementById("pwrDayMax").innerHTML = maximum;
document.getElementById("pwrDayRefresh").innerHTML = refresh;
if (addNextChart)
setTimeout(() => { getAjax("/api/yieldDayHistory", parseYieldDayHistory); }, 50);
else
parseNav(obj.generic);
}
}
function parseYieldDayHistory(obj) {
if (null != obj) {
parseNav(obj.generic);
let refresh = obj.refresh
let maximum = obj.max;
let addNextChart = false;
if (ydHistObj == null) {
ydHistObj = new powChart("yd");
ydHistObj.init(obj.value.length);
document.getElementById("ydChart").appendChild(ydHistObj.getContainer());
// Regular update:
window.setInterval("getAjax('/api/yieldDayHistory', parseYieldDayHistory)", refresh * 500);
addNextChart = true;
}
ydHistObj.setXScale(refresh, obj.lastValueTs * 1000);
ydHistObj.update(obj.value, maximum);
document.getElementById("ydMax").innerHTML = maximum;
}
}
getAjax("/api/powerHistory", parsePowerHistory);
</script>
</body>
</html>