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.
338 lines
15 KiB
338 lines
15 KiB
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<title>Live</title>
|
|
{#HTML_HEADER}
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
</head>
|
|
<body>
|
|
<!-- The following lines are commented out as there is no permission to redistribute this
|
|
charting lib reference functional with the CC BY-NC-SA 4.0 license of the AHOY DTU.
|
|
This charting lib has a proprietary and commercial license model. See their web site (shop) for details.
|
|
Also see the their blog: https://www.highcharts.com/blog/download for more details.
|
|
Therefore these lines are prepared for private testing only. See how easy to use this library is - technically speaking.
|
|
Choose another charting lib with a matching open source license if you want to redistribute the charting function with this project. -->
|
|
<!--
|
|
<script src="https://code.highcharts.com/highcharts.js"></script>
|
|
<script src="https://code.highcharts.com/modules/data.js"></script>
|
|
-->
|
|
|
|
{#HTML_NAV}
|
|
<div id="wrapper">
|
|
<div id="content">
|
|
<div id="live"></div>
|
|
<div id="powerchart">Please find a charting library with a suitable license model.</div>
|
|
<p>Every <span id="refresh"></span> seconds the values are updated</p>
|
|
</div>
|
|
</div>
|
|
<pre id="dyn_csv_url" style="display:none">empty</pre>
|
|
<pre id="csv" style="display:none">empty</pre>
|
|
<pre id="chart_title" style="display:none">empty</pre>
|
|
<pre id="yaxis_grid_power_title" style="display:none">empty</pre>
|
|
|
|
{#HTML_FOOTER}
|
|
<script type="text/javascript">
|
|
var exeOnce = true;
|
|
var units, ivEn;
|
|
var mIvHtml = [];
|
|
var mNum = 0;
|
|
var names = ["Voltage", "Current", "Power", "Yield Day", "Yield Total", "Irradiation"];
|
|
var total = Array(5).fill(0);
|
|
var mychart;
|
|
|
|
function parseGeneric(obj) {
|
|
if(true == exeOnce){
|
|
parseNav(obj);
|
|
parseESP(obj);
|
|
}
|
|
parseRssi(obj);
|
|
}
|
|
|
|
function numBig(val, unit, des) {
|
|
return ml("div", {class: "col-6 col-sm-4 col-md-3 a-c"}, [
|
|
ml("div", {class: "row"},
|
|
ml("div", {class: "col"}, [
|
|
ml("span", {class: "fs-5 fs-md-4"}, String(Math.round(val * 100) / 100)),
|
|
ml("span", {class: "fs-6 fs-md-7 mx-1"}, unit)
|
|
])),
|
|
ml("div", {class: "row"},
|
|
ml("div", {class: "col"},
|
|
ml("span", {class: "fs-9 px-1"}, des)
|
|
)
|
|
)
|
|
]);
|
|
}
|
|
|
|
function numMid(val, unit, des) {
|
|
return ml("div", {class: "col-6 col-sm-4 col-md-3 mb-2"}, [
|
|
ml("div", {class: "row"},
|
|
ml("div", {class: "col"}, [
|
|
ml("span", {class: "fs-6"}, String(Math.round(val * 100) / 100)),
|
|
ml("span", {class: "fs-8 mx-1"}, unit)
|
|
])),
|
|
ml("div", {class: "row"},
|
|
ml("div", {class: "col"},
|
|
ml("span", {class: "fs-9"}, des)
|
|
)
|
|
)
|
|
]);
|
|
}
|
|
|
|
function totals() {
|
|
for(var i = 0; i < 5; i++) {
|
|
total[i] = Math.round(total[i] * 100) / 100;
|
|
}
|
|
|
|
return ml("div", {class: "row mt-3 mb-5"},
|
|
ml("div", {class: "col"}, [
|
|
ml("div", {class: "p-2 total-h"},
|
|
ml("div", {class: "row"},
|
|
ml("div", {class: "col mx-2 mx-md-1"}, "TOTAL")
|
|
),
|
|
),
|
|
ml("div", {class: "p-2 total-bg"}, [
|
|
ml("div", {class: "row"}, [
|
|
numBig(total[0], "W", "AC Power"),
|
|
numBig(total[1], "Wh", "Yield Day"),
|
|
numBig(total[2], "kWh", "Yield Total")
|
|
]),
|
|
ml("div", {class: "hr"}),
|
|
ml("div", {class: "row"}, [
|
|
numMid(total[3], "W", "DC Power"),
|
|
numMid(total[4], "var", "Reactive Power")
|
|
])
|
|
])
|
|
])
|
|
);
|
|
}
|
|
function ivHead(obj) {
|
|
total[0] += obj.ch[0][2]; // P_AC
|
|
total[1] += obj.ch[0][7]; // YieldDay
|
|
total[2] += obj.ch[0][6]; // YieldTotal
|
|
total[3] += obj.ch[0][8]; // P_DC
|
|
total[4] += obj.ch[0][10]; // Q_AC
|
|
var t = span(" ° C");
|
|
return ml("div", {class: "row mt-2"},
|
|
ml("div", {class: "col"}, [
|
|
ml("div", {class: "p-2 iv-h"},
|
|
ml("div", {class: "row"}, [
|
|
ml("div", {class: "col mx-2 mx-md-1"}, obj.name),
|
|
ml("div", {class: "col a-c"}, "Power limit " + ((obj.power_limit_read == 65535) ? "n/a" : (obj.power_limit_read + " %"))),
|
|
ml("div", {class: "col a-r mx-2 mx-md-1"}, String(obj.ch[0][5]) + t.innerHTML)
|
|
])
|
|
),
|
|
ml("div", {class: "p-2 iv-bg"}, [
|
|
ml("div", {class: "row"},[
|
|
numBig(obj.ch[0][2], "W", "AC Power"),
|
|
numBig(obj.ch[0][11], "W", "Max AC Power"),
|
|
numBig(obj.ch[0][7], "Wh", "Yield Day"),
|
|
numBig(obj.ch[0][6], "kWh", "Yield Total")
|
|
]),
|
|
ml("div", {class: "hr"}),
|
|
(obj["grid_power"] === undefined) ?
|
|
ml("div", {class: "row mt-2"},[
|
|
numMid(obj.ch[0][8], "W", "DC Power"),
|
|
numMid(obj.ch[0][0], "V", "Voltage"),
|
|
numMid(obj.ch[0][1], "A", "Current"),
|
|
numMid(obj.ch[0][3], "Hz", "Frequency"),
|
|
numMid(obj.ch[0][9], "%", "Efficiency"),
|
|
numMid(obj.ch[0][10], "var", "Reactive Power"),
|
|
numMid(obj.ch[0][4], "", "Power Factor")
|
|
]) :
|
|
ml("div", {class: "row mt-2"},[
|
|
numMid(obj.ch[0][8], "W", "DC Power"),
|
|
numMid(obj.grid_power, "W", "Grid Power"),
|
|
numMid(obj.ch[0][0], "V", "Voltage"),
|
|
numMid(obj.ch[0][1], "A", "Current"),
|
|
numMid(obj.ch[0][3], "Hz", "Frequency"),
|
|
numMid(obj.ch[0][9], "%", "Efficiency"),
|
|
numMid(obj.ch[0][10], "var", "Reactive Power"),
|
|
numMid(obj.ch[0][4], "", "Power Factor")
|
|
])
|
|
])
|
|
])
|
|
);
|
|
}
|
|
|
|
function numCh(val, unit, des) {
|
|
return ml("div", {class: "col-12 col-sm-6 col-md-12 mb-2"}, [
|
|
ml("div", {class: "row"},
|
|
ml("div", {class: "col"}, [
|
|
ml("span", {class: "fs-6 fs-md-7"}, String(Math.round(val * 100) / 100)),
|
|
ml("span", {class: "fs-8 mx-2"}, unit)
|
|
])),
|
|
ml("div", {class: "row"},
|
|
ml("div", {class: "col"},
|
|
ml("span", {class: "fs-9"}, des)
|
|
)
|
|
)
|
|
]);
|
|
}
|
|
|
|
function ch(name, vals) {
|
|
return ml("div", {class: "col-6 col-md-3 mt-2"}, [
|
|
ml("div", {class: "ch-h p-2 a-c"}, name),
|
|
ml("div", {class: "p-2 ch-bg"}, [
|
|
ml("div", {class: "row"}, [
|
|
numCh(vals[2], units[2], "Power"),
|
|
numCh(vals[6], units[2], "Max Power"),
|
|
numCh(vals[5], units[5], "Irradiation"),
|
|
numCh(vals[3], units[3], "Yield Day"),
|
|
numCh(vals[4], units[4], "Yield Total"),
|
|
numCh(vals[0], units[0], "Voltage"),
|
|
numCh(vals[1], units[1], "Current")
|
|
])
|
|
])
|
|
]);
|
|
}
|
|
|
|
function tsInfo(ts) {
|
|
var ageInfo = "Last received data requested at: ";
|
|
if(ts > 0) {
|
|
var date = new Date(ts * 1000);
|
|
ageInfo += date.toLocaleString('de-DE');
|
|
}
|
|
else
|
|
ageInfo += "nothing received";
|
|
|
|
return ml("div", {class: "mb-5"}, [
|
|
ml("div", {class: "row p-1 ts-h mx-2"},
|
|
ml("div", {class: "col"}, "")
|
|
),
|
|
ml("div", {class: "row p-2 ts-bg mx-2"},
|
|
ml("div", {class: "col mx-2"}, ageInfo)
|
|
)
|
|
]);
|
|
}
|
|
|
|
function parseIv(obj) {
|
|
mNum++;
|
|
|
|
var chn = [];
|
|
for(var i = 1; i < obj.ch.length; i++) {
|
|
var name = obj.ch_name[i];
|
|
if(name.length == 0)
|
|
name = "CHANNEL " + i;
|
|
if(obj.ch_max_pwr[i] > 0) // show channel only if max mod pwr
|
|
chn.push(ch(name, obj.ch[i]));
|
|
}
|
|
mIvHtml.push(
|
|
ml("div", {}, [
|
|
ivHead(obj),
|
|
ml("div", {class: "row mb-2"}, chn),
|
|
tsInfo(obj.ts_last_success)
|
|
])
|
|
);
|
|
|
|
var last = true;
|
|
for(var i = obj.id + 1; i < ivEn.length; i++) {
|
|
if((i != ivEn.length) && ivEn[i]) {
|
|
last = false;
|
|
getAjax("/api/inverter/id/" + i, parseIv);
|
|
break;
|
|
}
|
|
}
|
|
if(last) {
|
|
if(mNum > 1)
|
|
mIvHtml.unshift(totals());
|
|
document.getElementById("live").replaceChildren(...mIvHtml);
|
|
}
|
|
}
|
|
|
|
function parseCSV(data) {
|
|
document.getElementById("csv").innerHTML = data;
|
|
|
|
// The following code line may not be redistributed functional with this project.
|
|
// Also see the comment at the top area of this file about the commercial license model of this charting lib.
|
|
// mychart.update({data: {csv: document.getElementById("csv").innerHTML}});
|
|
}
|
|
|
|
function parse(obj) {
|
|
if(null != obj) {
|
|
parseGeneric(obj["generic"]);
|
|
units = Object.assign({}, obj["fld_units"]);
|
|
ivEn = Object.values(Object.assign({}, obj["iv"]));
|
|
mIvHtml = [];
|
|
mNum = 0;
|
|
total.fill(0);
|
|
for(var i = 0; i < obj.iv.length; i++) {
|
|
if(obj.iv[i]) {
|
|
getAjax("/api/inverter/id/" + i, parseIv);
|
|
break;
|
|
}
|
|
}
|
|
if(true == exeOnce) {
|
|
var r = document.querySelector(':root');
|
|
var rs = getComputedStyle(r);
|
|
|
|
document.getElementById("dyn_csv_url").innerHTML = document.baseURI.split ("\/live")[0] + "/get_chartdata/chartdata.csv";
|
|
document.getElementById("refresh").innerHTML = obj["refresh"];
|
|
if (obj["grid_power"] === undefined) {
|
|
document.getElementById("chart_title").innerHTML = "Solar Power during Daylight";
|
|
document.getElementById("yaxis_grid_power_title").innerHTML = "";
|
|
} else {
|
|
document.getElementById("chart_title").innerHTML = "Solar and Grid Power during Daylight";
|
|
document.getElementById("yaxis_grid_power_title").innerHTML = "Grid Power in W";
|
|
}
|
|
window.setInterval("getAjax('/api/live', parse)", obj["refresh"] * 1000);
|
|
exeOnce = false;
|
|
|
|
// The following object may not be redistributed functional with this project.
|
|
// Also see the comment at the top area of this file about the commercial license model of this charting lib.
|
|
/*
|
|
mychart = Highcharts.chart('powerchart', {
|
|
accessibility: {
|
|
enabled: false
|
|
},
|
|
|
|
data: {
|
|
csv: document.getElementById('csv').innerHTML,
|
|
enablePolling: false,
|
|
dataRefreshRate: 30
|
|
},
|
|
|
|
series: [{
|
|
yAxis: 0,
|
|
type: 'column',
|
|
}, {
|
|
yAxis: 1,
|
|
type: 'areaspline',
|
|
fillOpacity: 0.3
|
|
}],
|
|
|
|
yAxis: [{
|
|
title: {
|
|
text: 'AC Power in W'
|
|
}},
|
|
{
|
|
title: {
|
|
text: document.getElementById('yaxis_grid_power_title').innerHTML
|
|
},
|
|
opposite: true
|
|
}
|
|
],
|
|
|
|
title: {
|
|
text: document.getElementById('chart_title').innerHTML
|
|
},
|
|
|
|
subtitle: {
|
|
text: 'Values averaged every 10 minutes'
|
|
},
|
|
|
|
legend: {
|
|
enabled: false
|
|
},
|
|
colors: [rs.getPropertyValue('--iv-head-bg'), '#ffa500']
|
|
});
|
|
*/
|
|
}
|
|
} else {
|
|
document.getElementById("refresh").innerHTML = "n/a";
|
|
}
|
|
getCSV(document.getElementById("dyn_csv_url").innerHTML, parseCSV)
|
|
}
|
|
getAjax("/api/live", parse);
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|