modify filemode for linux

This commit is contained in:
2026-02-14 20:08:34 +01:00
parent 0e78302640
commit ae455dba20
393 changed files with 114401 additions and 114401 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1191 -1191
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
File diff suppressed because one or more lines are too long
+14 -14
View File
File diff suppressed because one or more lines are too long
+148 -148
View File
@@ -1,149 +1,149 @@
async function checkRegistration() {
try {
if (!window.fetch || !navigator.credentials || !navigator.credentials.create) {
throw new Error('Browser not supported.');
}
// get check args
let rep = await window.fetch('authServer.php?fn=getGetArgs' + getGetParams(), {method:'GET',cache:'no-cache'});
const getArgs = await rep.json();
// error handling
if (getArgs.success === false) {
throw new Error(getArgs.msg);
}
// replace binary base64 data with ArrayBuffer. a other way to do this
// is the reviver function of JSON.parse()
recursiveBase64StrToArrayBuffer(getArgs);
// check credentials with hardware
const cred = await navigator.credentials.get(getArgs);
// create object for transmission to server
const authenticatorAttestationResponse = {
id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null,
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null,
signature: cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null,
userHandle: cred.response.userHandle ? arrayBufferToBase64(cred.response.userHandle) : null
};
// send to server
rep = await window.fetch('authServer.php?fn=processGet' + getGetParams(), {
method:'POST',
body: JSON.stringify(authenticatorAttestationResponse),
cache:'no-cache'
});
const authenticatorAttestationServerResponse = await rep.json();
// check server response
if (authenticatorAttestationServerResponse.success) {
window.location.reload();
/// window.alert(authenticatorAttestationServerResponse.msg || 'login success');
} else {
throw new Error(authenticatorAttestationServerResponse.msg);
}
} catch (err) {
//reloadServerPreview();
window.alert(err.message || 'unknown error occured');
}
}
function queryFidoMetaDataService() {
window.fetch('authServer.php?fn=queryFidoMetaDataService' + getGetParams(), {method:'GET',cache:'no-cache'}).then(function(response) {
return response.json();
}).then(function(json) {
if (json.success) {
window.alert(json.msg);
} else {
throw new Error(json.msg);
}
}).catch(function(err) {
window.alert(err.message || 'unknown error occured');
});
}
/**
* convert RFC 1342-like base64 strings to array buffer
* @param {mixed} obj
* @returns {undefined}
*/
function recursiveBase64StrToArrayBuffer(obj) {
let prefix = '=?BINARY?B?';
let suffix = '?=';
if (typeof obj === 'object') {
for (let key in obj) {
if (typeof obj[key] === 'string') {
let str = obj[key];
if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) {
str = str.substring(prefix.length, str.length - suffix.length);
let binary_string = window.atob(str);
let len = binary_string.length;
let bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
obj[key] = bytes.buffer;
}
} else {
recursiveBase64StrToArrayBuffer(obj[key]);
}
}
}
}
/**
* Convert a ArrayBuffer to Base64
* @param {ArrayBuffer} buffer
* @returns {String}
*/
function arrayBufferToBase64(buffer) {
let binary = '';
let bytes = new Uint8Array(buffer);
let len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa(binary);
}
/**
* Get URL parameter
* @returns {String}
*/
function getGetParams() {
let url = '';
url += '&apple=1';
url += '&yubico=1';
url += '&solo=1';
url += '&hypersecu=1';
url += '&google=1';
url += '&microsoft=1';
url += '&mds=1';
url += '&requireResidentKey=0';
url += '&type_usb=1';
url += '&type_nfc=1';
url += '&type_ble=1';
url += '&type_int=1';
url += '&type_hybrid=1';
url += '&fmt_android-key=1';
url += '&fmt_android-safetynet=1';
url += '&fmt_apple=1';
url += '&fmt_fido-u2f=1';
url += '&fmt_none=0' ;
url += '&fmt_packed=1';
url += '&fmt_tpm=1';
url += '&userVerification=discouraged';
return url;
async function checkRegistration() {
try {
if (!window.fetch || !navigator.credentials || !navigator.credentials.create) {
throw new Error('Browser not supported.');
}
// get check args
let rep = await window.fetch('authServer.php?fn=getGetArgs' + getGetParams(), {method:'GET',cache:'no-cache'});
const getArgs = await rep.json();
// error handling
if (getArgs.success === false) {
throw new Error(getArgs.msg);
}
// replace binary base64 data with ArrayBuffer. a other way to do this
// is the reviver function of JSON.parse()
recursiveBase64StrToArrayBuffer(getArgs);
// check credentials with hardware
const cred = await navigator.credentials.get(getArgs);
// create object for transmission to server
const authenticatorAttestationResponse = {
id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null,
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null,
signature: cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null,
userHandle: cred.response.userHandle ? arrayBufferToBase64(cred.response.userHandle) : null
};
// send to server
rep = await window.fetch('authServer.php?fn=processGet' + getGetParams(), {
method:'POST',
body: JSON.stringify(authenticatorAttestationResponse),
cache:'no-cache'
});
const authenticatorAttestationServerResponse = await rep.json();
// check server response
if (authenticatorAttestationServerResponse.success) {
window.location.reload();
/// window.alert(authenticatorAttestationServerResponse.msg || 'login success');
} else {
throw new Error(authenticatorAttestationServerResponse.msg);
}
} catch (err) {
//reloadServerPreview();
window.alert(err.message || 'unknown error occured');
}
}
function queryFidoMetaDataService() {
window.fetch('authServer.php?fn=queryFidoMetaDataService' + getGetParams(), {method:'GET',cache:'no-cache'}).then(function(response) {
return response.json();
}).then(function(json) {
if (json.success) {
window.alert(json.msg);
} else {
throw new Error(json.msg);
}
}).catch(function(err) {
window.alert(err.message || 'unknown error occured');
});
}
/**
* convert RFC 1342-like base64 strings to array buffer
* @param {mixed} obj
* @returns {undefined}
*/
function recursiveBase64StrToArrayBuffer(obj) {
let prefix = '=?BINARY?B?';
let suffix = '?=';
if (typeof obj === 'object') {
for (let key in obj) {
if (typeof obj[key] === 'string') {
let str = obj[key];
if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) {
str = str.substring(prefix.length, str.length - suffix.length);
let binary_string = window.atob(str);
let len = binary_string.length;
let bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
obj[key] = bytes.buffer;
}
} else {
recursiveBase64StrToArrayBuffer(obj[key]);
}
}
}
}
/**
* Convert a ArrayBuffer to Base64
* @param {ArrayBuffer} buffer
* @returns {String}
*/
function arrayBufferToBase64(buffer) {
let binary = '';
let bytes = new Uint8Array(buffer);
let len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa(binary);
}
/**
* Get URL parameter
* @returns {String}
*/
function getGetParams() {
let url = '';
url += '&apple=1';
url += '&yubico=1';
url += '&solo=1';
url += '&hypersecu=1';
url += '&google=1';
url += '&microsoft=1';
url += '&mds=1';
url += '&requireResidentKey=0';
url += '&type_usb=1';
url += '&type_nfc=1';
url += '&type_ble=1';
url += '&type_int=1';
url += '&type_hybrid=1';
url += '&fmt_android-key=1';
url += '&fmt_android-safetynet=1';
url += '&fmt_apple=1';
url += '&fmt_fido-u2f=1';
url += '&fmt_none=0' ;
url += '&fmt_packed=1';
url += '&fmt_tpm=1';
url += '&userVerification=discouraged';
return url;
}
+6 -6
View File
File diff suppressed because one or more lines are too long
+13 -13
View File
File diff suppressed because one or more lines are too long
+7 -7
View File
@@ -1,7 +1,7 @@
/*!
* chartjs-adapter-luxon v1.3.1
* https://www.chartjs.org
* (c) 2023 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("chart.js"),require("luxon")):"function"==typeof define&&define.amd?define(["chart.js","luxon"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Chart,e.luxon)}(this,(function(e,t){"use strict";const n={datetime:t.DateTime.DATETIME_MED_WITH_SECONDS,millisecond:"h:mm:ss.SSS a",second:t.DateTime.TIME_WITH_SECONDS,minute:t.DateTime.TIME_SIMPLE,hour:{hour:"numeric"},day:{day:"numeric",month:"short"},week:"DD",month:{month:"short",year:"numeric"},quarter:"'Q'q - yyyy",year:{year:"numeric"}};e._adapters._date.override({_id:"luxon",_create:function(e){return t.DateTime.fromMillis(e,this.options)},init(e){this.options.locale||(this.options.locale=e.locale)},formats:function(){return n},parse:function(e,n){const i=this.options,r=typeof e;return null===e||"undefined"===r?null:("number"===r?e=this._create(e):"string"===r?e="string"==typeof n?t.DateTime.fromFormat(e,n,i):t.DateTime.fromISO(e,i):e instanceof Date?e=t.DateTime.fromJSDate(e,i):"object"!==r||e instanceof t.DateTime||(e=t.DateTime.fromObject(e,i)),e.isValid?e.valueOf():null)},format:function(e,t){const n=this._create(e);return"string"==typeof t?n.toFormat(t):n.toLocaleString(t)},add:function(e,t,n){const i={};return i[n]=t,this._create(e).plus(i).valueOf()},diff:function(e,t,n){return this._create(e).diff(this._create(t)).as(n).valueOf()},startOf:function(e,t,n){if("isoWeek"===t){n=Math.trunc(Math.min(Math.max(0,n),6));const t=this._create(e);return t.minus({days:(t.weekday-n+7)%7}).startOf("day").valueOf()}return t?this._create(e).startOf(t).valueOf():e},endOf:function(e,t){return this._create(e).endOf(t).valueOf()}})}));
/*!
* chartjs-adapter-luxon v1.3.1
* https://www.chartjs.org
* (c) 2023 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("chart.js"),require("luxon")):"function"==typeof define&&define.amd?define(["chart.js","luxon"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Chart,e.luxon)}(this,(function(e,t){"use strict";const n={datetime:t.DateTime.DATETIME_MED_WITH_SECONDS,millisecond:"h:mm:ss.SSS a",second:t.DateTime.TIME_WITH_SECONDS,minute:t.DateTime.TIME_SIMPLE,hour:{hour:"numeric"},day:{day:"numeric",month:"short"},week:"DD",month:{month:"short",year:"numeric"},quarter:"'Q'q - yyyy",year:{year:"numeric"}};e._adapters._date.override({_id:"luxon",_create:function(e){return t.DateTime.fromMillis(e,this.options)},init(e){this.options.locale||(this.options.locale=e.locale)},formats:function(){return n},parse:function(e,n){const i=this.options,r=typeof e;return null===e||"undefined"===r?null:("number"===r?e=this._create(e):"string"===r?e="string"==typeof n?t.DateTime.fromFormat(e,n,i):t.DateTime.fromISO(e,i):e instanceof Date?e=t.DateTime.fromJSDate(e,i):"object"!==r||e instanceof t.DateTime||(e=t.DateTime.fromObject(e,i)),e.isValid?e.valueOf():null)},format:function(e,t){const n=this._create(e);return"string"==typeof t?n.toFormat(t):n.toLocaleString(t)},add:function(e,t,n){const i={};return i[n]=t,this._create(e).plus(i).valueOf()},diff:function(e,t,n){return this._create(e).diff(this._create(t)).as(n).valueOf()},startOf:function(e,t,n){if("isoWeek"===t){n=Math.trunc(Math.min(Math.max(0,n),6));const t=this._create(e);return t.minus({days:(t.weekday-n+7)%7}).startOf("day").valueOf()}return t?this._create(e).startOf(t).valueOf():e},endOf:function(e,t){return this._create(e).endOf(t).valueOf()}})}));
File diff suppressed because one or more lines are too long
+7 -7
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+6 -6
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
/*! https://github.com/FranBar1966/bootstrap-5-modal-dynamic - License in the terms described in the LICENSE file */
/*! https://github.com/FranBar1966/bootstrap-5-modal-dynamic - License in the terms described in the LICENSE file */
function startDynamicModal(){document.body.removeEventListener("click",dynamicModalHandler),document.body.addEventListener("click",dynamicModalHandler)}function dynamicModalHandler(e){const t=e.target.closest(".modal-dynamic");if(!t)return;e.target.closest("a")&&e.preventDefault();const a=e.target.getAttribute("href"),d=e.target.dataset.template||"#modalTemplate";let o=document.querySelector(a);if(!o){const e=document.querySelector(d);e&&(o=e.cloneNode(!0),o.id=a.substring(1),document.body.appendChild(o))}if(!o)return;const n=e.target.dataset.class,r=e.target.dataset.title,s=e.target.dataset.header,l=e.target.dataset.noheader,c=e.target.dataset.url,i=e.target.dataset.footer,u=e.target.dataset.nofooter,m=e.target.dataset.width||"",y=e.target.dataset.backdrop||"false",h=!e.target.dataset.keyboard||"true"===e.target.dataset.keyboard;if(n&&o.classList.add(...n.split(" ")),s){const e=o.querySelector(".modal-header"),t=document.querySelector(s);e&&t&&(e.innerHTML=t.innerHTML)}if(l){const e=o.querySelector(".modal-header");e&&e.classList.add("hidden","d-none")}if(r){const e=o.querySelector(".modal-title");e&&(e.innerHTML=r)}if(i){const e=o.querySelector(".modal-footer"),t=document.querySelector(i);e&&t&&(e.innerHTML=t.innerHTML)}if(u){const e=o.querySelector(".modal-footer");e&&e.classList.add("hidden","d-none")}if(m){const e=o.querySelector(".modal-dialog");if(e){const t=isNaN(m)||""===m?m:m+"px";e.style.maxWidth=t,e.style.width="auto"}}let f=bootstrap.Modal.getInstance(o);f||(f=new bootstrap.Modal(o,{keyboard:h,backdrop:y})),o.addEventListener("hidden.bs.modal",e=>{o.remove()}),o.addEventListener("shown.bs.modal",e=>{o.focus()}),f.show();const g=o.querySelector(".modal-body");if(c.startsWith("#")){const e=document.querySelector(c);g.innerHTML=e?e.innerHTML:"ERROR: Content not found"}else fetch(c,{method:"GET",headers:{"X-Requested-From-Modal":a.substring(1),"Requested-With-Ajax":"ajax"}}).then(e=>e.text()).then(e=>{g.innerHTML=e,window.dispatchEvent(new CustomEvent("neutralFetchCompleted",{detail:{element:o,url:c}}))}).catch(e=>{g.innerHTML=e.message,window.dispatchEvent(new CustomEvent("neutralFetchError",{detail:{element:o,url:c}}))})}startDynamicModal(),window.addEventListener("neutralFetchCompleted",()=>{startDynamicModal()});
+23895 -23895
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6 -6
View File
File diff suppressed because one or more lines are too long
+294 -294
View File
@@ -1,295 +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}">&gt;</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}">&gt;</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}">&gt;</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;
});
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}">&gt;</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}">&gt;</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}">&gt;</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;
});
}
+235 -235
View File
@@ -1,236 +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"
}
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"
}
}
+198 -198
View File
@@ -1,199 +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"
}
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"
}
}
+426 -426
View File
@@ -1,427 +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>&nbsp;&nbsp;&nbsp;" + 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;
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>&nbsp;&nbsp;&nbsp;" + 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;
}
+860 -860
View File
File diff suppressed because it is too large Load Diff