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" } }