Initial commit
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
function changeValueType(event){
|
||||
dropdown = event.currentTarget;
|
||||
type = dropdown.options[dropdown.selectedIndex].dataset.type;
|
||||
id = dropdown.id.match(/\d+$/);
|
||||
if(dropdown.id.search("act") > -1){
|
||||
opBtnID = "btnActOperator"+id;
|
||||
valBlockID = "actValBlock"+id;
|
||||
valElemID = "actValue"+id;
|
||||
}else{
|
||||
opBtnID = "btnOperator"+id;
|
||||
valBlockID ="valBlock"+id;
|
||||
valElemID = "threshold"+id;
|
||||
}
|
||||
if(type =="hidden"){
|
||||
document.getElementById(opBtnID).hidden = true;
|
||||
document.getElementById(valBlockID).hidden = true;
|
||||
}else{
|
||||
document.getElementById(opBtnID).hidden = false;
|
||||
document.getElementById(valBlockID).hidden = false;
|
||||
document.getElementById(valElemID).type = type;
|
||||
}
|
||||
}
|
||||
|
||||
function fillSensorDD(ID){
|
||||
var elem = document.getElementById("sensorSelect"+ID);
|
||||
fetch("./ajax/fillSensorDD.php", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Requested-From-Modal': 'a',
|
||||
'Requested-With-Ajax': 'ajax'
|
||||
}
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
elem.innerHTML = html;
|
||||
elem.addEventListener("change", arrangeSensorInputs);
|
||||
document.getElementById("paramSelect"+ID).addEventListener("change", changeValueType);
|
||||
elem.dispatchEvent(new Event('change'));
|
||||
})
|
||||
.catch(error => {
|
||||
elem.innerHTML = "";
|
||||
});
|
||||
}
|
||||
|
||||
function fillActorDD(ID){
|
||||
var elem = document.getElementById("actorSelect"+ID);
|
||||
fetch("./ajax/fillActorDD.php", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Requested-From-Modal': 'a',
|
||||
'Requested-With-Ajax': 'ajax'
|
||||
}
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
elem.innerHTML = html;
|
||||
elem.addEventListener("change", arrangeActorInputs);
|
||||
document.getElementById("actParamSelect"+ID).addEventListener("change", changeValueType);
|
||||
document.getElementById("actorSelect"+ID).dispatchEvent(new Event('change'));
|
||||
})
|
||||
.catch(error => {
|
||||
elem.innerHTML = "";
|
||||
});
|
||||
}
|
||||
|
||||
function changeAllIDs (parentNode, newID) {
|
||||
for (var i = 0; i < parentNode.childNodes.length; i++) {
|
||||
var child = parentNode.childNodes[i];
|
||||
changeAllIDs(child, newID);
|
||||
}
|
||||
if(parentNode.id){
|
||||
parentNode.id = parentNode.id.replace(/\d+$/, newID);
|
||||
}
|
||||
if(parentNode.dataset !== undefined){
|
||||
if(parentNode.dataset.delid)
|
||||
parentNode.dataset.delid = parentNode.dataset.delid.replace(/\d+$/, newID);
|
||||
}
|
||||
}
|
||||
|
||||
function delAutoEntry(event){
|
||||
ID = event.currentTarget.dataset.delid;
|
||||
document.getElementById(ID).remove();
|
||||
ID = ID.replace(/\d+$/, function(n){ return ++n });
|
||||
while(sensor= document.getElementById(ID)){
|
||||
changeAllIDs(sensor, ID.match(/\d+$/)-1);
|
||||
ID = ID.replace(/\d+$/, function(n){ return ++n });
|
||||
}
|
||||
}
|
||||
function addSensor(event){
|
||||
var t = document.getElementById('sensorsList').children;
|
||||
//get the second last element (ignore "add" button)
|
||||
nextID = Number(t[t.length-1].id.replace("sensorSettings","")) + 1;
|
||||
var div = document.createElement('div');
|
||||
div.className = "input-group mt-3";
|
||||
div.id = "sensorSettings"+String(nextID);
|
||||
div.innerHTML = `<button class='btn btn-outline-secondary' type='button' id='btnLogic${nextID}' name='btnLogic${nextID}' data-tglstates='["und","oder"]' >und</button>
|
||||
<div class="form-floating">
|
||||
<select class="form-select" id="sensorSelect${nextID}" name="sensorSelect${nextID}" aria-label="Default select example">
|
||||
</select>
|
||||
<label>Sensor</label>
|
||||
</div>
|
||||
<div class="form-floating" id="paramBlock${nextID}">
|
||||
<select class="form-select" id="paramSelect${nextID}" name="paramSelect${nextID}" aria-label="Default select example">
|
||||
</select>
|
||||
<label>Messwert</label>
|
||||
</div>
|
||||
<button class="btn btn-outline-secondary " type="button" id="btnOperator${nextID}" name="btnOperator${nextID}">></button>
|
||||
<div class="form-floating" id="valBlock${nextID}">
|
||||
<input type="number" class="form-control" id="threshold${nextID}" name="threshold${nextID}" placeholder="0" value="0"></input>
|
||||
<label>Wert/Schwelle</label>
|
||||
</div>
|
||||
<button class='btn btn-outline-danger' type='button' id='btnDel${nextID}' data-delid="sensorSettings${nextID}" onclick="delAutoEntry(event)"><i class="bi bi-trash3"></i></button>
|
||||
</div>`;
|
||||
document.getElementById("sensorsList").appendChild(div);
|
||||
fillSensorDD(nextID);
|
||||
}
|
||||
|
||||
function addActor(event){
|
||||
var t = document.getElementById('actorsList').children;
|
||||
//get the second last element (ignore "add" button)
|
||||
nextID = Number(t[t.length-1].id.replace("actorSettings","")) + 1;
|
||||
var div = document.createElement('div');
|
||||
div.className = "input-group mt-3";
|
||||
div.id = "actorSettings"+String(nextID);
|
||||
div.innerHTML = `<div class="form-floating">
|
||||
<select class="form-select" id="actorSelect${nextID}" name="actorSelect${nextID}" aria-label="Default select example">
|
||||
</select>
|
||||
<label>Aktor</label>
|
||||
</div>
|
||||
<div class="form-floating" id="actParamBlock${nextID}">
|
||||
<select class="form-select" id="actParamSelect${nextID}" name="actParamSelect${nextID}" aria-label="Default select example">
|
||||
</select>
|
||||
<label>Eigenschaft</label>
|
||||
</div>
|
||||
<button class="btn btn-outline-secondary " type="button" id="btnActOperator${nextID}" name="btnActOperator${nextID}">></button>
|
||||
<div class="form-floating" id="actValBlock${nextID}">
|
||||
<input type="number" class="form-control" id="actValue${nextID}" name="actValue${nextID}" placeholder="0" value="0"></input>
|
||||
<label>Sollwert</label>
|
||||
</div>
|
||||
<button class='btn btn-outline-danger' type='button' id='btnActDel${nextID}' data-delid="actorSettings${nextID}" onclick="delAutoEntry(event)"><i class="bi bi-trash3"></i></button>`;
|
||||
|
||||
document.getElementById("actorsList").appendChild(div);
|
||||
/*"afterend",`<div class='input-group mb-3' id='actorSettings${nextID}'>
|
||||
<div class="form-floating">
|
||||
<select class="form-select" id="actorSelect${nextID}" aria-label="Default select example">
|
||||
</select>
|
||||
<label>Aktor</label>
|
||||
</div>
|
||||
<div class="form-floating" id="actParamBlock${nextID}">
|
||||
<select class="form-select" id="actParamSelect${nextID}" aria-label="Default select example">
|
||||
</select>
|
||||
<label>Eigenschaft</label>
|
||||
</div>
|
||||
<button class="btn btn-outline-secondary " type="button" id="btnActOperator${nextID}">></button>
|
||||
<div class="form-floating" id="actValBlock${nextID}">
|
||||
<input type="number" class="form-control" id="actValue${nextID}" placeholder="0" value="0"></input>
|
||||
<label>Sollwert</label>
|
||||
</div>
|
||||
<button class='btn btn-outline-danger' type='button' id='btnActDel${nextID}' data-delid="actorSettings${nextID}" onclick="delAutoEntry(event)"><i class="bi bi-trash3"></i></button>
|
||||
</div>`);*/
|
||||
fillActorDD(nextID);
|
||||
}
|
||||
|
||||
function arrangeSensorInputs(event){
|
||||
ID = Number(event.currentTarget.id.replace("sensorSelect",""));
|
||||
sensorID = document.getElementById("sensorSelect"+ID).value;
|
||||
|
||||
fetch("./ajax/sensorDetails.php?sensorID="+sensorID, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Requested-From-Modal': 'a',
|
||||
'Requested-With-Ajax': 'ajax'
|
||||
}
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
params = JSON.parse(html);
|
||||
document.getElementById("paramSelect"+ID).innerHTML = "";
|
||||
if(params.Parameters.length == 1){
|
||||
document.getElementById("paramBlock"+ID).hidden = true;
|
||||
}else{
|
||||
document.getElementById("paramBlock"+ID).hidden = false;
|
||||
}
|
||||
params.Parameters.forEach((param, index) => {
|
||||
var option = document.createElement("option");
|
||||
option.text = param.name;
|
||||
option.value = index;
|
||||
option.setAttribute("data-type",param.type);
|
||||
document.getElementById("paramSelect"+ID).appendChild(option);
|
||||
document.getElementById("btnOperator"+ID).setAttribute("data-tglstates",JSON.stringify(param.operators));
|
||||
document.getElementById("btnOperator"+ID).innerHTML = param.operators[0];
|
||||
document.getElementById("btnOperator"+ID).addEventListener("click", tglOperators);
|
||||
if(document.getElementById("btnLogic"+ID))
|
||||
document.getElementById("btnLogic"+ID).addEventListener("click", tglOperators);
|
||||
document.getElementById("threshold"+ID).setAttribute("type",param.type);
|
||||
});
|
||||
document.getElementById("paramSelect"+ID).dispatchEvent(new Event('change'));
|
||||
})
|
||||
.catch(error => {
|
||||
alert(error);
|
||||
document.getElementById("paramSelect"+ID).innerHTML = "";
|
||||
});
|
||||
}
|
||||
|
||||
function arrangeActorInputs(event){
|
||||
ID = Number(event.currentTarget.id.replace("actorSelect",""));
|
||||
sensorID = document.getElementById("actorSelect"+ID).value;
|
||||
|
||||
fetch("./ajax/actorDetails.php?actorID="+sensorID, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Requested-From-Modal': 'a',
|
||||
'Requested-With-Ajax': 'ajax'
|
||||
}
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
params = JSON.parse(html);
|
||||
document.getElementById("actParamSelect"+ID).innerHTML = "";
|
||||
if(params.Parameters.length == 1){
|
||||
document.getElementById("actParamBlock"+ID).hidden = true;
|
||||
}else{
|
||||
document.getElementById("actParamBlock"+ID).hidden = false;
|
||||
}
|
||||
params.Parameters.forEach((param, index) => {
|
||||
var option = document.createElement("option");
|
||||
option.text = param.name;
|
||||
option.value = index;
|
||||
option.setAttribute("data-type",param.type);
|
||||
document.getElementById("actParamSelect"+ID).appendChild(option);
|
||||
if(param.operators === undefined){
|
||||
document.getElementById("btnActOperator"+ID).dataset.tglstates = "[\"=\"]";
|
||||
document.getElementById("btnActOperator"+ID).innerHTML = "=";
|
||||
}else{
|
||||
document.getElementById("btnActOperator"+ID).dataset.tglstates = JSON.stringify(param.operators);
|
||||
document.getElementById("btnActOperator"+ID).innerHTML = param.operators[0];
|
||||
}
|
||||
document.getElementById("btnActOperator"+ID).addEventListener("click", tglOperators);
|
||||
if(document.getElementById("btnActLogic"+ID)){
|
||||
document.getElementById("btnActLogic"+ID).addEventListener("click", tglOperators);
|
||||
}
|
||||
//if(document.getElementById("actParamSelect"+ID).value == param.id)
|
||||
// document.getElementById("actValue"+ID).setAttribute("type",param.type);
|
||||
});
|
||||
document.getElementById("actParamSelect"+ID).dispatchEvent(new Event('change'));
|
||||
})
|
||||
.catch(error => {
|
||||
document.getElementById("actParamSelect"+ID).innerHTML = "";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function tglOperators(event){
|
||||
btn = event.currentTarget;
|
||||
operators = JSON.parse(btn.dataset.tglstates);
|
||||
current = btn.innerHTML;
|
||||
btn.innerHTML = operators[(operators.indexOf(current)+1) % operators.length];
|
||||
}
|
||||
|
||||
function loadAutomatic(params){
|
||||
if(params.search("action=new")>0){
|
||||
fillSensorDD("1");
|
||||
fillActorDD("1");
|
||||
}
|
||||
}
|
||||
|
||||
function openAutoActionModal(params) {
|
||||
let contentURL = "./ajax/AutoAction.php"+params;
|
||||
if(params.search("action=new")>0)
|
||||
document.getElementById("modal-title").innerHTML = "Neue Automatik anlegen";
|
||||
else
|
||||
document.getElementById("modal-title").innerHTML = "Automatik Einstellungen";
|
||||
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;
|
||||
loadAutomatic(params);
|
||||
document.getElementById("btnAddSensor").addEventListener("click", addSensor);
|
||||
document.getElementById("btnAddActor").addEventListener("click", addActor);
|
||||
})
|
||||
.catch(error => {
|
||||
modalBodyElement.innerHTML += error.message;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
var mqttData = {};
|
||||
|
||||
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) {
|
||||
setNestedProp(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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const solarSVG = {
|
||||
updateCnt: 99,
|
||||
updateValuesMQTT: function (mqttData) {
|
||||
if (this.updateCnt > 10) {
|
||||
this.updateCnt = 0;
|
||||
var obj = document.querySelector("object");
|
||||
var htmlNode = obj.contentDocument;
|
||||
htmlNode.getElementById("PufferOtxt").innerHTML = mqttData["solarManager"]["t_buffT"] + " °C";
|
||||
htmlNode.getElementById("PufferMtxt").innerHTML = mqttData["solarManager"]["t_buffM"] + " °C";
|
||||
htmlNode.getElementById("PufferUtxt").innerHTML = mqttData["solarManager"]["t_buffB"] + " °C";
|
||||
htmlNode.getElementById("heaterVL").innerHTML = mqttData["solarManager"]["t_heatVL"] + " °C";
|
||||
htmlNode.getElementById("heaterRL").innerHTML = mqttData["solarManager"]["t_heatRL"] + " °C";
|
||||
htmlNode.getElementById("thermeVLfb").innerHTML = mqttData["solarManager"]["t_gasVLu"] + " °C";
|
||||
htmlNode.getElementById("thermeVLww").innerHTML = mqttData["solarManager"]["t_gasVLo"] + " °C";
|
||||
htmlNode.getElementById("thermeRL").innerHTML = mqttData["solarManager"]["t_gasRL"] + " °C";
|
||||
htmlNode.getElementById("fbVL").innerHTML = mqttData["solarManager"]["t_fbVL"] + " °C";
|
||||
htmlNode.getElementById("fbRL").innerHTML = mqttData["solarManager"]["t_fbRL"] + " °C";
|
||||
htmlNode.getElementById("triac").innerHTML = mqttData["solarManager"]["t_triac"] + " °C";
|
||||
}
|
||||
this.updateCnt++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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: {
|
||||
label: function (context) {
|
||||
let label = context.dataset.label || '';
|
||||
if (label) {
|
||||
label += ': ';
|
||||
}
|
||||
if (context.dataset.yAxisID == "y1") {
|
||||
label += Math.round(context.parsed.y * 10) / 10 + " " + "L/min";
|
||||
} else {
|
||||
if (context.parsed.y !== null) {
|
||||
ret = scale(Math.round(context.parsed.y), false);
|
||||
label += ret[0] + " " + ret[1] + "°C";
|
||||
}
|
||||
}
|
||||
return label;
|
||||
},
|
||||
},
|
||||
},
|
||||
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: false,
|
||||
display: true,
|
||||
position: 'left',
|
||||
ticks: {
|
||||
callback: value => `${value} °C`,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: "Temperatur"
|
||||
}
|
||||
},
|
||||
y1: {
|
||||
stacked: false,
|
||||
display: true,
|
||||
position: 'right',
|
||||
ticks: {
|
||||
callback: value => `${value} L/min`,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: "Wasserverbrauch"
|
||||
},
|
||||
data:{}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var chartData = {};
|
||||
const heatChart = new Chart(
|
||||
document.querySelector('#heat-chart'),
|
||||
Object.assign({}, chartSettings)
|
||||
);
|
||||
const waterChart = new Chart(
|
||||
document.querySelector('#water-chart'),
|
||||
Object.assign({}, chartSettings)
|
||||
);
|
||||
|
||||
document.addEventListener('readystatechange', function () {
|
||||
if (event.target.readyState === "complete") {
|
||||
solarMQTT.getMQTT();
|
||||
getData(heatChart, 'ajax/getHeaterData.php');
|
||||
getData(waterChart, 'ajax/getWaterData.php');
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
async function getData(chart, url, sunrise=true) {
|
||||
try {
|
||||
console.log("fetching");
|
||||
const response = await fetch(url);
|
||||
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=-24&TO=0");
|
||||
if (!response2.ok) {
|
||||
console.log("err");
|
||||
throw new Error(`Response status: ${response2.status}`);
|
||||
}
|
||||
chart.options.plugins.annotation.annotations = await response2.json();
|
||||
}
|
||||
chart.update();
|
||||
} 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"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
tooltipLabel = function (context) {
|
||||
let label = context.dataset.label || '';
|
||||
if (label) {
|
||||
label += ': ';
|
||||
}
|
||||
if (context.dataset.yAxisID == "y1") {
|
||||
label += Math.round(context.parsed.y * 10) / 10 + " " + "%";
|
||||
} else {
|
||||
if (context.parsed.y !== null) {
|
||||
ret = scale(Math.round(context.parsed.y), false);
|
||||
label += ret[0] + " " + ret[1] + "Wh";
|
||||
}
|
||||
}
|
||||
return label;
|
||||
};
|
||||
|
||||
tooltipFooter = function (tooltipItems){
|
||||
let sum = 0;
|
||||
|
||||
tooltipItems.forEach(function(tooltipItem) {
|
||||
if (tooltipItem.dataset.yAxisID != "y1") {
|
||||
sum += tooltipItem.parsed.y;
|
||||
}
|
||||
});
|
||||
ret = scale(Math.round(sum), false);
|
||||
sum = ret[0] + " " + ret[1] + "Wh";
|
||||
return 'Summe: ' + sum;
|
||||
}
|
||||
|
||||
legendLabels = function(chart){
|
||||
const datasets = chart.data.datasets;
|
||||
const {
|
||||
labels: {
|
||||
usePointStyle,
|
||||
pointStyle,
|
||||
textAlign,
|
||||
color
|
||||
}
|
||||
} = chart.legend.options;
|
||||
return chart._getSortedDatasetMetas().map((meta) => {
|
||||
const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
|
||||
const borderWidth = Chart.helpers.toPadding(style.borderWidth);
|
||||
ret = scale(Math.round(arraySum(datasets[meta.index].data)), false);
|
||||
ret2 = scale(Math.round(datasets[meta.index].data[datasets[meta.index].data.length-1]), false);
|
||||
return {
|
||||
text: datasets[meta.index].label + " Σ " + ret[0]+" "+ret[1]+"Wh",//+ " Last: " + ret2[0]+" "+ret2[1]+"W",
|
||||
fillStyle: style.backgroundColor,
|
||||
fontColor: color,
|
||||
hidden: !meta.visible,
|
||||
lineCap: style.borderCapStyle,
|
||||
lineDash: style.borderDash,
|
||||
lineDashOffset: style.borderDashOffset,
|
||||
lineJoin: style.borderJoinStyle,
|
||||
lineWidth: (borderWidth.width + borderWidth.height) / 4,
|
||||
strokeStyle: style.borderColor,
|
||||
pointStyle: pointStyle || style.pointStyle,
|
||||
rotation: style.rotation,
|
||||
textAlign: textAlign || style.textAlign,
|
||||
borderRadius: 0, // TODO: v4, default to style.borderRadius
|
||||
datasetIndex: meta.index
|
||||
};
|
||||
}, this);
|
||||
}
|
||||
Chart.defaults.plugins.tooltip.callbacks.footer = tooltipFooter;
|
||||
Chart.defaults.plugins.tooltip.callbacks.label = tooltipLabel;
|
||||
Chart.defaults.plugins.legend.labels.generateLabels = legendLabels;
|
||||
|
||||
var forecastChartSettings = {
|
||||
type: 'bar',
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: {
|
||||
intersect: false,
|
||||
mode: 'index',
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
stacked: true,
|
||||
display: true,
|
||||
min: 0,
|
||||
suggestedMax: 1000,
|
||||
ticks: {
|
||||
callback: value => `${value / 1000} kWh`,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var decadeChartSettings = {
|
||||
type: 'bar',
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: {
|
||||
intersect: false,
|
||||
mode: 'index',
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
stacked: true,
|
||||
display: true,
|
||||
min: 0,
|
||||
suggestedMax: 1000000,
|
||||
ticks: {
|
||||
callback: value => `${value / 1000000} MWh`,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var chartData = {};
|
||||
|
||||
const consChart = new Chart(
|
||||
document.querySelector('#consumption-chart'),
|
||||
Object.assign({}, forecastChartSettings)
|
||||
);
|
||||
const prodChart = new Chart(
|
||||
document.querySelector('#production-chart'),
|
||||
Object.assign({}, forecastChartSettings)
|
||||
);
|
||||
const consChartYear = new Chart(
|
||||
document.querySelector('#consumption-chart-year'),
|
||||
Object.assign({}, decadeChartSettings)
|
||||
);
|
||||
const prodChartYear = new Chart(
|
||||
document.querySelector('#production-chart-year'),
|
||||
Object.assign({}, decadeChartSettings)
|
||||
);
|
||||
const consChartDecade = new Chart(
|
||||
document.querySelector('#consumption-chart-decade'),
|
||||
Object.assign({}, decadeChartSettings)
|
||||
);
|
||||
const prodChartDecade = new Chart(
|
||||
document.querySelector('#production-chart-decade'),
|
||||
Object.assign({}, decadeChartSettings)
|
||||
);
|
||||
document.addEventListener('readystatechange', function () {
|
||||
if (event.target.readyState === "complete") {
|
||||
getData(prodChart, 'ajax/getProdData_month.php');
|
||||
getData(consChart, 'ajax/getConsData_month.php');
|
||||
getData(prodChartYear, 'ajax/getProdData_year.php');
|
||||
getData(consChartYear, 'ajax/getConsData_year.php');
|
||||
getData(prodChartDecade, 'ajax/getProdData_decade.php');
|
||||
getData(consChartDecade, 'ajax/getConsData_decade.php');
|
||||
//getData(prodChart, 'ajax/getProdData.php');
|
||||
//getData(foreChart,'ajax/getForecastData.php', false);
|
||||
getStats("Stats-Year","ajax/getStats.php?type=ThisYear");
|
||||
getStats("Stats-Lastyear","ajax/getStats.php?type=LastYear");
|
||||
getStats("Stats-Prelastyear","ajax/getStats.php?type=PreLastYear");
|
||||
}
|
||||
});
|
||||
|
||||
async function getData(chart, url, sunrise=true) {
|
||||
try {
|
||||
console.log("fetching"+chart);
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
console.log("err");
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
}
|
||||
chart.data = await response.json();
|
||||
|
||||
|
||||
chart.update();
|
||||
//chart.options.scales.x.min = chart.data.labels[0]-(chart.data.labels[1]-chart.data.labels[0])/2;
|
||||
//chart.options.scales.x.max = chart.data.labels[chart.data.labels.length-1]+(chart.data.labels[1]-chart.data.labels[0])/2;
|
||||
chart.update();
|
||||
} catch (error) {
|
||||
console.log(error.message);
|
||||
}
|
||||
setTimeout(function () { getData(chart, url, sunrise) }, 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"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
|
||||
const homeMQTT = {
|
||||
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("Raumtemp/#");
|
||||
});
|
||||
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) {
|
||||
setNestedProp(mqttData, topic, message);
|
||||
setTimeout(function () { homeSVG.updateValuesMQTT(mqttData) }, 200); //give the object tree some time to build up and receive all values
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const homeSVG = {
|
||||
updateCnt: 99,
|
||||
fillElementArray: function () {
|
||||
|
||||
},
|
||||
updateValuesMQTT: function (mqttData) {
|
||||
var htmlNode = document
|
||||
//OG
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["Heating"] == "false") htmlNode.getElementById('OG_wozi_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('OG_wozi_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["mode"] == "Overheating") htmlNode.getElementById('OG_wozi_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('OG_wozi_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_pres_wozi').innerHTML = Math.floor(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_tmp_wozi').innerHTML = mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_hum_wozi').innerHTML = mqttData["Raumtemp"]["OG"]["Wohnzimmer"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Bad"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Bad"]["Heating"] == "false") htmlNode.getElementById('OG_bad_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('OG_bad_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Bad"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Bad"]["mode"] == "Overheating") htmlNode.getElementById('OG_bad_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('OG_bad_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Bad"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_pres_bad').innerHTML = Math.floor(mqttData["Raumtemp"]["OG"]["Bad"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Bad"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_tmp_bad').innerHTML = mqttData["Raumtemp"]["OG"]["Bad"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Bad"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_hum_bad').innerHTML = mqttData["Raumtemp"]["OG"]["Bad"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["Heating"] == "false") htmlNode.getElementById('OG_schlafen_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('OG_schlafen_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["mode"] == "Overheating") htmlNode.getElementById('OG_schlafen_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('OG_schlafen_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_pres_schlafen').innerHTML = Math.floor(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_tmp_schlafen').innerHTML = mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_hum_schlafen').innerHTML = mqttData["Raumtemp"]["OG"]["Schlafzimmer"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["KiZi"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["KiZi"]["Heating"] == "false") htmlNode.getElementById('OG_kizi_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('OG_kizi_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["KiZi"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["KiZi"]["mode"] == "Overheating") htmlNode.getElementById('OG_kizi_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('OG_kizi_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["KiZi"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_pres_kizi').innerHTML = Math.floor(mqttData["Raumtemp"]["OG"]["KiZi"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["KiZi"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_tmp_kizi').innerHTML = mqttData["Raumtemp"]["OG"]["KiZi"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["KiZi"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_hum_kizi').innerHTML = mqttData["Raumtemp"]["OG"]["KiZi"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Buero"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Buero"]["Heating"] == "false") htmlNode.getElementById('OG_buero_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('OG_buero_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Buero"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["OG"]["Buero"]["mode"] == "Overheating") htmlNode.getElementById('OG_buero_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('OG_buero_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Buero"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_pres_buero').innerHTML = Math.floor(mqttData["Raumtemp"]["OG"]["Buero"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Buero"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_tmp_buero').innerHTML = mqttData["Raumtemp"]["OG"]["Buero"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["OG"]["Buero"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('OG_hum_buero').innerHTML = mqttData["Raumtemp"]["OG"]["Buero"]["rHum[%]"]+" %rF";
|
||||
|
||||
//EG
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["Heating"] == "false") htmlNode.getElementById('EG_wozi_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('EG_wozi_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["mode"] == "Overheating") htmlNode.getElementById('EG_wozi_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('EG_wozi_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_pres_wozi').innerHTML = Math.floor(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_tmp_wozi').innerHTML = mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_hum_wozi').innerHTML = mqttData["Raumtemp"]["EG"]["Wohnzimmer"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Bad"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Bad"]["Heating"] == "false") htmlNode.getElementById('EG_bad_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('EG_bad_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Bad"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Bad"]["mode"] == "Overheating") htmlNode.getElementById('EG_bad_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('EG_bad_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Bad"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_pres_bad').innerHTML = Math.floor(mqttData["Raumtemp"]["EG"]["Bad"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Bad"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_tmp_bad').innerHTML = mqttData["Raumtemp"]["EG"]["Bad"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Bad"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_hum_bad').innerHTML = mqttData["Raumtemp"]["EG"]["Bad"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Schlafen"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Schlafen"]["Heating"] == "false") htmlNode.getElementById('EG_schlafen_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('EG_schlafen_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Schlafen"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Schlafen"]["mode"] == "Overheating") htmlNode.getElementById('EG_schlafen_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('EG_schlafen_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Schlafen"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_pres_schlafen').innerHTML = Math.floor(mqttData["Raumtemp"]["EG"]["Schlafen"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Schlafen"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_tmp_schlafen').innerHTML = mqttData["Raumtemp"]["EG"]["Schlafen"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Schlafen"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_hum_schlafen').innerHTML = mqttData["Raumtemp"]["EG"]["Schlafen"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Florian"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Florian"]["Heating"] == "false") htmlNode.getElementById('EG_kizi_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('EG_kizi_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Florian"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Florian"]["mode"] == "Overheating") htmlNode.getElementById('EG_kizi_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('EG_kizi_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Florian"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_pres_kizi').innerHTML = Math.floor(mqttData["Raumtemp"]["EG"]["Florian"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Florian"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_tmp_kizi').innerHTML = mqttData["Raumtemp"]["EG"]["Florian"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Florian"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_hum_kizi').innerHTML = mqttData["Raumtemp"]["EG"]["Florian"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Magdalena"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Magdalena"]["Heating"] == "false") htmlNode.getElementById('EG_buero_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('EG_buero_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Magdalena"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["EG"]["Magdalena"]["mode"] == "Overheating") htmlNode.getElementById('EG_buero_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('EG_buero_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Magdalena"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_pres_buero').innerHTML = Math.floor(mqttData["Raumtemp"]["EG"]["Magdalena"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Magdalena"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_tmp_buero').innerHTML = mqttData["Raumtemp"]["EG"]["Magdalena"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["EG"]["Magdalena"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('EG_hum_buero').innerHTML = mqttData["Raumtemp"]["EG"]["Magdalena"]["rHum[%]"]+" %rF";
|
||||
//UG
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Kueche"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["UG"]["Kueche"]["Heating"] == "false") htmlNode.getElementById('UG_kueche_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('UG_kueche_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Kueche"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["UG"]["Kueche"]["mode"] == "Overheating") htmlNode.getElementById('UG_kueche_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('UG_kueche_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Kueche"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_pres_kueche').innerHTML = Math.floor(mqttData["Raumtemp"]["UG"]["Kueche"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Kueche"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_tmp_kueche').innerHTML = mqttData["Raumtemp"]["UG"]["Kueche"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Kueche"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_hum_kueche').innerHTML = mqttData["Raumtemp"]["UG"]["Kueche"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Buero"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["UG"]["Buero"]["Heating"] == "false") htmlNode.getElementById('UG_buero_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('UG_buero_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Buero"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["UG"]["Buero"]["mode"] == "Overheating") htmlNode.getElementById('UG_buero_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('UG_buero_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Buero"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_pres_buero').innerHTML = Math.floor(mqttData["Raumtemp"]["UG"]["Buero"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Buero"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_tmp_buero').innerHTML = mqttData["Raumtemp"]["UG"]["Buero"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Buero"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_hum_buero').innerHTML = mqttData["Raumtemp"]["UG"]["Buero"]["rHum[%]"]+" %rF";
|
||||
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Bad"]["Heating"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["UG"]["Bad"]["Heating"] == "false") htmlNode.getElementById('UG_bad_heater').setAttribute("display", "none");
|
||||
else htmlNode.getElementById('UG_bad_heater').setAttribute("display", "");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Bad"]["mode"]) != "undefined"){
|
||||
if(mqttData["Raumtemp"]["UG"]["Bad"]["mode"] == "Overheating") htmlNode.getElementById('UG_bad_buffer').setAttribute("display", "");
|
||||
else htmlNode.getElementById('UG_bad_buffer').setAttribute("display", "none");
|
||||
}
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Bad"]["Set Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_pres_bad').innerHTML = Math.floor(mqttData["Raumtemp"]["UG"]["Bad"]["Set Temp[degC]"])+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Bad"]["Temp[degC]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_tmp_bad').innerHTML = mqttData["Raumtemp"]["UG"]["Bad"]["Temp[degC]"]+" °C";
|
||||
if(typeof(mqttData["Raumtemp"]["UG"]["Bad"]["rHum[%]"]) != "undefined")
|
||||
htmlNode.getElementById('UG_hum_bad').innerHTML = mqttData["Raumtemp"]["UG"]["Bad"]["rHum[%]"]+" %rF";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var currentFloor = "OG";
|
||||
|
||||
function addClass(el, classNameToAdd){
|
||||
el.className += ' ' + classNameToAdd;
|
||||
}
|
||||
|
||||
function removeClass(el, classNameToRemove){
|
||||
var elClass = ' ' + el.className + ' ';
|
||||
while(elClass.indexOf(' ' + classNameToRemove + ' ') !== -1){
|
||||
elClass = elClass.replace(' ' + classNameToRemove + ' ', '');
|
||||
}
|
||||
el.className = elClass;
|
||||
}
|
||||
|
||||
function switchTab(newtab){
|
||||
newContent = document.getElementById(newtab);
|
||||
newTabBtn = document.getElementById(newtab+"-tab");
|
||||
removeClass(document.getElementById("actions-OG-tab"),"active");
|
||||
removeClass(document.getElementById("actions-EG-tab"),"active");
|
||||
removeClass(document.getElementById("actions-UG-tab"),"active");
|
||||
|
||||
removeClass(document.getElementById("actions-OG"),"active show");
|
||||
removeClass(document.getElementById("actions-EG"),"active show");
|
||||
removeClass(document.getElementById("actions-UG"),"active show");
|
||||
addClass(newTabBtn,"active");
|
||||
addClass(newContent,"active show");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function switchFloor(floor){
|
||||
if(currentFloor == floor)
|
||||
return;
|
||||
const targetIn = document.getElementById(floor+'_Info');
|
||||
const targetOut = document.getElementById(currentFloor+'_Info');
|
||||
var blendIn = new KeyframeEffect(
|
||||
targetIn, [{opacity: '0'},{opacity: '100'}],
|
||||
{
|
||||
duration: 500,
|
||||
easing: "ease-in-out",
|
||||
fill: "forwards",
|
||||
iterations: 1,
|
||||
}
|
||||
);
|
||||
var blendOut = new KeyframeEffect(
|
||||
targetOut, [{opacity: '100'},{opacity: '0'}],
|
||||
{
|
||||
duration: 500,
|
||||
easing: "ease-in-out",
|
||||
fill: "forwards",
|
||||
iterations: 1,
|
||||
}
|
||||
);
|
||||
var inAnim = new Animation(blendIn,document.timeline);
|
||||
var outAnim = new Animation(blendOut,document.timeline);
|
||||
targetIn.setAttribute("display","");
|
||||
outAnim.onfinish= (event) => {
|
||||
targetOut.setAttribute("display","none");
|
||||
};
|
||||
inAnim.play();
|
||||
outAnim.play();
|
||||
currentFloor = floor;
|
||||
}
|
||||
|
||||
|
||||
var modalEV = new bootstrap.Modal(document.getElementById('modalEV'), {
|
||||
keyboard: false
|
||||
});
|
||||
var offcanvas = new bootstrap.Offcanvas(document.getElementById('offcanvas'), {
|
||||
keyboard: false
|
||||
});
|
||||
|
||||
var mqttData = {};
|
||||
|
||||
function openHeaterSettings(heater){
|
||||
openModal(heater)
|
||||
}
|
||||
|
||||
document.addEventListener('readystatechange', function () {
|
||||
if (event.target.readyState === "complete") {
|
||||
homeMQTT.getMQTT();
|
||||
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>";
|
||||
}
|
||||
});
|
||||
|
||||
function loadingHTML(msg) {
|
||||
return "<div class='m-4'><div class='spinner-border' role='status'><span class='visually-hidden'>Loading...</span></div> " + msg + "</div>"
|
||||
}
|
||||
|
||||
function openModal(heater) {
|
||||
var contentURL = "./ajax/roomtemp.php?heater="+heater;
|
||||
let heaterMQTT = heater.toString().split("_");
|
||||
document.getElementById("modal-title").innerHTML = "Thermostat "+heater.replace("_"," ").replace("ue","ü").replace("ae","ä").replace("oe","ö");
|
||||
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");
|
||||
slider.oninput = function () {
|
||||
sliderPrcnt=(slider.value-10)*5;
|
||||
slider.style.setProperty("--background-size", `${sliderPrcnt}%`);
|
||||
marginValue = sliderPrcnt;
|
||||
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 + " °C";
|
||||
}
|
||||
|
||||
if(typeof(mqttData["Raumtemp"][heaterMQTT[0]][heaterMQTT[1]]["Set Temp[degC]"])!= "undefined")
|
||||
slider.setAttribute("value",mqttData["Raumtemp"][heaterMQTT[0]][heaterMQTT[1]]["Set Temp[degC]"]);
|
||||
else
|
||||
slider.setAttribute("value",10);
|
||||
slider.dispatchEvent(new Event('input'));
|
||||
})
|
||||
.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){
|
||||
setTimeout(function () { modalEV.hide() }, 700);
|
||||
alert(xmlhttp.responseText);
|
||||
}
|
||||
}
|
||||
const form = document.getElementById('modalEV').querySelector('form');
|
||||
post = "";
|
||||
// Get interesting form elements
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,861 @@
|
||||
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> " + 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;
|
||||
}
|
||||
Reference in New Issue
Block a user