Smart-Dashboard/js/solar/solarMQTT.js
2026-02-14 20:08:34 +01:00

861 lines
38 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const solarMQTT = {
getMQTT: function () {
const id = Math.random().toString(36).substring(7);
const topic = "#";
const connection = "wss://mqtt.nas.el-wa.org:443"
mqttsolarTreeDone = false;
// const connection = "ws://username:password@37.97.203.138:8083" // Works
// const connection = "wss://public:public@public.cloud.shiftr.io" // Works
const client = mqtt.connect(connection, {
rejectUnauthorized: false,
});
client.on("message", messageReceived);
client.on("connect", function () {
client.subscribe("solarManager/#");
client.subscribe("wattpilot/properties/lmo/state");
client.subscribe("wattpilot/properties/ftt/state");
client.subscribe("wattpilot/properties/fte/state");
client.subscribe("wattpilot/properties/amp/state");
client.subscribe("wattpilot/properties/car/state");
client.subscribe("go-eCharger/270003/amp");
client.subscribe("go-eCharger/270003/ate");
client.subscribe("go-eCharger/270003/lmo");
client.subscribe("go-eCharger/270003/att");
client.subscribe("go-eCharger/270003/car");
client.subscribe("weatherStation/#");
});
client.on("error", function (error) {
//alert("MQTT Error: " + error);
});
client.on('end', function () {
setTimeout(getMQTT, 5000);
alert("MQTT Disconnected, try to reconnect in 5 secs.");
})
function getNestedProp(obj, path) {
return path.split('/').reduce((acc, key) => acc && acc[key], obj);
}
function setNestedProp(obj, path, value) {
var schema = obj; // a moving reference to internal objects within obj
var pList = path.split('/');
var len = pList.length;
for (var i = 0; i < len - 1; i++) {
var elem = pList[i];
if (!schema[elem]) schema[elem] = {}
schema = schema[elem];
}
schema[pList[len - 1]] = value;
}
function messageReceived(topic, message) {
mqttData[topic] = message;
if (topic == "solarManager/P_Load") {
setTimeout(function () { solarSVG.updateValuesMQTT(mqttData) }, 200); //give the object tree some time to build up and receive all values
}else if(topic == "weatherStation/windDeg"){
setTimeout(function () { updateValuesWeather() }, 200); //give the object tree some time to build up and receive all values
}
}
}
}
const solarSVG = {
updateCnt: 99,
fillElementArray: function () {
},
updateValuesMQTT: function (mqttData) {
const angleFactor = 15000 / 288;
const sixkWangleFactor = 6000 / 288;
var cons = Number(mqttData["solarManager/P_Load"]);
var pvn = JSON.parse(mqttData["solarManager/P_PVn"]);
var pv = Number(mqttData["solarManager/P_PV"]);
var pv2 = Number(pvn[1]);
var pv1 = Number(pvn[0]);
var pv3 = pv - (pv1 + pv2);
var pbatt = Number(mqttData["solarManager/P_Akku"]);
var limbatt = Number(mqttData["solarManager/crgMaxPct"]);
var grid = Number(mqttData["solarManager/P_Grid"]);
var soc = Number(mqttData["solarManager/SOC"]);
var og = Number(mqttData["solarManager/og"]);
var eg = Number(mqttData["solarManager/eg"]);
var ug = Number(mqttData["solarManager/ug"]);
var evsoc = Number(mqttData["solarManager/evSOC"]);
var evlock = Number(mqttData["solarManager/evLock"]);
var evMode = mqttData["solarManager/evMode"];
var evPower = Number(mqttData["solarManager/evPower"]);
var plugev = Number(mqttData["solarManager/evPlug"]);
var fuelev = Number(mqttData["solarManager/evFuel"]);
var heatOG = Number(mqttData["solarManager/heatOG"]);
var heatEG = Number(mqttData["solarManager/heatEG"]);
var puffO = Number(mqttData["solarManager/t_buffT"]);
var puffM = Number(mqttData["solarManager/t_buffM"]);
var puffU = Number(mqttData["solarManager/t_buffB"]);
var heatMode = mqttData["solarManager/heatMode"];
var carRemChrg = Number(mqttData["solarManager/carRemChrg"]);
var aut = Number(mqttData["solarManager/autarky"]);
var Pheat = Number(mqttData["solarManager/pHeat"]);
var waterHeight = Number(mqttData["solarManager/waterHeight"]);
var waterTemp = Number(mqttData["solarManager/waterTemp"]);
var p_wr = Number(mqttData["solarManager/P_WR"]);
var eff = Number(mqttData["solarManager/eff"]);
var i_l1evu = Number(mqttData["solarManager/i_l1evu"]);
var i_l2evu = Number(mqttData["solarManager/i_l2evu"]);
var i_l3evu = Number(mqttData["solarManager/i_l3evu"]);
var evPowerOG = Number(mqttData["solarManager/evPowerOG"]);
var evPlugOG = Number(mqttData["solarManager/evPlugOG"]);
var evModeOG = mqttData["solarManager/evModeOG"];
var common = -cons - ug - eg + og ;
if(common < 0){
common = 0;
}
var htmlNode = document
htmlNode.getElementById('consumerArc').setAttribute("d", describeArc(100, 100, 95, 0, Math.round(-cons / angleFactor)));
htmlNode.getElementById("ogArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(-og / angleFactor)));
htmlNode.getElementById("consumerText").innerHTML = powerToString(-cons);
htmlNode.getElementById("consumerTextAllg").innerHTML = "Gemein: "+powerToString(common);
if (evPower > 0) {
htmlNode.getElementById("evCharge").style.display = "";
if (carRemChrg > -1) {
var today = new Date();
today.setMinutes(today.getMinutes() + carRemChrg);
var h = today.getHours();
var m = today.getMinutes();
if (h < 10)
h = "0" + h;
if (m < 10)
m = "0" + m;
htmlNode.getElementById("evRemText").innerHTML = h + ":" + m
}
} else {
htmlNode.getElementById("evRemText").innerHTML = "";
}
htmlNode.getElementById("ogText").innerHTML = powerToString(-og);
htmlNode.getElementById("egText").innerHTML = powerToString(eg);
htmlNode.getElementById("ugText").innerHTML = powerToString(ug);
htmlNode.getElementById("pvText").innerHTML = powerToString(pv);
htmlNode.getElementById("pv1txt").innerHTML = powerToString(pv1);
htmlNode.getElementById("pv2txt").innerHTML = powerToString(pv2);
htmlNode.getElementById("pv3txt").innerHTML = powerToString(pv3);
htmlNode.getElementById("il1txt").innerHTML = Math.round(i_l1evu * 10) / 10 + "A"
htmlNode.getElementById("il2txt").innerHTML = Math.round(i_l2evu * 10) / 10 + "A"
htmlNode.getElementById("il3txt").innerHTML = Math.round(i_l3evu * 10) / 10 + "A"
htmlNode.getElementById("batText").innerHTML = powerToString(pbatt);
htmlNode.getElementById("heatText").innerHTML = powerToString(Pheat);
htmlNode.getElementById("evText").innerHTML = powerToString(evPower * 1000);
htmlNode.getElementById("evTextOG").innerHTML = powerToString(evPowerOG * 1000);
htmlNode.getElementById("genText").innerHTML = "Autarkie: " + Math.round(aut) + "%";
htmlNode.getElementById("genInfoText").innerHTML = "Wirkungsgrad: " + Math.round(eff) + "%";// powerToString(p_wr);
htmlNode.getElementById("gridText").innerHTML = powerToString(grid);
htmlNode.getElementById("waterText").innerHTML = Math.round(waterHeight) / 10 + "cm"
htmlNode.getElementById("waterTemp").innerHTML = (waterTemp).toPrecision(3) + "°C"
htmlNode.getElementById("waterState").setAttribute("y", (100 - (waterHeight / 1500) * 100) + "%");
for (i = 0; i < pvn.length; i++) {
htmlNode.getElementById("det_pv" + i + "P").innerHTML = powerToString(pvn[i]);
}
tttext = ""
var i = 0;
while (mqttData["solarManager/inverters" + i]) {
if (mqttData["solarManager/inverters" + i+"/error"] > 0) {
tttext = tttext + '<tspan x="0" dy="1.2em">' + mqttData["solarManager/inverters" + i+"/name"] + ":</tspan>"
tttext = tttext + '<tspan x="160">' + "--" + "°C</tspan>"
tttext = tttext + '<tspan x="215">' + "--W" + "</tspan>"
} else {
tttext = tttext + '<tspan x="0" dy="1.2em">' + mqttData["solarManager/inverters" + i+"/name"] + ":</tspan>"
tttext = tttext + '<tspan x="160">' + Math.round(mqttData["solarManager/inverters" + i+"/temp"]) + "°C</tspan>"
tttext = tttext + '<tspan x="215">' + powerToString(mqttData["solarManager/inverters" + i+"/p_AC"]) + "</tspan>"
}
i++;
}
htmlNode.getElementById("invList").innerHTML = tttext
htmlNode.getElementById("egArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(eg / angleFactor)));
htmlNode.getElementById("ugArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(ug / angleFactor)));
htmlNode.getElementById("pvArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(pv1 / angleFactor)));
htmlNode.getElementById("pv2Arc").setAttribute("d", describeArc(100, 100, 95, Math.round(pv1 / angleFactor), Math.round(pv1 / angleFactor) + Math.round(pv2 / angleFactor)));
htmlNode.getElementById("pv3Arc").setAttribute("d", describeArc(100, 100, 95, Math.round(pv1 / angleFactor) + Math.round(pv2 / angleFactor), Math.round(pv1 / angleFactor) + Math.round(pv2 / angleFactor) + Math.round(pv3 / angleFactor)));
if (pbatt < 0) {
if (limbatt < 100) {
htmlNode.getElementById("charge").style.display = "none";
htmlNode.getElementById("batLim").style.display = "";
htmlNode.getElementById("batLimText").innerHTML = Math.round(limbatt) + "%";
} else {
htmlNode.getElementById("charge").style.display = "";
htmlNode.getElementById("batLim").style.display = "none";
}
htmlNode.getElementById("batArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(-pbatt / angleFactor)));
htmlNode.getElementById("battani").setAttribute("class", "stream-rev");
htmlNode.getElementById("battani").setAttribute("stroke-width", 55 * (1 - Math.exp(pbatt / 2000)));
} else {
htmlNode.getElementById("charge").style.display = "none";
htmlNode.getElementById("batLim").style.display = "none";
htmlNode.getElementById("batArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(pbatt / angleFactor)));
htmlNode.getElementById("battani").setAttribute("class", "stream");
htmlNode.getElementById("battani").setAttribute("stroke-width", 55 * (1 - Math.exp(-pbatt / 2000)));
}
htmlNode.getElementById("batChargeState").setAttribute("y", (100 - soc) + "%");
//htmlNode.getElementById("heatChargeState").setAttribute("y", 100 - ((((puffO + puffM) / 2) - 30) * 1.66) + "%");
htmlNode.getElementById('tmpH').setAttribute("stop-color", assignColor("#2389BA", "#BA3B23", 20, 80, puffO));
htmlNode.getElementById('tmpM').setAttribute("stop-color", assignColor("#2389BA", "#BA3B23", 20, 80, puffM));
htmlNode.getElementById('tmpL').setAttribute("stop-color", assignColor("#2389BA", "#BA3B23", 20, 80, puffU));
htmlNode.getElementById("batSOC").innerHTML = soc + "%";
htmlNode.getElementById("evArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(evPower * 2000 / angleFactor)));
htmlNode.getElementById("evChargeState").setAttribute("y", (100 - evsoc) + "%");
htmlNode.getElementById("evSOC").innerHTML = evsoc + "%";
htmlNode.getElementById("evFuel").innerHTML = fuelev + "%";
htmlNode.getElementById("heatArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(Pheat / sixkWangleFactor)));
htmlNode.getElementById("heatUp").innerHTML = Math.round(puffO * 10) / 10 + "°C";
htmlNode.getElementById("heatDown").innerHTML = Math.round(puffM * 10) / 10 + "°C";
if (evlock == false) {
htmlNode.getElementById("evLock").style.display = "none";
} else {
htmlNode.getElementById("evLock").style.display = "";
}
if (heatMode == "eco") {
htmlNode.getElementById("heatEco").style.display = "";
htmlNode.getElementById("heatDefault").style.display = "none";
} else {
htmlNode.getElementById("heatEco").style.display = "none";
htmlNode.getElementById("heatDefault").style.display = "";
}
if (evMode == "Eco") {
htmlNode.getElementById("evEco").style.display = "";
htmlNode.getElementById("evNextTrip").style.display = "none";
htmlNode.getElementById("evDefault").style.display = "none";
} else if (evMode == "Next Trip") {
htmlNode.getElementById("evEco").style.display = "none";
htmlNode.getElementById("evNextTrip").style.display = "";
htmlNode.getElementById("evDefault").style.display = "none";
} else {
htmlNode.getElementById("evEco").style.display = "none";
htmlNode.getElementById("evNextTrip").style.display = "none";
htmlNode.getElementById("evDefault").style.display = "";
}
if (heatOG) {
htmlNode.getElementById("heatOG").style.display = "";
} else {
htmlNode.getElementById("heatOG").style.display = "none";
}
if (heatEG) {
htmlNode.getElementById("heatEG").style.display = "";
} else {
htmlNode.getElementById("heatEG").style.display = "none";
}
if (plugev != "no car") {
htmlNode.getElementById("evPlug").style.display = "";
} else {
htmlNode.getElementById("evPlug").style.display = "none";
}
if (evModeOG == "Eco") {
htmlNode.getElementById("evEcoOG").style.display = "";
htmlNode.getElementById("evNextTripOG").style.display = "none";
htmlNode.getElementById("evDefaultOG").style.display = "none";
} else if (evModeOG == "Next Trip") {
htmlNode.getElementById("evEcoOG").style.display = "none";
htmlNode.getElementById("evNextTripOG").style.display = "";
htmlNode.getElementById("evDefaultOG").style.display = "none";
} else {
htmlNode.getElementById("evEcoOG").style.display = "none";
htmlNode.getElementById("evNextTripOG").style.display = "none";
htmlNode.getElementById("evDefaultOG").style.display = "";
}
if (evPlugOG > 0) {
htmlNode.getElementById("evPlugOG").style.display = "";
} else {
htmlNode.getElementById("evPlugOG").style.display = "none";
}
if (grid < 0) {
htmlNode.getElementById("gridArc").setAttribute("d", describeArc(100, 100, 95, 0, -grid / angleFactor));
htmlNode.getElementById("consGridani").setAttribute("class", "stream-rev");
htmlNode.getElementById("consGridani").setAttribute("stroke-width", 55 * (1 - Math.exp(grid / 2000)));
} else {
htmlNode.getElementById("gridArc").setAttribute("d", describeArc(100, 100, 95, 0, grid / angleFactor));
htmlNode.getElementById("consGridani").setAttribute("class", "stream");
htmlNode.getElementById("consGridani").setAttribute("stroke-width", 55 * (1 - Math.exp(-grid / 2000)));
}
htmlNode.getElementById("consEVani").setAttribute("stroke-width", 55 * (1 - Math.exp(-evPower)));
htmlNode.getElementById("consEVOGani").setAttribute("stroke-width", 55 * (1 - Math.exp(-evPowerOG)));
htmlNode.getElementById("consOGani").setAttribute("stroke-width", 55 * (1 - Math.exp(og / 2000)));
htmlNode.getElementById("consUGani").setAttribute("stroke-width", 55 * (1 - Math.exp( -ug / 2000)));
htmlNode.getElementById("consHeatAni").setAttribute("stroke-width", 55 * (1 - Math.exp(-Pheat / 2000)));
htmlNode.getElementById("consAni").setAttribute("stroke-width", 55 * (1 - Math.exp(cons / 2000)));
htmlNode.getElementById("consEGani").setAttribute("stroke-width", 55 * (1 - Math.exp(-eg / 2000)));
htmlNode.getElementById("pvani").setAttribute("stroke-width", 55 * (1 - Math.exp(-pv / 2000)));
htmlNode.getElementById("pvani");
}
}
var chartSettings = {
type: 'line',
options: {
animation: true,
plugins: {
annotation: {
common: { type: 'box', drawTime: 'beforeDatasetsDraw', yScaleID: 'y-axis-0', backgroundColor: 'rgba(255, 255, 255, 0.05)', init: true },
annotations: []
},
tooltip: {
position: 'nearest',
pointStyle: "circle",
boxWidth: 4,
usePointStyle: true,
callbacks: {
footer: function (tooltipItems){return ""},
},
},
legend: {
position: "bottom",
labels: {
pointStyleWidth: 10,
usePointStyle: true,
pointStyle: "line",
}
},
},
responsive: true,
maintainAspectRatio: false,
interaction: {
intersect: false,
mode: 'index',
},
scales: {
x: {
adapters: {
date: {
locale: "DE-de"
}
},
ticks: {
},
type: 'timestack',
},
y: {
stacked: true,
display: true,
min: 0,
position: 'left',
ticks: {
callback: value => `${value / 1000}kW`,
},
/*title: {
display: true,
text: "Leistung"
}*/
},
y1: {
stacked: false,
display: true,
position: 'right',
min: 0,
max: 100,
ticks: {
callback: value => `${value}%`,
},
/*title: {
display: true,
text: "Ladestand"
},*/
data:{}
}
}
}
};
var forecastChartSettings = {
type: 'bar',
options: {
animation: true,
plugins: {
tooltip: {
position: 'nearest',
pointStyle: "circle",
boxWidth: 4,
usePointStyle: true,
callbacks: {
footer: function (tooltipItems){return ""},
},
},
legend: {
position: "bottom",
labels: {
pointStyleWidth: 10,
usePointStyle: true,
pointStyle: "line",
}
},
},
responsive: true,
maintainAspectRatio: false,
interaction: {
intersect: false,
mode: 'index',
},
scales: {
x: {
adapters: {
date: {
locale: "DE-de"
}
},
ticks: {
},
type: 'timestack',
timestack:{
right_floating_tick_thres: 0.3,
format_style: {month: 'long'},
}
},
y: {
stacked: false,
display: true,
position: 'left',
ticks: {
callback: value => `${value / 1000}kW`,
},
/*title: {
display: true,
text: "Leistung"
}*/
},
}
}
};
var modalEV = new bootstrap.Modal(document.getElementById('modalEV'), {
keyboard: false
});
var chartData = {};
var mqttData = {};
var timeFrom = -24;
var timeTo = 12;
const consChart = new Chart(
document.querySelector('#consumption-chart'),
Object.assign({}, chartSettings)
);
const prodChart = new Chart(
document.querySelector('#production-chart'),
Object.assign({}, chartSettings)
);
const foreChart = new Chart(
document.querySelector('#forecast-chart'),
Object.assign({}, forecastChartSettings)
);
function updateCharts(){
getData(consChart, 'ajax/getConsData.php',true,false,false);
getData(prodChart, 'ajax/getProdData.php',true,false,false);
}
function prevDay(){
timeFrom -= 24;
timeTo -= 24;
var now = new Date();
now.setDate(now.getDate()+1+(timeFrom/24));
var day = ("0" + now.getDate()).slice(-2);
var month = ("0" + (now.getMonth() + 1)).slice(-2);
var selected = now.getFullYear()+"-"+(month)+"-"+(day);
document.getElementById("DatePickerCons").value = selected;
document.getElementById("DatePickerProd").value = selected;
updateCharts();
}
function changeDay(e){
const date1 = new Date(e.target.value);
const date2 = new Date();
const difference = Math.floor((date1.getTime() - date2.getTime()) / (1000*60*60*24)) *24;
timeFrom = difference;
timeTo = difference+36;
updateCharts();
//.then((ret) => enableEvents());
}
function nextDay(){
timeFrom += 24;
timeTo += 24;
var now = new Date();
now.setDate(now.getDate()+1+(timeFrom/24));
var day = ("0" + now.getDate()).slice(-2);
var month = ("0" + (now.getMonth() + 1)).slice(-2);
var selected = now.getFullYear()+"-"+(month)+"-"+(day);
document.getElementById("DatePickerCons").value = selected;
document.getElementById("DatePickerProd").value = selected;
updateCharts();
}
document.addEventListener('readystatechange', function () {
if (event.target.readyState === "complete") {
solarMQTT.getMQTT();
getData(consChart, 'ajax/getConsData.php');
getData(prodChart, 'ajax/getProdData.php');
getData(foreChart,'ajax/getForecastData.php', false);
getStats("Stats-Year","ajax/getStats.php?type=ThisYear");
solarSVG.fillElementArray();
this.getElementById("meteogram").innerHTML = "<iframe src='"+meteogramURL+"' frameborder='0' scrolling=NO' allowtransparency='true' sandbox='allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox' style='width: 100%;height: 500px;border: 0;overflow: hidden;'></iframe><!-- DO NOT REMOVE THIS LINK --><a href='https://www.meteoblue.com/de/wetter/woche/index' target='_blank' rel='noopener'></a>";
}
});
String.prototype.toHHMM = function () {
var sec_num = parseInt(this, 10); // don't forget the second param
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
//var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) { hours = "0" + hours; }
if (minutes < 10) { minutes = "0" + minutes; }
return hours + ':' + minutes;
}
function loadingHTML(msg) {
return "<div class='m-4'><div class='spinner-border' role='status'><span class='visually-hidden'>Loading...</span></div>&nbsp;&nbsp;&nbsp;" + msg + "</div>"
}
function openModal(type) {
switch(type){
case "CarEG":
document.getElementById("modal-title").innerHTML = "Autoladung EG";
contentURL = "ajax/carEG.php";
break;
case "CarOG":
document.getElementById("modal-title").innerHTML = "Autoladung OG";
contentURL = "ajax/carOG.php";
break;
case "heater":
document.getElementById("modal-title").innerHTML = "Steuerung Heizstab";
contentURL = "ajax/heater.php";
break;
default:
document.getElementById("modal-title").innerHTML = "Fehler";
contentURL = "";
break;
}
modalBodyElement = document.getElementById('modal-body');
modalBodyElement.innerHTML = loadingHTML("Wird geladen...");
document.getElementById("modalSaveBtn").addEventListener("click", submitFormAjax);
document.getElementById("modalSaveBtn").contentURL = contentURL;
modalEV.show();
fetch(contentURL, {
method: 'GET',
headers: {
'X-Requested-From-Modal': 'a',
'Requested-With-Ajax': 'ajax'
}
})
.then(response => response.text())
.then(html => {
modalBodyElement.innerHTML = html;
var slider = document.getElementById("modal-slider");
var span = document.getElementById("modal-slider-label");
switch(type){
case "CarEG":
slider.oninput = function () {
marginValue = parseInt(this.value);
slider.style.setProperty("--background-size", `${marginValue}%`);
if (marginValue < 10) {
marginValue = marginValue - 0.4 * marginValue;
} else if (marginValue < 85) {
marginValue = marginValue - 4;
}
else {
marginValue = marginValue - 4 - 0.5 * (marginValue - 85);
}
span.setAttribute('style', 'margin-left:' + marginValue + '%;');
span.innerHTML = this.value + "%";
}
document.getElementById("evStart/Stop").addEventListener("click", submitFormAjax);
document.getElementById("evStart/Stop").contentURL = contentURL;
mode = new TextDecoder().decode(mqttData["wattpilot/properties/lmo/state"]);
time = String(mqttData["wattpilot/properties/ftt/state"]);
energy = mqttData["wattpilot/properties/fte/state"];
amp = new TextDecoder().decode(mqttData["wattpilot/properties/amp/state"]);
car = new TextDecoder().decode(mqttData["wattpilot/properties/car/state"]);
charge = Number(mqttData["solarManager/p_l1ev"])+Number(mqttData["solarManager/p_l2ev"])+Number(mqttData["solarManager/p_l3ev"])
if (charge < 0.2) { document.getElementById("evStart/Stop").innerHTML = 'Laden starten' }
else { document.getElementById("evStart/Stop").innerHTML = 'Laden stoppen' }
if (mode == "Awattar") { document.getElementById("EV_Eco").click(); }
else if (mode == "Default") { document.getElementById("EV_Default").click(); }
else if (mode == "AutomaticStop") { document.getElementById("EV_NextTrip").click(); }
else { alert(mode); }
document.getElementById("EV_NextTripTime").value = time.toHHMM();
document.getElementById("modal-slider").value = Math.round(energy * 100 / 14000);
document.getElementById("modal-slider").dispatchEvent(new Event('input'));
if (amp == "16") { document.getElementById("EV_16A").click(); }
else if (amp == "10") { document.getElementById("EV_10A").click(); }
else if (amp == "6") { document.getElementById("EV_6A").click(); }
break;
case "CarOG":
slider.oninput = function () {
marginValue = parseInt((this.value-this.min)*100/this.max);
slider.style.setProperty("--background-size", `${marginValue}%`);
if (marginValue < 10) {
marginValue = marginValue - 0.4 * marginValue;
} else if (marginValue < 85) {
marginValue = marginValue - 4;
}
else {
marginValue = marginValue - 4 - 0.5 * (marginValue - 85);
}
span.setAttribute('style', 'margin-left:' + marginValue + '%;');
span.innerHTML = this.value + "%";
}
document.getElementById("evStart/Stop").addEventListener("click", submitFormAjax);
document.getElementById("evStart/Stop").contentURL = contentURL;
mode = mqttData["go-eCharger/270003/lmo"];
time = String(mqttData["go-eCharger/270003/att"]);
energy = mqttData["go-eCharger/270003/ate"];
amp = mqttData["go-eCharger/270003/amp"];
car = mqttData["go-eCharger/270003/car"];
if (car != "2") { document.getElementById("evStart/Stop").innerHTML = 'Laden starten' }
else { document.getElementById("evStart/Stop").innerHTML = 'Laden stoppen' }
if (mode == "4") { document.getElementById("EV_Eco").click(); }
else if (mode == "3") { document.getElementById("EV_Default").click(); }
else if (mode == "5") { document.getElementById("EV_NextTrip").click(); }
else { alert(mode); }
document.getElementById("EV_NextTripTime").value = time.toHHMM();
document.getElementById("modal-slider").value = Math.round(energy * 100 / 14000);
document.getElementById("modal-slider").dispatchEvent(new Event('input'));
if (amp == "16") { document.getElementById("EV_16A").click(); }
else if (amp == "10") { document.getElementById("EV_10A").click(); }
else if (amp == "6") { document.getElementById("EV_6A").click(); }
break;
case "heater":
slider.oninput = function () {
marginValue = parseInt((this.value-this.min)*100/this.max);
slider.style.setProperty("--background-size", `${marginValue}%`);
if (marginValue < 10) {
marginValue = marginValue - 0.4 * marginValue;
} else if (marginValue < 85) {
marginValue = marginValue - 4;
}
else {
marginValue = marginValue - 4 - 0.5 * (marginValue - 85);
}
span.setAttribute('style', 'margin-left:' + marginValue + '%;');
if(this.value == 0){
span.innerHTML = "Automatik";
}else{
span.innerHTML = (this.value/10) + " kW";
}
}
if(mqttData["solarManager/heatMode"] == "eco"){
document.getElementById("modal-slider").value = 0;
}else{
document.getElementById("modal-slider").value = Math.round(mqttData["solarManager/pHeat"]/100);
}
document.getElementById("modal-slider").dispatchEvent(new Event('input'));
break;
}
})
.catch(error => {
modalBodyElement.innerHTML = error.message;
});
}
function submitFormAjax(event) {
let xmlhttp = window.XMLHttpRequest ?
new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200)
modalEV.hide();
}
const form = document.getElementById('modalEV').querySelector('form');
post = "";
// ✅ Get interesting form elements
if (event.currentTarget.id == "evStart/Stop") {
post = "evStart/Stop=" + event.currentTarget.innerHTML;
} else {
const formElements = Array.from(form.elements);
for (let i = 0; i < formElements.length; i++) {
if(formElements[i].name){
if (formElements[i].type == "radio" && formElements[i].checked) {
post += formElements[i].name + "=" + encodeURIComponent(formElements[i].value) + "&";
} else if(formElements[i].type == "checkbox" && formElements[i].checked){
post += formElements[i].name + "=" + encodeURIComponent(formElements[i].value) + "&";
} else if(formElements[i].type == "button" && !formElements[i].classList.contains("accordion-button")){
post += formElements[i].name + "=" + encodeURIComponent(formElements[i].innerHTML) + "&";
}else if(formElements[i].type != "checkbox" && formElements[i].type != "radio") {
post += formElements[i].name + "=" + encodeURIComponent(formElements[i].value) + "&";
}
}
}
}
xmlhttp.open("POST", event.currentTarget.contentURL, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
document.getElementById('modalEV').querySelector('.modal-body').innerHTML = loadingHTML("Änderungen werden übernommen...");
xmlhttp.send(post);
return false;
}
async function getData(chrt, url, sunrise=true, autoUpdate=true, animation=true) {
try {
chrt.options.events = [];
console.log("fetching "+url+"?FROM="+timeFrom+"&TO="+timeTo);
const response = await fetch(url+"?FROM="+timeFrom+"&TO="+timeTo);
if (!response.ok) {
console.log("err");
throw new Error(`Response status: ${response.status}`);
}
chrt.data = await response.json();
if(sunrise){
const response2 = await fetch("ajax/getSunrise.php?FROM="+timeFrom+"&TO="+timeTo);
if (!response2.ok) {
console.log("err");
throw new Error(`Response status: ${response2.status}`);
}
chrt.options.plugins.annotation.annotations = await response2.json();
}
chrt.options.events = ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'];
if(animation)
chrt.update();
else
chrt.update("none");
} catch (error) {
console.log(error.message);
}
if(autoUpdate){
setTimeout(function () { getData(chrt, url, sunrise,autoUpdate,animation) }, 5 * 60 * 1000); //renew data every 5 min.
}
}
async function getDataOnly(chart, url, sunrise=true, autoUpdate=true, animation=true) {
try {
console.log("fetching "+url+"?FROM="+timeFrom+"&TO="+timeTo);
const response = await fetch(url+"?FROM="+timeFrom+"&TO="+timeTo);
if (!response.ok) {
console.log("err");
throw new Error(`Response status: ${response.status}`);
}
chart.data = await response.json();
if(sunrise){
const response2 = await fetch("ajax/getSunrise.php?FROM="+timeFrom+"&TO="+timeTo);
if (!response2.ok) {
console.log("err");
throw new Error(`Response status: ${response2.status}`);
}
chart.options.plugins.annotation.annotations = await response2.json();
}
} catch (error) {
console.log(error.message);
}
if(autoUpdate){
setTimeout(function () { getData(chart, url, sunrise,autoUpdate,animation) }, 5 * 60 * 1000); //renew data every 5 min.
}
}
async function getStats(elem_id, url) {
try {
console.log("fetching");
const response = await fetch(url);
if (!response.ok) {
console.log("err");
throw new Error(`Response status: ${response.status}`);
}
document.getElementById(elem_id).innerHTML = await response.text();
} catch (error) {
console.log(error.message);
}
setTimeout(function () { getData(chart, url, sunrise) }, 5 * 60 * 1000); //renew data every 5 min.
}
function powerToString(power) {
if (Math.abs(power) > 999) {
power = power / 1000
return power.toPrecision(3) + "kW"
} else {
return Math.round(power) + "W"
}
}
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
function getRBGComponent(colRange, minCol, valRange, minVal, val) {
return Math.round(((val - minVal) / valRange) * colRange + minCol)
.toString(16)
.toUpperCase()
.padStart(2, '0');
}
function assignColor(minCol, maxCol, minVal, maxVal, val) {
var color = "";
var minR = parseInt(minCol.substring(1, 3), 16);
var maxR = parseInt(maxCol.substring(1, 3), 16);
var minG = parseInt(minCol.substring(3, 5), 16);
var maxG = parseInt(maxCol.substring(3, 5), 16);
var minB = parseInt(minCol.substring(5, 7), 16);
var maxB = parseInt(maxCol.substring(5, 7), 16);
var valsRange = maxVal - minVal;
var rangeG = maxG - minG;
var rangeR = maxR - minR;
var rangeB = maxB - minB;
if (val > maxVal)
val = maxVal;
else if (val < minVal)
val = minVal;
color = '#'
+ getRBGComponent(rangeR, minR, valsRange, minVal, val)
+ getRBGComponent(rangeG, minG, valsRange, minVal, val)
+ getRBGComponent(rangeB, minB, valsRange, minVal, val);
return color;
}
function describeArc(x, y, radius, startAngle, endAngle) {
if (endAngle > 288) {
endAngle = 288;
}
var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);
var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
var d = [
"M", start.x, start.y,
"A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
].join(" ");
return d;
}
function updateValuesWeather(){
var div=document.getElementById("windDir");
div.style.transform = "rotate("+(90+Number(mqttData["weatherStation/windDeg"]))+"deg)";
document.getElementById("windSpd").innerHTML = mqttData["weatherStation/avgWindspeed"];
document.getElementById("humidity").innerHTML = mqttData["weatherStation/hum"];
document.getElementById("temp").innerHTML = mqttData["weatherStation/tempAmb"];
document.getElementById("windDirGust").style.transform = "rotate("+(90+Number(mqttData["weatherStation/gustDeg"]))+"deg)";
document.getElementById("windGust").innerHTML = mqttData["weatherStation/maxgust"];
document.getElementById("ambPress").innerHTML = Math.round(mqttData["weatherStation/qff"]*10)/10;
}