mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-11 02:34:29 +05:00
642 lines
25 KiB
HTML
642 lines
25 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title data-i18n>dashboard.title</title>
|
|
<link rel="stylesheet" href="/static/app.css?{BUILD_TIME}" />
|
|
</head>
|
|
|
|
<body>
|
|
<header class="container">
|
|
<nav>
|
|
<ul>
|
|
<li>
|
|
<a href="/">
|
|
<div class="logo" data-i18n>logo</div>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<ul>
|
|
<li>
|
|
<select id="lang" aria-label="Lang">
|
|
<option value="en" selected>EN</option>
|
|
<option value="ru">RU</option>
|
|
</select>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="container">
|
|
<article>
|
|
<hgroup>
|
|
<h2 data-i18n>dashboard.name</h2>
|
|
<p></p>
|
|
</hgroup>
|
|
|
|
<div id="dashboard-busy" aria-busy="true"></div>
|
|
<div id="dashboard-container" class="hidden">
|
|
<details open>
|
|
<summary><b data-i18n>dashboard.section.control</b></summary>
|
|
<div class="grid">
|
|
<div class="thermostat" id="thermostat-heating">
|
|
<div class="thermostat-header" data-i18n>dashboard.thermostat.heating</div>
|
|
<div class="thermostat-temp">
|
|
<div class="thermostat-temp-target"><span id="tHeatTargetTemp"></span> <span class="tempUnit"></span></div>
|
|
<div class="thermostat-temp-current"><span data-i18n>dashboard.thermostat.temp.current</span>: <span id="tHeatCurrentTemp"></span> <span class="tempUnit"></span></div>
|
|
</div>
|
|
<div class="thermostat-minus"><button id="tHeatActionMinus" class="outline"><i class="icons-down"></i></button></div>
|
|
<div class="thermostat-plus"><button id="tHeatActionPlus" class="outline"><i class="icons-up"></i></button></div>
|
|
<div class="thermostat-control">
|
|
<input type="checkbox" role="switch" id="tHeatEnabled" value="true">
|
|
<label htmlFor="tHeatEnabled" data-i18n>dashboard.thermostat.enable</label>
|
|
|
|
<input type="checkbox" role="switch" id="tHeatTurbo" value="true">
|
|
<label htmlFor="tHeatTurbo" data-i18n>dashboard.thermostat.turbo</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="thermostat" id="thermostat-dhw">
|
|
<div class="thermostat-header" data-i18n>dashboard.thermostat.dhw</div>
|
|
<div class="thermostat-temp">
|
|
<div class="thermostat-temp-target"><span id="tDhwTargetTemp"></span> <span class="tempUnit"></span></div>
|
|
<div class="thermostat-temp-current"><span data-i18n>dashboard.thermostat.temp.current</span>: <span id="tDhwCurrentTemp"></span> <span class="tempUnit"></span></div>
|
|
</div>
|
|
<div class="thermostat-minus"><button class="outline" id="tDhwActionMinus"><i class="icons-down"></i></button></div>
|
|
<div class="thermostat-plus"><button class="outline" id="tDhwActionPlus"><i class="icons-up"></i></button></div>
|
|
<div class="thermostat-control">
|
|
<input type="checkbox" role="switch" id="tDhwEnabled" value="true">
|
|
<label htmlFor="tDhwEnabled" data-i18n>dashboard.thermostat.enable</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>dashboard.section.states</b></summary>
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mNetworkConnected</th>
|
|
<td><i class="mNetworkConnected"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mMqttConnected</th>
|
|
<td><i class="mMqttConnected"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mEmergencyState</th>
|
|
<td><i class="mEmergencyState"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mExtPumpState</th>
|
|
<td><i class="mExtPumpState"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mCascadeControlInput</th>
|
|
<td><i class="mCascadeControlInput"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mCascadeControlOutput</th>
|
|
<td><i class="mCascadeControlOutput"></i></td>
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sConnected</th>
|
|
<td><i class="sConnected"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sFlame</th>
|
|
<td><i class="sFlame"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sCooling</th>
|
|
<td><i class="sCooling"></i></td>
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sFaultActive</th>
|
|
<td><i class="sFaultActive"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sFaultCode</th>
|
|
<td><b class="sFaultCode"></b></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sDiagActive</th>
|
|
<td><i class="sDiagActive"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sDiagCode</th>
|
|
<td><b class="sDiagCode"></b></td>
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatEnabled</th>
|
|
<td><i class="mHeatEnabled"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatBlocking</th>
|
|
<td><i class="mHeatBlocking"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sHeatActive</th>
|
|
<td><i class="sHeatActive"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatTargetTemp</th>
|
|
<td><b class="mHeatTargetTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatSetpointTemp</th>
|
|
<td><b class="mHeatSetpointTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatCurrTemp</th>
|
|
<td><b class="mHeatCurrTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatRetTemp</th>
|
|
<td><b class="mHeatRetTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatIndoorTemp</th>
|
|
<td><b class="mHeatIndoorTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mHeatOutdoorTemp</th>
|
|
<td><b class="mHeatOutdoorTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mDhwEnabled</th>
|
|
<td><i class="mDhwEnabled"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.sDhwActive</th>
|
|
<td><i class="sDhwActive"></i></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mDhwTargetTemp</th>
|
|
<td><b class="mDhwTargetTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mDhwCurrTemp</th>
|
|
<td><b class="mDhwCurrTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row" data-i18n>dashboard.states.mDhwRetTemp</th>
|
|
<td><b class="mDhwRetTemp"></b> <span class="tempUnit"></span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>dashboard.section.sensors</b></summary>
|
|
<table>
|
|
<tbody class="sensors">
|
|
<tr class="sensor template hidden">
|
|
<td style="width: 1.35rem">
|
|
<span class="sStatusContainer">
|
|
<i class="sStatus"></i>
|
|
</span>
|
|
</td>
|
|
<th scope="row" class="sName"></th>
|
|
<td class="sValue"></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</details>
|
|
|
|
<hr />
|
|
|
|
<details>
|
|
<summary><b data-i18n>dashboard.section.diag</b></summary>
|
|
<pre><b>Vendor:</b> <span class="sVendor"></span>
|
|
<b>Member ID:</b> <span class="sMemberId"></span>
|
|
<b>Flags:</b> <span class="sFlags"></span>
|
|
<b>Type:</b> <span class="sType"></span>
|
|
<b>AppVersion:</b> <span class="sAppVersion"></span>
|
|
<b>OT version:</b> <span class="sProtocolVersion"></span>
|
|
<b>Modulation limits:</b> <span class="sModMin"></span>...<span class="sModMax"></span> %
|
|
<b>Power limits:</b> <span class="sPowerMin"></span>...<span class="sPowerMax"></span> kW
|
|
<b>Heating limits:</b> <span class="sHeatMinTemp"></span>...<span class="sHeatMaxTemp"></span> <span class="tempUnit"></span>
|
|
<b>DHW limits:</b> <span class="sDhwMinTemp"></span>...<span class="sDhwMaxTemp"></span> <span class="tempUnit"></span></pre>
|
|
</details>
|
|
</div>
|
|
</article>
|
|
</main>
|
|
|
|
<footer class="container">
|
|
<small>
|
|
<b>Made by Laxilef</b>
|
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary" data-i18n>nav.license</a>
|
|
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary" data-i18n>nav.source</a>
|
|
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary" data-i18n>nav.help</a>
|
|
• <a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary" data-i18n>nav.issues</a>
|
|
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary" data-i18n>nav.releases</a>
|
|
</small>
|
|
</footer>
|
|
|
|
<script src="/static/app.js?{BUILD_TIME}"></script>
|
|
<script>
|
|
let modifiedTime = null;
|
|
let noRegulators;
|
|
let prevSettings;
|
|
let newSettings = {
|
|
heating: {
|
|
enable: false,
|
|
turbo: false,
|
|
target: 0
|
|
},
|
|
dhw: {
|
|
enable: false,
|
|
target: 0
|
|
}
|
|
};
|
|
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
const lang = new Lang(document.getElementById('lang'));
|
|
lang.build();
|
|
|
|
document.querySelector('#tHeatActionMinus').addEventListener('click', (event) => {
|
|
if (!prevSettings) {
|
|
return;
|
|
}
|
|
|
|
newSettings.heating.target -= 0.5;
|
|
modifiedTime = Date.now();
|
|
|
|
let minTemp;
|
|
if (noRegulators) {
|
|
minTemp = prevSettings.heating.minTemp;
|
|
} else {
|
|
minTemp = prevSettings.system.unitSystem == 0 ? 5 : 41;
|
|
}
|
|
|
|
if (prevSettings && newSettings.heating.target < minTemp) {
|
|
newSettings.heating.target = minTemp;
|
|
}
|
|
|
|
setValue('#tHeatTargetTemp', newSettings.heating.target);
|
|
});
|
|
|
|
document.querySelector('#tHeatActionPlus').addEventListener('click', (event) => {
|
|
if (!prevSettings) {
|
|
return;
|
|
}
|
|
|
|
newSettings.heating.target += 0.5;
|
|
modifiedTime = Date.now();
|
|
|
|
let maxTemp;
|
|
if (noRegulators) {
|
|
maxTemp = prevSettings.heating.maxTemp;
|
|
} else {
|
|
maxTemp = prevSettings.system.unitSystem == 0 ? 30 : 86;
|
|
}
|
|
|
|
if (prevSettings && newSettings.heating.target > maxTemp) {
|
|
newSettings.heating.target = maxTemp;
|
|
}
|
|
|
|
setValue('#tHeatTargetTemp', newSettings.heating.target);
|
|
});
|
|
|
|
document.querySelector('#tDhwActionMinus').addEventListener('click', (event) => {
|
|
if (!prevSettings) {
|
|
return;
|
|
}
|
|
|
|
newSettings.dhw.target -= 1.0;
|
|
modifiedTime = Date.now();
|
|
|
|
if (newSettings.dhw.target < prevSettings.dhw.minTemp) {
|
|
newSettings.dhw.target = prevSettings.dhw.minTemp;
|
|
}
|
|
|
|
setValue('#tDhwTargetTemp', newSettings.dhw.target);
|
|
});
|
|
|
|
document.querySelector('#tDhwActionPlus').addEventListener('click', (event) => {
|
|
if (!prevSettings) {
|
|
return;
|
|
}
|
|
|
|
newSettings.dhw.target += 1.0;
|
|
modifiedTime = Date.now();
|
|
|
|
if (newSettings.dhw.target > prevSettings.dhw.maxTemp) {
|
|
newSettings.dhw.target = prevSettings.dhw.maxTemp;
|
|
}
|
|
|
|
setValue('#tDhwTargetTemp', newSettings.dhw.target);
|
|
});
|
|
|
|
document.querySelector('#tHeatEnabled').addEventListener('change', (event) => {
|
|
modifiedTime = Date.now();
|
|
newSettings.heating.enabled = event.currentTarget.checked;
|
|
});
|
|
|
|
document.querySelector('#tHeatTurbo').addEventListener('change', (event) => {
|
|
modifiedTime = Date.now();
|
|
newSettings.heating.turbo = event.currentTarget.checked;
|
|
});
|
|
|
|
document.querySelector('#tDhwEnabled').addEventListener('change', (event) => {
|
|
modifiedTime = Date.now();
|
|
newSettings.dhw.enabled = event.currentTarget.checked;
|
|
});
|
|
|
|
setTimeout(async function onLoadPage() {
|
|
let unitSystem = null;
|
|
|
|
if (modifiedTime) {
|
|
if ((Date.now() - modifiedTime) < 5000) {
|
|
setTimeout(onLoadPage, 1000);
|
|
return;
|
|
}
|
|
|
|
modifiedTime = null;
|
|
}
|
|
|
|
// settings
|
|
try {
|
|
let modified = prevSettings && (
|
|
(prevSettings.heating.enabled != newSettings.heating.enabled)
|
|
|| (prevSettings.heating.turbo != newSettings.heating.turbo)
|
|
|| (prevSettings.heating.target != newSettings.heating.target)
|
|
|| (prevSettings.opentherm.options.dhwSupport && prevSettings.dhw.enabled != newSettings.dhw.enabled)
|
|
|| (prevSettings.opentherm.options.dhwSupport && prevSettings.dhw.target != newSettings.dhw.target)
|
|
);
|
|
|
|
if (modified) {
|
|
console.log(newSettings);
|
|
}
|
|
|
|
let parameters = {
|
|
method: "GET",
|
|
cache: "no-cache",
|
|
credentials: "include"
|
|
};
|
|
|
|
if (modified) {
|
|
parameters.method = "POST";
|
|
parameters.body = JSON.stringify(newSettings);
|
|
}
|
|
|
|
const response = await fetch("/api/settings", parameters);
|
|
if (!response.ok) {
|
|
throw new Error('Response not valid');
|
|
}
|
|
|
|
const result = await response.json();
|
|
noRegulators = !result.opentherm.options.nativeHeatingControl && !result.equitherm.enabled && !result.pid.enabled;
|
|
prevSettings = result;
|
|
unitSystem = result.system.unitSystem;
|
|
newSettings.heating.enabled = result.heating.enabled;
|
|
newSettings.heating.turbo = result.heating.turbo;
|
|
newSettings.heating.target = result.heating.target;
|
|
newSettings.dhw.enabled = result.dhw.enabled;
|
|
newSettings.dhw.target = result.dhw.target;
|
|
|
|
if (result.opentherm.options.dhwSupport) {
|
|
show('#thermostat-dhw');
|
|
} else {
|
|
hide('#thermostat-dhw');
|
|
}
|
|
|
|
setCheckboxValue('#tHeatEnabled', result.heating.enabled);
|
|
setCheckboxValue('#tHeatTurbo', result.heating.turbo);
|
|
setValue('#tHeatTargetTemp', result.heating.target);
|
|
|
|
setCheckboxValue('#tDhwEnabled', result.dhw.enabled);
|
|
setValue('#tDhwTargetTemp', result.dhw.target);
|
|
|
|
setValue('.tempUnit', temperatureUnit(unitSystem));
|
|
setValue('.pressureUnit', pressureUnit(unitSystem));
|
|
setValue('.volumeUnit', volumeUnit(unitSystem));
|
|
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
|
|
// vars
|
|
try {
|
|
const response = await fetch("/api/vars", {
|
|
cache: "no-cache",
|
|
credentials: "include"
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Response not valid');
|
|
}
|
|
|
|
const result = await response.json();
|
|
|
|
// Graph
|
|
setValue('#tHeatCurrentTemp', result.master.heating.indoorTempControl
|
|
? result.master.heating.indoorTemp
|
|
: result.master.heating.currentTemp
|
|
);
|
|
setValue('#tDhwCurrentTemp', result.master.dhw.currentTemp);
|
|
|
|
|
|
// SLAVE
|
|
setValue('.sMemberId', result.slave.memberId);
|
|
setValue('.sVendor', memberIdToVendor(result.slave.memberId));
|
|
setValue('.sFlags', result.slave.flags);
|
|
setValue('.sType', result.slave.type);
|
|
setValue('.sAppVersion', result.slave.appVersion);
|
|
setValue('.sProtocolVersion', result.slave.protocolVersion);
|
|
|
|
setStatus(
|
|
'.sConnected',
|
|
result.slave.connected ? "success" : "error",
|
|
result.slave.connected ? "green" : "red"
|
|
);
|
|
setState('.sFlame', result.slave.flame);
|
|
setState('.sCooling', result.slave.cooling);
|
|
|
|
setValue('.sModMin', result.slave.modulation.min);
|
|
setValue('.sModMax', result.slave.modulation.max);
|
|
|
|
setValue('.sPowerMin', result.slave.power.min);
|
|
setValue('.sPowerMax', result.slave.power.max);
|
|
|
|
setState('.sHeatActive', result.slave.heating.active);
|
|
setValue('.sHeatMinTemp', result.slave.heating.minTemp);
|
|
setValue('.sHeatMaxTemp', result.slave.heating.maxTemp);
|
|
|
|
setState('.sDhwActive', result.slave.dhw.active);
|
|
setValue('.sDhwMinTemp', result.slave.dhw.minTemp);
|
|
setValue('.sDhwMaxTemp', result.slave.dhw.maxTemp);
|
|
|
|
setStatus(
|
|
'.sFaultActive',
|
|
result.slave.fault.active ? "success" : "error",
|
|
result.slave.fault.active ? "red" : "green"
|
|
);
|
|
setValue(
|
|
'.sFaultCode',
|
|
result.slave.fault.active
|
|
? `${result.slave.fault.code} (0x${dec2hex(result.slave.fault.code)})`
|
|
: "-"
|
|
);
|
|
|
|
setStatus(
|
|
'.sDiagActive',
|
|
result.slave.diag.active ? "success" : "error",
|
|
result.slave.diag.active ? "red" : "green"
|
|
);
|
|
setValue(
|
|
'.sDiagCode',
|
|
result.slave.diag.active
|
|
? `${result.slave.diag.code} (0x${dec2hex(result.slave.diag.code)})`
|
|
: "-"
|
|
);
|
|
|
|
|
|
// MASTER
|
|
setState('.mHeatEnabled', result.master.heating.enabled);
|
|
setStatus(
|
|
'.mHeatBlocking',
|
|
result.master.heating.blocking ? "success" : "error",
|
|
result.master.heating.blocking ? "red" : "green"
|
|
);
|
|
setState('.mHeatIndoorTempControl', result.master.heating.indoorTempControl);
|
|
setValue('.mHeatSetpointTemp', result.master.heating.setpointTemp);
|
|
setValue('.mHeatTargetTemp', result.master.heating.targetTemp);
|
|
setValue('.mHeatCurrTemp', result.master.heating.currentTemp);
|
|
setValue('.mHeatRetTemp', result.master.heating.returnTemp);
|
|
setValue('.mHeatIndoorTemp', result.master.heating.indoorTemp);
|
|
setValue('.mHeatOutdoorTemp', result.master.heating.outdoorTemp);
|
|
setValue('.mHeatMinTemp', result.master.heating.minTemp);
|
|
setValue('.mHeatMaxTemp', result.master.heating.maxTemp);
|
|
|
|
setState('.mDhwEnabled', result.master.dhw.enabled);
|
|
setValue('.mDhwTargetTemp', result.master.dhw.targetTemp);
|
|
setValue('.mDhwCurrTemp', result.master.dhw.currentTemp);
|
|
setValue('.mDhwRetTemp', result.master.dhw.returnTemp);
|
|
setValue('.mDhwMinTemp', result.master.dhw.minTemp);
|
|
setValue('.mDhwMaxTemp', result.master.dhw.maxTemp);
|
|
|
|
setStatus(
|
|
'.mNetworkConnected',
|
|
result.master.network.connected ? "success" : "error",
|
|
result.master.network.connected ? "green" : "red"
|
|
);
|
|
setState('.mMqttConnected', result.master.mqtt.connected);
|
|
setStatus(
|
|
'.mEmergencyState',
|
|
result.master.emergency.state ? "success" : "error",
|
|
result.master.emergency.state ? "red" : "green"
|
|
);
|
|
setState('.mExtPumpState', result.master.externalPump.state);
|
|
setState('.mCascadeControlInput', result.master.cascadeControl.input);
|
|
setState('.mCascadeControlOutput', result.master.cascadeControl.output);
|
|
|
|
setBusy('#dashboard-busy', '#dashboard-container', false);
|
|
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
|
|
// sensors
|
|
try {
|
|
const response = await fetch("/api/sensors?detailed=1", {
|
|
cache: "no-cache",
|
|
credentials: "include"
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Response not valid");
|
|
}
|
|
|
|
const container = document.querySelector(".sensors");
|
|
const templateNode = container.querySelector(".template");
|
|
const result = await response.json();
|
|
|
|
for (const sensorId in result) {
|
|
let sensorNode = container.querySelector(`.sensor[data-id='${sensorId}']`);
|
|
if (sensorNode) {
|
|
continue;
|
|
}
|
|
|
|
sensorNode = templateNode.cloneNode(true);
|
|
sensorNode.dataset.id = sensorId;
|
|
sensorNode.classList.remove("template");
|
|
container.appendChild(sensorNode);
|
|
}
|
|
|
|
for (const sensorId in result) {
|
|
const sensorNode = container.querySelector(`.sensor[data-id='${sensorId}']`);
|
|
if (!sensorNode) {
|
|
continue;
|
|
}
|
|
|
|
const sData = result[sensorId];
|
|
if (!sData.enabled || sData.purpose == 255) {
|
|
sensorNode.classList.toggle("hidden", true);
|
|
continue;
|
|
}
|
|
|
|
sensorNode.classList.toggle("hidden", false);
|
|
|
|
setStatus(
|
|
".sStatus",
|
|
sData.connected ? "success" : "error",
|
|
sData.connected ? "green" : "red",
|
|
sensorNode
|
|
);
|
|
setValue(".sName", sData.name, sensorNode);
|
|
setValue(".sValue", "", sensorNode);
|
|
|
|
const statusNode = sensorNode.querySelector(`.sStatusContainer`);
|
|
if (statusNode) {
|
|
statusNode.dataset.tooltip = `${sData.signalQuality}%`;
|
|
}
|
|
|
|
if (sData.value !== undefined) {
|
|
const sUnit = purposeUnit(sData.purpose, unitSystem);
|
|
appendValue(".sValue", `<b>${sData.value.toFixed(2)}</b> ${sUnit !== null ? sUnit : ``}`, `<br />`, sensorNode);
|
|
}
|
|
|
|
if (sData.temperature !== undefined) {
|
|
const sUnit = temperatureUnit(unitSystem);
|
|
appendValue(".sValue", `${i18n('dashboard.sensors.values.temp')}: <b>${sData.temperature.toFixed(2)}</b> ${sUnit !== null ? sUnit : ``}`, `<br />`, sensorNode);
|
|
}
|
|
|
|
if (sData.humidity !== undefined) {
|
|
appendValue(".sValue", `${i18n('dashboard.sensors.values.humidity')}: <b>${sData.humidity.toFixed(2)}</b> %`, `<br />`, sensorNode);
|
|
}
|
|
|
|
if (sData.battery !== undefined) {
|
|
appendValue(".sValue", `${i18n('dashboard.sensors.values.battery')}: <b>${sData.battery.toFixed(2)}</b> %`, `<br />`, sensorNode);
|
|
}
|
|
|
|
if (sData.rssi !== undefined) {
|
|
appendValue(".sValue", `${i18n('dashboard.sensors.values.rssi')}: <b>${sData.rssi.toFixed(0)}</b> ${i18n('dbm')}`, `<br />`, sensorNode);
|
|
}
|
|
}
|
|
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
|
|
setTimeout(onLoadPage, 10000);
|
|
}, 1000);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |