chore: html files moved to src_data dir; compression files

This commit is contained in:
Yurii
2024-04-12 04:13:44 +03:00
parent 63228baebd
commit 1cd8c6a336
14 changed files with 0 additions and 0 deletions

415
src_data/dashboard.html Normal file
View File

@@ -0,0 +1,415 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Dashboard - OpenTherm Gateway</title>
<link rel="stylesheet" href="/static/pico.min.css">
<link rel="stylesheet" href="/static/app.css"/>
</head>
<body>
<header class="container">
<nav>
<ul>
<li><a href="/"><div class="logo">OpenTherm Gateway</div></a></li>
</ul>
<ul>
<li><a href="https://github.com/Laxilef/OTGateway/wiki" role="button" class="secondary" target="_blank">Help</a></li>
</ul>
</nav>
</header>
<main class="container">
<article>
<hgroup>
<h2>Dashboard</h2>
<p></p>
</hgroup>
<div id="dashboard-busy" aria-busy="true"></div>
<div id="dashboard-container" class="hidden">
<details open>
<summary><b>Control</b></summary>
<div class="grid">
<div class="thermostat" id="thermostat-heating">
<div class="thermostat-header">Heating</div>
<div class="thermostat-temp">
<div class="thermostat-temp-target"><span id="thermostat-heating-target"></span> <span class="temp-unit"></span></div>
<div class="thermostat-temp-current">Current: <span id="thermostat-heating-current"></span> <span class="temp-unit"></span></div>
</div>
<div class="thermostat-minus"><button id="thermostat-heating-minus" class="outline"><b>-</b></button></div>
<div class="thermostat-plus"><button id="thermostat-heating-plus" class="outline"><b>+</b></button></div>
<div class="thermostat-control">
<input type="checkbox" role="switch" id="thermostat-heating-enabled" value="true">
<label htmlFor="thermostat-heating-enabled">Enable</label>
<input type="checkbox" role="switch" id="thermostat-heating-turbo" value="true">
<label htmlFor="thermostat-heating-turbo">Turbo mode</label>
</div>
</div>
<div class="thermostat" id="thermostat-dhw">
<div class="thermostat-header">DHW</div>
<div class="thermostat-temp">
<div class="thermostat-temp-target"><span id="thermostat-dhw-target"></span> <span class="temp-unit"></span></div>
<div class="thermostat-temp-current">Current: <span id="thermostat-dhw-current"></span> <span class="temp-unit"></span></div>
</div>
<div class="thermostat-minus"><button class="outline" id="thermostat-dhw-minus"><b>-</b></button></div>
<div class="thermostat-plus"><button class="outline" id="thermostat-dhw-plus"><b>+</b></button></div>
<div class="thermostat-control">
<input type="checkbox" role="switch" id="thermostat-dhw-enabled" value="true">
<label htmlFor="thermostat-dhw-enabled">Enable</label>
</div>
</div>
</div>
</details>
<hr />
<details>
<summary><b>States and sensors</b></summary>
<table>
<tbody>
<tr>
<th scope="row">OpenTherm connected:</th>
<td><input type="radio" id="ot-connected" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">MQTT connected:</th>
<td><input type="radio" id="mqtt-connected" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">Emergency:</th>
<td><input type="radio" id="ot-emergency" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">Heating:</th>
<td><input type="radio" id="ot-heating" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">DHW:</th>
<td><input type="radio" id="ot-dhw" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">Flame:</th>
<td><input type="radio" id="ot-flame" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">Fault:</th>
<td><input type="radio" id="ot-fault" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">Diagnostic:</th>
<td><input type="radio" id="ot-diagnostic" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">External pump:</th>
<td><input type="radio" id="ot-external-pump" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">Modulation:</th>
<td><b id="ot-modulation"></b> %</td>
</tr>
<tr>
<th scope="row">Pressure:</th>
<td><b id="ot-pressure"></b> <span class="pressure-unit"></span></td>
</tr>
<tr>
<th scope="row">DHW flow rate:</th>
<td><b id="ot-dhw-flow-rate"></b> <span class="volume-unit"></span>/min</td>
</tr>
<tr>
<th scope="row">Fault code:</th>
<td><b id="ot-fault-code"></b></td>
</tr>
<tr>
<th scope="row">Indoor temp:</th>
<td><b id="indoor-temp"></b> <span class="temp-unit"></span></td>
</tr>
<tr>
<th scope="row">Outdoor temp:</th>
<td><b id="outdoor-temp"></b> <span class="temp-unit"></span></td>
</tr>
<tr>
<th scope="row">Heating temp:</th>
<td><b id="heating-temp"></b> <span class="temp-unit"></span></td>
</tr>
<tr>
<th scope="row">Heating setpoint temp:</th>
<td><b id="heating-setpoint-temp"></b> <span class="temp-unit"></span></td>
</tr>
<tr>
<th scope="row">Heating return temp:</th>
<td><b id="heating-return-temp"></b> <span class="temp-unit"></span></td>
</tr>
<tr>
<th scope="row">DHW temp:</th>
<td><b id="dhw-temp"></b> <span class="temp-unit"></span></td>
</tr>
<tr>
<th scope="row">Exhaust temp:</th>
<td><b id="exhaust-temp"></b> <span class="temp-unit"></span></td>
</tr>
</tbody>
</table>
</details>
<hr />
<details>
<summary><b>OpenTherm diagnostic</b></summary>
<pre><b>Vendor:</b> <span id="slave-vendor"></span>
<b>Member ID:</b> <span id="slave-member-id"></span>
<b>Flags:</b> <span id="slave-flags"></span>
<b>Type:</b> <span id="slave-type"></span>
<b>Version:</b> <span id="slave-version"></span>
<b>OT version:</b> <span id="slave-ot-version"></span>
<b>Heating limits:</b> <span id="heating-min-temp"></span>...<span id="heating-max-temp"></span> <span class="temp-unit"></span>
<b>DHW limits:</b> <span id="dhw-min-temp"></span>...<span id="dhw-max-temp"></span> <span class="temp-unit"></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">License</a>
<a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
<a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
<a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
<a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
</small>
</footer>
<script src="/static/app.js"></script>
<script>
let modifiedTime = null;
let noRegulators;
let prevSettings;
let newSettings = {
heating: {
enable: false,
turbo: false,
target: 0
},
dhw: {
enable: false,
target: 0
}
};
window.onload = async function () {
document.querySelector('#thermostat-heating-minus').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('#thermostat-heating-target', newSettings.heating.target);
});
document.querySelector('#thermostat-heating-plus').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('#thermostat-heating-target', newSettings.heating.target);
});
document.querySelector('#thermostat-dhw-minus').addEventListener('click', (event) => {
if (!prevSettings) {
return;
}
newSettings.dhw.target -= 1;
modifiedTime = Date.now();
if (newSettings.dhw.target < prevSettings.dhw.minTemp) {
newSettings.dhw.target = prevSettings.dhw.minTemp;
}
setValue('#thermostat-dhw-target', newSettings.dhw.target);
});
document.querySelector('#thermostat-dhw-plus').addEventListener('click', (event) => {
if (!prevSettings) {
return;
}
newSettings.dhw.target += 1;
modifiedTime = Date.now();
if (newSettings.dhw.target > prevSettings.dhw.maxTemp) {
newSettings.dhw.target = prevSettings.dhw.maxTemp;
}
setValue('#thermostat-dhw-target', newSettings.dhw.target);
});
document.querySelector('#thermostat-heating-enabled').addEventListener('change', (event) => {
modifiedTime = Date.now();
newSettings.heating.enable = event.currentTarget.checked;
});
document.querySelector('#thermostat-heating-turbo').addEventListener('change', (event) => {
modifiedTime = Date.now();
newSettings.heating.turbo = event.currentTarget.checked;
});
document.querySelector('#thermostat-dhw-enabled').addEventListener('change', (event) => {
modifiedTime = Date.now();
newSettings.heating.dhw = event.currentTarget.checked;
});
setTimeout(async function onLoadPage() {
if (modifiedTime) {
if ((Date.now() - modifiedTime) < 5000) {
setTimeout(onLoadPage, 1000);
return;
}
modifiedTime = null;
}
// settings
try {
let modified = prevSettings && (
(prevSettings.heating.enable != newSettings.heating.enable)
|| (prevSettings.heating.turbo != newSettings.heating.turbo)
|| (prevSettings.heating.target != newSettings.heating.target)
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.enable != newSettings.dhw.enable)
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.target != newSettings.dhw.target)
);
if (modified) {
console.log(newSettings);
}
let parameters = {cache: 'no-cache'};
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.equitherm.enable && !result.pid.enable;
prevSettings = result;
newSettings.heating.enable = result.heating.enable;
newSettings.heating.turbo = result.heating.turbo;
newSettings.heating.target = result.heating.target;
newSettings.dhw.enable = result.dhw.enable;
newSettings.dhw.target = result.dhw.target;
if (result.opentherm.dhwPresent) {
show('#thermostat-dhw');
} else {
hide('#thermostat-dhw');
}
setCheckboxValue('#thermostat-heating-enabled', result.heating.enable);
setCheckboxValue('#thermostat-heating-turbo', result.heating.turbo);
setValue('#thermostat-heating-target', result.heating.target);
setCheckboxValue('#thermostat-dhw-enabled', result.dhw.enable);
setValue('#thermostat-dhw-target', result.dhw.target);
setValue('.temp-unit', temperatureUnit(result.system.unitSystem));
setValue('.pressure-unit', pressureUnit(result.system.unitSystem));
setValue('.volume-unit', volumeUnit(result.system.unitSystem));
} catch (error) {
console.log(error);
}
// vars
try {
const response = await fetch('/api/vars', { cache: 'no-cache' });
if (!response.ok) {
throw new Error('Response not valid');
}
const result = await response.json();
setValue('#thermostat-heating-current', noRegulators ? result.temperatures.heating : result.temperatures.indoor);
setValue('#thermostat-dhw-current', result.temperatures.dhw);
setState('#ot-connected', result.states.otStatus);
setState('#ot-emergency', result.states.emergency);
setState('#ot-heating', result.states.heating);
setState('#ot-dhw', result.states.dhw);
setState('#ot-flame', result.states.flame);
setState('#ot-fault', result.states.fault);
setState('#ot-diagnostic', result.states.diagnostic);
setState('#ot-external-pump', result.states.externalPump);
setState('#mqtt-connected', result.states.mqtt);
setValue('#ot-modulation', result.sensors.modulation);
setValue('#ot-pressure', result.sensors.pressure);
setValue('#ot-dhw-flow-rate', result.sensors.dhwFlowRate);
setValue('#ot-fault-code', result.sensors.faultCode ? ("E" + result.sensors.faultCode) : "-");
setValue('#indoor-temp', result.temperatures.indoor);
setValue('#outdoor-temp', result.temperatures.outdoor);
setValue('#heating-temp', result.temperatures.heating);
setValue('#heating-return-temp', result.temperatures.heatingReturn);
setValue('#dhw-temp', result.temperatures.dhw);
setValue('#exhaust-temp', result.temperatures.exhaust);
setValue('#heating-min-temp', result.parameters.heatingMinTemp);
setValue('#heating-max-temp', result.parameters.heatingMaxTemp);
setValue('#heating-setpoint-temp', result.parameters.heatingSetpoint);
setValue('#dhw-min-temp', result.parameters.dhwMinTemp);
setValue('#dhw-max-temp', result.parameters.dhwMaxTemp);
setValue('#slave-member-id', result.parameters.slaveMemberId);
setValue('#slave-vendor', memberIdToVendor(result.parameters.slaveMemberId));
setValue('#slave-flags', result.parameters.slaveFlags);
setValue('#slave-type', result.parameters.slaveType);
setValue('#slave-version', result.parameters.slaveVersion);
setValue('#slave-ot-version', result.parameters.slaveOtVersion);
setBusy('#dashboard-busy', '#dashboard-container', false);
} catch (error) {
console.log(error);
}
setTimeout(onLoadPage, 10000);
}, 1000);
};
</script>
</body>
</html>

178
src_data/index.html Normal file
View File

@@ -0,0 +1,178 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OpenTherm Gateway</title>
<link rel="stylesheet" href="/static/pico.min.css">
<link rel="stylesheet" href="/static/app.css"/>
</head>
<body>
<header class="container">
<nav>
<ul>
<li><a href="/"><div class="logo">OpenTherm Gateway</div></a></li>
</ul>
<ul>
<li><a href="https://github.com/Laxilef/OTGateway/wiki" role="button" class="secondary" target="_blank">Help</a></li>
</ul>
</nav>
</header>
<main class="container">
<article>
<div>
<hgroup>
<h2>Network</h2>
<p></p>
</hgroup>
<div id="main-busy" aria-busy="true"></div>
<table id="main-table" class="hidden">
<tbody>
<tr>
<th scope="row">Hostname:</th>
<td><b id="network-hostname"></b></td>
</tr>
<tr>
<th scope="row">MAC:</th>
<td><b id="network-mac"></b></td>
</tr>
<tr>
<th scope="row">Connected:</th>
<td><input type="radio" id="network-connected" aria-invalid="false" checked disabled /></td>
</tr>
<tr>
<th scope="row">SSID:</th>
<td><b id="network-ssid"></b></td>
</tr>
<tr>
<th scope="row">Signal:</th>
<td><b id="network-signal"></b> %</td>
</tr>
<tr>
<th scope="row">IP:</th>
<td><b id="network-ip"></b></td>
</tr>
<tr>
<th scope="row">Subnet:</th>
<td><b id="network-subnet"></b></td>
</tr>
<tr>
<th scope="row">Gateway:</th>
<td><b id="network-gateway"></b></td>
</tr>
<tr>
<th scope="row">DNS:</th>
<td><b id="network-dns"></b></td>
</tr>
</tbody>
</table>
<div class="grid">
<a href="/network.html" role="button">Network settings</a>
</div>
</div>
</article>
<article>
<div>
<hgroup>
<h2>System</h2>
<p></p>
</hgroup>
<div id="system-busy" aria-busy="true"></div>
<table id="system-table" class="hidden">
<tbody>
<tr>
<th scope="row">Version:</th>
<td><b id="version"></b></td>
</tr>
<tr>
<th scope="row">Build date:</th>
<td><b id="build-date"></b></td>
</tr>
<tr>
<th scope="row">Uptime:</th>
<td><b id="uptime-days"></b> days, <b id="uptime-hours"></b> hours, <b id="uptime-min"></b> min., <b id="uptime-sec"></b> sec.</td>
</tr>
<tr>
<th scope="row">Free memory:</th>
<td><b id="free-heap"></b> of <b id="total-heap"></b> bytes (min: <b id="min-free-heap"></b> bytes)<br />max free block: <b id="max-free-block-heap"></b> bytes (min: <b id="min-max-free-block-heap"></b> bytes)</td>
</tr>
<tr>
<th scope="row">Last reset reason:</th>
<td><b id="reset-reason"></b></td>
</tr>
</tbody>
</table>
<div class="grid">
<a href="/dashboard.html" role="button">Dashboard</a>
<a href="/settings.html" role="button">Settings</a>
<a href="/upgrade.html" role="button">Upgrade</a>
<a href="/restart.html" role="button" class="secondary restart">Restart</a>
</div>
</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">License</a>
<a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
<a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
<a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
<a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
</small>
</footer>
<script src="/static/app.js"></script>
<script>
window.onload = async function () {
setTimeout(async function onLoadPage() {
try {
const response = await fetch('/api/info', { cache: 'no-cache' });
if (!response.ok) {
throw new Error('Response not valid');
}
const result = await response.json();
setValue('#network-hostname', result.network.hostname);
setValue('#network-mac', result.network.mac);
setState('#network-connected', result.network.connected);
setValue('#network-ssid', result.network.ssid);
setValue('#network-signal', result.network.signalQuality);
setValue('#network-ip', result.network.ip);
setValue('#network-subnet', result.network.subnet);
setValue('#network-gateway', result.network.gateway);
setValue('#network-dns', result.network.dns);
setBusy('#main-busy', '#main-table', false);
setValue('#version', result.system.version);
setValue('#build-date', result.system.buildDate);
setValue('#uptime', result.system.uptime);
setValue('#uptime-days', Math.floor(result.system.uptime / 86400));
setValue('#uptime-hours', Math.floor(result.system.uptime % 86400 / 3600));
setValue('#uptime-min', Math.floor(result.system.uptime % 3600 / 60));
setValue('#uptime-sec', Math.floor(result.system.uptime % 60));
setValue('#total-heap', result.system.totalHeap);
setValue('#free-heap', result.system.freeHeap);
setValue('#min-free-heap', result.system.minFreeHeap);
setValue('#max-free-block-heap', result.system.maxFreeBlockHeap);
setValue('#min-max-free-block-heap', result.system.minMaxFreeBlockHeap);
setValue('#reset-reason', result.system.resetReason);
setBusy('#system-busy', '#system-table', false);
} catch (error) {
console.log(error);
}
setTimeout(onLoadPage, 10000);
}, 1000);
};
</script>
</body>
</html>

207
src_data/network.html Normal file
View File

@@ -0,0 +1,207 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Network - OpenTherm Gateway</title>
<link rel="stylesheet" href="/static/pico.min.css">
<link rel="stylesheet" href="/static/app.css" />
</head>
<body>
<header class="container">
<nav>
<ul>
<li><a href="/"><div class="logo">OpenTherm Gateway</div></a></li>
</ul>
<ul>
<li><a href="https://github.com/Laxilef/OTGateway/wiki" role="button" class="secondary" target="_blank">Help</a></li>
</ul>
</nav>
</header>
<main class="container">
<article>
<div>
<hgroup>
<h2>Network settings</h2>
<p></p>
</hgroup>
<div id="network-settings-busy" aria-busy="true"></div>
<form action="/api/network/settings" id="network-settings" class="hidden">
<label for="network-hostname">
Hostname
<input type="text" id="network-hostname" name="hostname" maxlength="24" pattern="[A-Za-z0-9]+[A-Za-z0-9\-]+[A-Za-z0-9]+" required>
</label>
<label for="network-use-dhcp">
<input type="checkbox" id="network-use-dhcp" name="useDhcp" value="true">
Use DHCP
</label>
<br />
<hr />
<label for="network-static-ip">
Static IP:
<input type="text" id="network-static-ip" name="staticConfig[ip]" value="true" maxlength="16" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" required>
</label>
<label for="network-static-gateway">
Static gateway:
<input type="text" id="network-static-gateway" name="staticConfig[gateway]" maxlength="16" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" required>
</label>
<label for="network-static-subnet">
Static subnet:
<input type="text" id="network-static-subnet" name="staticConfig[subnet]" maxlength="16" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" required>
</label>
<label for="network-static-dns">
Static DNS:
<input type="text" id="network-static-dns" name="staticConfig[dns]" maxlength="16" pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" required>
</label>
<button type="submit">Save</button>
</form>
</div>
</article>
<article>
<div>
<hgroup>
<h3>Available networks</h3>
<p></p>
</hgroup>
<form action="/api/network/scan" id="network-scan">
<figure style="max-height: 25em;">
<table id="networks" role="grid">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">SSID</th>
<th scope="col">Signal</th>
</tr>
</thead>
<tbody></tbody>
</table>
</figure>
<button type="submit">Refresh</button>
</form>
<hr />
<div>
<hgroup>
<h2>WiFi settings</h2>
<p></p>
</hgroup>
<div id="sta-settings-busy" aria-busy="true"></div>
<form action="/api/network/settings" id="sta-settings" class="hidden">
<label for="sta-ssid">
SSID:
<input type="text" id="sta-ssid" name="sta[ssid]" maxlength="32" required>
</label>
<label for="sta-password">
Password:
<input type="password" id="sta-password" name="sta[password]" maxlength="64" required>
</label>
<label for="sta-channel">
Channel:
<input type="number" inputmode="numeric" id="sta-channel" name="sta[channel]" min="0" max="12" step="1" required>
<small>set 0 for auto select</small>
</label>
<button type="submit">Save</button>
</form>
</div>
</div>
</article>
<article>
<div>
<hgroup>
<h2>AP settings</h2>
<p></p>
</hgroup>
<div id="ap-settings-busy" aria-busy="true"></div>
<form action="/api/network/settings" id="ap-settings" class="hidden">
<label for="ap-ssid">
SSID:
<input type="text" id="ap-ssid" name="ap[ssid]" maxlength="32" required>
</label>
<label for="ap-password">
Password:
<input type="text" id="ap-password" name="ap[password]" maxlength="64" required>
</label>
<label for="ap-channel">
Channel:
<input type="number" inputmode="numeric" id="ap-channel" name="ap[channel]" min="1" max="12" step="1" required>
</label>
<button type="submit">Save</button>
</form>
</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">License</a>
<a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
<a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
<a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
<a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
</small>
</footer>
<script src="/static/app.js"></script>
<script>
window.onload = async function () {
try {
const response = await fetch('/api/network/settings', { cache: 'no-cache' });
if (!response.ok) {
throw new Error('Response not valid');
}
const result = await response.json();
setInputValue('#network-hostname', result.hostname);
setCheckboxValue('#network-use-dhcp', result.useDhcp);
setInputValue('#network-static-ip', result.staticConfig.ip);
setInputValue('#network-static-gateway', result.staticConfig.gateway);
setInputValue('#network-static-subnet', result.staticConfig.subnet);
setInputValue('#network-static-dns', result.staticConfig.dns);
setBusy('#network-settings-busy', '#network-settings', false);
setInputValue('#sta-ssid', result.sta.ssid);
setInputValue('#sta-password', result.sta.password);
setInputValue('#sta-channel', result.sta.channel);
setBusy('#sta-settings-busy', '#sta-settings', false);
setInputValue('#ap-ssid', result.ap.ssid);
setInputValue('#ap-password', result.ap.password);
setInputValue('#ap-channel', result.ap.channel);
setBusy('#ap-settings-busy', '#ap-settings', false);
} catch (error) {
console.log(error);
}
setupForm('#network-settings');
setupNetworkScanForm('#network-scan', '#networks');
setupForm('#sta-settings');
setupForm('#ap-settings');
};
</script>
</body>
</html>

804
src_data/settings.html Normal file
View File

@@ -0,0 +1,804 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Settings - OpenTherm Gateway</title>
<link rel="stylesheet" href="/static/pico.min.css">
<link rel="stylesheet" href="/static/app.css" />
</head>
<body>
<header class="container">
<nav>
<ul>
<li><a href="/"><div class="logo">OpenTherm Gateway</div></a></li>
</ul>
<ul>
<li><a href="https://github.com/Laxilef/OTGateway/wiki" role="button" class="secondary" target="_blank">Help</a></li>
</ul>
</nav>
</header>
<main class="container">
<article>
<hgroup>
<h2>Settings</h2>
<p></p>
</hgroup>
<details>
<summary><b>Portal settings</b></summary>
<div>
<div id="portal-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="portal-settings" class="hidden">
<div class="grid">
<label for="portal-login">
Login
<input type="text" id="portal-login" name="portal[login]" maxlength="12" required>
</label>
<label for="portal-password">
Password
<input type="password" id="portal-password" name="portal[password]" maxlength="32" required>
</label>
</div>
<label for="portal-auth">
<input type="checkbox" id="portal-auth" name="portal[auth]" value="true">
Require authentication
</label>
<br />
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>System settings</b></summary>
<div>
<div id="system-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="system-settings" class="hidden">
<fieldset>
<legend>Unit system</legend>
<label>
<input type="radio" id="system-unit-system" name="system[unitSystem]" value="0" />
Metric (celsius, liters, bar)
</label>
<label>
<input type="radio" id="system-unit-system" name="system[unitSystem]" value="1" />
Imperial (fahrenheit, gallons, psi)
</label>
</fieldset>
<fieldset>
<label for="system-status-led-gpio">
Status LED GPIO
<input type="number" inputmode="numeric" id="system-status-led-gpio" name="system[statusLedGpio]" min="0" max="254" step="1">
<small>blank - not use</small>
</label>
</fieldset>
<fieldset>
<legend>Diagnostic</legend>
<label for="system-debug">
<input type="checkbox" id="system-debug" name="system[debug]" value="true">
Debug mode
</label>
<label for="system-serial-enable">
<input type="checkbox" id="system-serial-enable" name="system[serial][enable]" value="true">
Enable Serial port
</label>
<label for="system-telnet-enable">
<input type="checkbox" id="system-telnet-enable" name="system[telnet][enable]" value="true">
Enable Telnet
</label>
<div class="grid">
<label for="system-serial-baudrate">
Serial port baud rate
<input type="number" inputmode="numeric" id="system-serial-baudrate" name="system[serial][baudrate]" min="9600" max="115200" step="1" required>
<small>Available: 9600, 19200, 38400, 57600, 74880, 115200</small>
</label>
<label for="system-telnet-port">
Telnet port
<input type="number" inputmode="numeric" id="system-telnet-port" name="system[telnet][port]" min="1" max="65535" step="1" required>
<small>Default: 23</small>
</label>
</div>
</fieldset>
<fieldset>
<mark>After changing this settings, the ESP must be restarted for the changes to take effect.</mark>
</fieldset>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>Heating settings</b></summary>
<div>
<div id="heating-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="heating-settings" class="hidden">
<div class="grid">
<label for="heating-min-temp">
Minimum temperature
<input type="number" inputmode="numeric" id="heating-min-temp" name="heating[minTemp]" min="0" max="0" step="1" required>
</label>
<label for="heating-max-temp">
Maximum temperature
<input type="number" inputmode="numeric" id="heating-max-temp" name="heating[maxTemp]" min="0" max="0" step="1" required>
</label>
</div>
<div class="grid">
<label for="heating-hysteresis">
Hysteresis
<input type="number" inputmode="numeric" id="heating-hysteresis" name="heating[hysteresis]" min="0" max="5" step="0.05" required>
</label>
<label for="heating-max-modulation">
Max modulation level
<input type="number" inputmode="numeric" id="heating-max-modulation" name="heating[maxModulation]" min="1" max="100" step="1" required>
</label>
</div>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>DHW settings</b></summary>
<div>
<div id="dhw-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="dhw-settings" class="hidden">
<div class="grid">
<label for="dhw-min-temp">
Minimum temperature
<input type="number" inputmode="numeric" id="dhw-min-temp" name="dhw[minTemp]" min="0" max="0" step="1" required>
</label>
<label for="dhw-max-temp">
Maximum temperature
<input type="number" inputmode="numeric" id="dhw-max-temp" name="dhw[maxTemp]" min="0" max="0" step="1" required>
</label>
</div>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>Emergency mode settings</b></summary>
<div>
<div id="emergency-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="emergency-settings" class="hidden">
<fieldset>
<label for="emergency-enable">
<input type="checkbox" id="emergency-enable" name="emergency[enable]" value="true">
Enable
</label>
<small>
<b>!</b> Emergency mode can be useful <u>only</u> when using Equitherm and/or PID (when normal work) and when reporting indoor/outdoor temperature via MQTT or API. In this mode, sensor values that are reported via MQTT/API are not used.
</small>
</fieldset>
<div class="grid">
<label for="emergency-target">
Target temperature
<input type="number" inputmode="numeric" id="emergency-target" name="emergency[target]" min="0" max="0" step="1" required>
<small>
<u>Indoor temperature</u> if Equitherm or PID is <b>enabled</b><br />
<u>Heat carrier temperature</u> if Equitherm and PID <b>is disabled</b>
</small>
</label>
<label for="emergency-treshold-time">
Treshold time <small>(sec)</small>
<input type="number" inputmode="numeric" id="emergency-treshold-time" name="emergency[tresholdTime]" min="60" max="1800" step="1" required>
</label>
</div>
<fieldset>
<legend>Events</legend>
<label for="emergency-on-network-fault">
<input type="checkbox" id="emergency-on-network-fault" name="emergency[onNetworkFault]" value="true">
On network fault
</label>
<label for="emergency-on-mqtt-fault">
<input type="checkbox" id="emergency-on-mqtt-fault" name="emergency[onMqttFault]" value="true">
On MQTT fault
</label>
</fieldset>
<fieldset>
<legend>Using regulators</legend>
<label for="emergency-use-equitherm">
<input type="checkbox" id="emergency-use-equitherm" name="emergency[useEquitherm]" value="true">
<span>
Equitherm <small>(requires at least an external/boiler <u>outdoor</u> sensor)</small>
</span>
</label>
<label for="emergency-use-pid">
<input type="checkbox" id="emergency-use-pid" name="emergency[usePid]" value="true">
<span>
PID <small>(requires at least an external/BLE <u>indoor</u> sensor)</small>
</span>
</label>
</fieldset>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>Equitherm settings</b></summary>
<div>
<div id="equitherm-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="equitherm-settings" class="hidden">
<fieldset>
<label for="equitherm-enable">
<input type="checkbox" id="equitherm-enable" name="equitherm[enable]" value="true">
Enable
</label>
</fieldset>
<div class="grid">
<label for="equitherm-n-factor">
N factor
<input type="number" inputmode="numeric" id="equitherm-n-factor" name="equitherm[n_factor]" min="0.001" max="10" step="0.001" required>
</label>
<label for="equitherm-k-factor">
K factor
<input type="number" inputmode="numeric" id="equitherm-k-factor" name="equitherm[k_factor]" min="0" max="10" step="0.01" required>
</label>
<label for="equitherm-t-factor">
T factor
<input type="number" inputmode="numeric" id="equitherm-t-factor" name="equitherm[t_factor]" min="0" max="10" step="0.01" required>
<small>Not used if PID is enabled</small>
</label>
</div>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>PID settings</b></summary>
<div>
<div id="pid-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="pid-settings" class="hidden">
<fieldset>
<label for="pid-enable">
<input type="checkbox" id="pid-enable" name="pid[enable]" value="true">
Enable
</label>
</fieldset>
<div class="grid">
<label for="pid-p-factor">
P factor
<input type="number" inputmode="numeric" id="pid-p-factor" name="pid[p_factor]" min="0.1" max="1000" step="0.1" required>
</label>
<label for="pid-i-factor">
I factor
<input type="number" inputmode="numeric" id="pid-i-factor" name="pid[i_factor]" min="0" max="100" step="0.001" required>
</label>
<label for="pid-d-factor">
D factor
<input type="number" inputmode="numeric" id="pid-d-factor" name="pid[d_factor]" min="0" max="100000" step="1" required>
</label>
</div>
<label for="pid-dt">
DT <small>in seconds</small>
<input type="number" inputmode="numeric" id="pid-dt" name="pid[dt]" min="30" max="600" step="1" required>
</label>
<hr />
<div class="grid">
<label for="pid-min-temp">
Minimum temperature
<input type="number" inputmode="numeric" id="pid-min-temp" name="pid[minTemp]" min="0" max="0" step="1" required>
</label>
<label for="pid-max-temp">
Maximum temperature
<input type="number" inputmode="numeric" id="pid-max-temp" name="pid[maxTemp]" min="0" max="0" step="1" required>
</label>
</div>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>OpenTherm settings</b></summary>
<div>
<div id="opentherm-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="opentherm-settings" class="hidden">
<fieldset>
<legend>Unit system</legend>
<label>
<input type="radio" id="opentherm-unit-system" name="opentherm[unitSystem]" value="0" />
Metric (celsius)
</label>
<label>
<input type="radio" id="opentherm-unit-system" name="opentherm[unitSystem]" value="1" />
Imperial (fahrenheit)
</label>
</fieldset>
<div class="grid">
<label for="opentherm-in-gpio">
In GPIO
<input type="number" inputmode="numeric" id="opentherm-in-gpio" name="opentherm[inGpio]" min="0" max="254" step="1">
</label>
<label for="opentherm-in-gpio">
Out GPIO
<input type="number" inputmode="numeric" id="opentherm-out-gpio" name="opentherm[outGpio]" min="0" max="254" step="1">
</label>
</div>
<div class="grid">
<label for="opentherm-rx-led-gpio">
RX LED GPIO
<input type="number" inputmode="numeric" id="opentherm-rx-led-gpio" name="opentherm[rxLedGpio]" min="0" max="254" step="1">
<small>blank - not use</small>
</label>
<label for="opentherm-member-id-code">
Master MemberID code
<input type="number" inputmode="numeric" id="opentherm-member-id-code" name="opentherm[memberIdCode]" min="0" max="65535" step="1" required>
</label>
</div>
<fieldset>
<legend>Options</legend>
<label for="opentherm-dhw-present">
<input type="checkbox" id="opentherm-dhw-present" name="opentherm[dhwPresent]" value="true">
DHW present
</label>
<label for="opentherm-sw-mode">
<input type="checkbox" id="opentherm-sw-mode" name="opentherm[summerWinterMode]" value="true">
Summer/winter mode
</label>
<label for="opentherm-heating-ch2-enabled">
<input type="checkbox" id="opentherm-heating-ch2-enabled" name="opentherm[heatingCh2Enabled]" value="true">
Heating CH2 always enabled
</label>
<label for="opentherm-heating-ch1-to-ch2">
<input type="checkbox" id="opentherm-heating-ch1-to-ch2" name="opentherm[heatingCh1ToCh2]" value="true">
Duplicate heating CH1 to CH2
</label>
<label for="opentherm-dhw-to-ch2">
<input type="checkbox" id="opentherm-dhw-to-ch2" name="opentherm[dhwToCh2]" value="true">
Duplicate DHW to CH2
</label>
<label for="opentherm-dhw-blocking">
<input type="checkbox" id="opentherm-dhw-blocking" name="opentherm[dhwBlocking]" value="true">
DHW blocking
</label>
<label for="opentherm-sync-modulation-with-heating">
<input type="checkbox" id="opentherm-sync-modulation-with-heating" name="opentherm[modulationSyncWithHeating]" value="true">
Sync modulation with heating
</label>
<label for="opentherm-get-min-max-temp">
<input type="checkbox" id="opentherm-get-min-max-temp" name="opentherm[getMinMaxTemp]" value="true">
Get min/max temp from boiler
</label>
</fieldset>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>MQTT settings</b></summary>
<div>
<div id="mqtt-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="mqtt-settings" class="hidden">
<fieldset>
<label for="mqtt-enable">
<input type="checkbox" id="mqtt-enable" name="mqtt[enable]" value="true">
Enable
</label>
</fieldset>
<div class="grid">
<label for="mqtt-server">
Server
<input type="text" id="mqtt-server" name="mqtt[server]" maxlength="80" required>
</label>
<label for="mqtt-port">
Port
<input type="number" inputmode="numeric" id="mqtt-port" name="mqtt[port]" min="1" max="65535" step="1" required>
</label>
</div>
<div class="grid">
<label for="mqtt-user">
User
<input type="text" id="mqtt-user" name="mqtt[user]" maxlength="32" required>
</label>
<label for="mqtt-password">
Password
<input type="password" id="mqtt-password" name="mqtt[password]" maxlength="32">
</label>
</div>
<div class="grid">
<label for="mqtt-prefix">
Prefix
<input type="text" id="mqtt-prefix" name="mqtt[prefix]" maxlength="32" required>
</label>
<label for="mqtt-interval">
Publish interval <small>(sec)</small>
<input type="number" inputmode="numeric" id="mqtt-interval" name="mqtt[interval]" min="3" max="60" step="1" required>
</label>
</div>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>Outdoor sensor settings</b></summary>
<div>
<div id="outdoor-sensor-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="outdoor-sensor-settings" class="hidden">
<fieldset>
<legend>Source type</legend>
<label>
<input type="radio" id="outdoor-sensor-type" name="sensors[outdoor][type]" value="0" />
From boiler via OpenTherm
</label>
<label>
<input type="radio" id="outdoor-sensor-type" name="sensors[outdoor][type]" value="1" />
Manual via MQTT/API
</label>
<label>
<input type="radio" id="outdoor-sensor-type" name="sensors[outdoor][type]" value="2" />
External (DS18B20)
</label>
</fieldset>
<label for="outdoor-sensor-gpio">
GPIO
<input type="number" inputmode="numeric" id="outdoor-sensor-gpio" name="sensors[outdoor][gpio]" min="0" max="254" step="1">
</label>
<label for="outdoor-sensor-offset">
Temp offset (calibration)
<input type="number" inputmode="numeric" id="outdoor-sensor-offset" name="sensors[outdoor][offset]" min="-10" max="10" step="0.01" required>
</label>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>Indoor sensor settings</b></summary>
<div>
<div id="indoor-sensor-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="indoor-sensor-settings" class="hidden">
<fieldset>
<legend>Source type</legend>
<label>
<input type="radio" id="indoor-sensor-type" name="sensors[indoor][type]" value="1" />
Manual via MQTT/API
</label>
<label>
<input type="radio" id="indoor-sensor-type" name="sensors[indoor][type]" value="2" />
External (DS18B20)
</label>
<label>
<input type="radio" id="indoor-sensor-type" name="sensors[indoor][type]" value="3" />
BLE device <i>(ONLY for some ESP32 which support BLE)</i>
</label>
</fieldset>
<label for="indoor-sensor-gpio">
GPIO
<input type="number" inputmode="numeric" id="indoor-sensor-gpio" name="sensors[indoor][gpio]" min="0" max="254" step="1">
</label>
<div class="grid">
<label for="indoor-sensor-offset">
Temp offset (calibration)
<input type="number" inputmode="numeric" id="indoor-sensor-offset" name="sensors[indoor][offset]" min="-10" max="10" step="0.01" required>
</label>
<label for="indoor-sensor-ble-addresss">
BLE addresss
<input type="text" id="indoor-sensor-ble-addresss" name="sensors[indoor][bleAddresss]" pattern="([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}">
<small>ONLY for some ESP32 which support BLE</small>
</label>
</div>
<button type="submit">Save</button>
</form>
</div>
</details>
<hr />
<details>
<summary><b>External pump settings</b></summary>
<div>
<div id="extpump-settings-busy" aria-busy="true"></div>
<form action="/api/settings" id="extpump-settings" class="hidden">
<fieldset>
<label for="extpump-use">
<input type="checkbox" id="extpump-use" name="externalPump[use]" value="true">
Use external pump
</label>
</fieldset>
<div class="grid">
<label for="extpump-gpio">
Relay GPIO
<input type="number" inputmode="numeric" id="extpump-gpio" name="externalPump[gpio]" min="0" max="254" step="1">
</label>
<label for="extpump-pc-time">
Post circulation time <small>(min)</small>
<input type="number" inputmode="numeric" id="extpump-pc-time" name="externalPump[postCirculationTime]" min="1" max="120" step="1" required>
</label>
</div>
<div class="grid">
<label for="extpump-as-interval">
Anti stuck interval <small>(days)</small>
<input type="number" inputmode="numeric" id="extpump-as-interval" name="externalPump[antiStuckInterval]" min="1" max="366" step="1" required>
</label>
<label for="extpump-as-time">
Anti stuck time <small>(min)</small>
<input type="number" inputmode="numeric" id="extpump-as-time" name="externalPump[antiStuckTime]" min="1" max="20" step="1" required>
</label>
</div>
<button type="submit">Save</button>
</form>
</div>
</details>
</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">License</a>
<a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
<a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
<a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
<a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
</small>
</footer>
<script src="/static/app.js"></script>
<script>
window.onload = async function () {
const fillData = (data) => {
// System
setCheckboxValue('#system-debug', data.system.debug);
setCheckboxValue('#system-serial-enable', data.system.serial.enable);
setInputValue('#system-serial-baudrate', data.system.serial.baudrate);
setCheckboxValue('#system-telnet-enable', data.system.telnet.enable);
setInputValue('#system-telnet-port', data.system.telnet.port);
setRadioValue('#system-unit-system', data.system.unitSystem);
setInputValue('#system-status-led-gpio', data.system.statusLedGpio < 255 ? data.system.statusLedGpio : '');
setBusy('#system-settings-busy', '#system-settings', false);
// Portal
setCheckboxValue('#portal-auth', data.portal.auth);
setInputValue('#portal-login', data.portal.login);
setInputValue('#portal-password', data.portal.password);
setBusy('#portal-settings-busy', '#portal-settings', false);
// Opentherm
setRadioValue('#opentherm-unit-system', data.opentherm.unitSystem);
setInputValue('#opentherm-in-gpio', data.opentherm.inGpio < 255 ? data.opentherm.inGpio : '');
setInputValue('#opentherm-out-gpio', data.opentherm.outGpio < 255 ? data.opentherm.outGpio : '');
setInputValue('#opentherm-rx-led-gpio', data.opentherm.rxLedGpio < 255 ? data.opentherm.rxLedGpio : '');
setInputValue('#opentherm-member-id-code', data.opentherm.memberIdCode);
setCheckboxValue('#opentherm-dhw-present', data.opentherm.dhwPresent);
setCheckboxValue('#opentherm-sw-mode', data.opentherm.summerWinterMode);
setCheckboxValue('#opentherm-heating-ch2-enabled', data.opentherm.heatingCh2Enabled);
setCheckboxValue('#opentherm-heating-ch1-to-ch2', data.opentherm.heatingCh1ToCh2);
setCheckboxValue('#opentherm-dhw-to-ch2', data.opentherm.dhwToCh2);
setCheckboxValue('#opentherm-dhw-blocking', data.opentherm.dhwBlocking);
setCheckboxValue('#opentherm-sync-modulation-with-heating', data.opentherm.modulationSyncWithHeating);
setCheckboxValue('#opentherm-get-min-max-temp', data.opentherm.getMinMaxTemp);
setBusy('#opentherm-settings-busy', '#opentherm-settings', false);
// MQTT
setCheckboxValue('#mqtt-enable', data.mqtt.enable);
setInputValue('#mqtt-server', data.mqtt.server);
setInputValue('#mqtt-port', data.mqtt.port);
setInputValue('#mqtt-user', data.mqtt.user);
setInputValue('#mqtt-password', data.mqtt.password);
setInputValue('#mqtt-prefix', data.mqtt.prefix);
setInputValue('#mqtt-interval', data.mqtt.interval);
setBusy('#mqtt-settings-busy', '#mqtt-settings', false);
// Outdoor sensor
setRadioValue('#outdoor-sensor-type', data.sensors.outdoor.type);
setInputValue('#outdoor-sensor-gpio', data.sensors.outdoor.gpio < 255 ? data.sensors.outdoor.gpio : '');
setInputValue('#outdoor-sensor-offset', data.sensors.outdoor.offset);
setBusy('#outdoor-sensor-settings-busy', '#outdoor-sensor-settings', false);
// Indoor sensor
setRadioValue('#indoor-sensor-type', data.sensors.indoor.type);
setInputValue('#indoor-sensor-gpio', data.sensors.indoor.gpio < 255 ? data.sensors.indoor.gpio : '');
setInputValue('#indoor-sensor-offset', data.sensors.indoor.offset);
setInputValue('#indoor-sensor-ble-addresss', data.sensors.indoor.bleAddresss);
setBusy('#indoor-sensor-settings-busy', '#indoor-sensor-settings', false);
// Extpump
setCheckboxValue('#extpump-use', data.externalPump.use);
setInputValue('#extpump-gpio', data.externalPump.gpio < 255 ? data.externalPump.gpio : '');
setInputValue('#extpump-pc-time', data.externalPump.postCirculationTime);
setInputValue('#extpump-as-interval', data.externalPump.antiStuckInterval);
setInputValue('#extpump-as-time', data.externalPump.antiStuckTime);
setBusy('#extpump-settings-busy', '#extpump-settings', false);
// Heating
setInputValue('#heating-min-temp', data.heating.minTemp, {
"min": data.system.unitSystem == 0 ? 0 : 32,
"max": data.system.unitSystem == 0 ? 99 : 211
});
setInputValue('#heating-max-temp', data.heating.maxTemp, {
"min": data.system.unitSystem == 0 ? 1 : 33,
"max": data.system.unitSystem == 0 ? 100 : 212
});
setInputValue('#heating-hysteresis', data.heating.hysteresis);
setInputValue('#heating-max-modulation', data.heating.maxModulation);
setBusy('#heating-settings-busy', '#heating-settings', false);
// DHW
setInputValue('#dhw-min-temp', data.dhw.minTemp, {
"min": data.system.unitSystem == 0 ? 0 : 32,
"max": data.system.unitSystem == 0 ? 99 : 211
});
setInputValue('#dhw-max-temp', data.dhw.maxTemp, {
"min": data.system.unitSystem == 0 ? 1 : 33,
"max": data.system.unitSystem == 0 ? 100 : 212
});
setBusy('#dhw-settings-busy', '#dhw-settings', false);
// Emergency mode
setCheckboxValue('#emergency-enable', data.emergency.enable);
setInputValue('#emergency-treshold-time', data.emergency.tresholdTime);
setCheckboxValue('#emergency-use-equitherm', data.emergency.useEquitherm);
setCheckboxValue('#emergency-use-pid', data.emergency.usePid);
setCheckboxValue('#emergency-on-network-fault', data.emergency.onNetworkFault);
setCheckboxValue('#emergency-on-mqtt-fault', data.emergency.onMqttFault);
setInputValue('#emergency-target', data.emergency.target, {
"min": (!data.emergency.useEquitherm && !data.emergency.usePid) ? data.heating.minTemp : 10,
"max": (!data.emergency.useEquitherm && !data.emergency.usePid) ? data.heating.maxTemp : 30,
});
setBusy('#emergency-settings-busy', '#emergency-settings', false);
// Equitherm
setCheckboxValue('#equitherm-enable', data.equitherm.enable);
setInputValue('#equitherm-n-factor', data.equitherm.n_factor);
setInputValue('#equitherm-k-factor', data.equitherm.k_factor);
setInputValue('#equitherm-t-factor', data.equitherm.t_factor);
setBusy('#equitherm-settings-busy', '#equitherm-settings', false);
// PID
setCheckboxValue('#pid-enable', data.pid.enable);
setInputValue('#pid-p-factor', data.pid.p_factor);
setInputValue('#pid-i-factor', data.pid.i_factor);
setInputValue('#pid-d-factor', data.pid.d_factor);
setInputValue('#pid-dt', data.pid.dt);
setInputValue('#pid-min-temp', data.pid.minTemp, {
"min": 0,
"max": data.system.unitSystem == 0 ? 99 : 211
});
setInputValue('#pid-max-temp', data.pid.maxTemp, {
"min": 1,
"max": data.system.unitSystem == 0 ? 100 : 212
});
setBusy('#pid-settings-busy', '#pid-settings', false);
};
try {
const response = await fetch('/api/settings', { cache: 'no-cache' });
if (!response.ok) {
throw new Error('Response not valid');
}
const result = await response.json();
fillData(result);
setupForm('#portal-settings', fillData);
setupForm('#system-settings', fillData);
setupForm('#heating-settings', fillData);
setupForm('#dhw-settings', fillData);
setupForm('#emergency-settings', fillData);
setupForm('#equitherm-settings', fillData);
setupForm('#pid-settings', fillData);
setupForm('#opentherm-settings', fillData);
setupForm('#mqtt-settings', fillData);
setupForm('#outdoor-sensor-settings', fillData);
setupForm('#indoor-sensor-settings', fillData);
setupForm('#extpump-settings', fillData);
} catch (error) {
console.log(error);
}
};
</script>
</body>
</html>

108
src_data/upgrade.html Normal file
View File

@@ -0,0 +1,108 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Upgrade - OpenTherm Gateway</title>
<link rel="stylesheet" href="/static/pico.min.css">
<link rel="stylesheet" href="/static/app.css">
</head>
<body>
<header class="container">
<nav>
<ul>
<li><a href="/"><div class="logo">OpenTherm Gateway</div></a></li>
</ul>
<ul>
<li><a href="https://github.com/Laxilef/OTGateway/wiki" role="button" class="secondary" target="_blank">Help</a></li>
</ul>
</nav>
</header>
<main class="container">
<article>
<div>
<hgroup>
<h2>Backup & restore</h2>
<p>
In this section you can save and restore a backup of ALL settings.
</p>
</hgroup>
<form action="/api/backup/restore" id="restore">
<label for="restore-file">
Settings file:
<input type="file" name="settings" id="restore-file" accept=".json">
</label>
<div class="grid">
<button type="submit">Restore</button>
<button type="button" class="secondary" onclick="window.location='/api/backup/save';">Backup</button>
</div>
</form>
</div>
</article>
<article>
<div>
<hgroup>
<h2>Upgrade</h2>
<p>
In this section you can upgrade the firmware and filesystem of your device.<br />
Latest releases can be downloaded from the <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank">Releases page</a> of the project repository.
</p>
</hgroup>
<form action="/api/upgrade" id="upgrade">
<fieldset class="primary">
<label for="firmware-file">
Firmware:
<div class="grid">
<input type="file" name="firmware" id="firmware-file" accept=".bin">
<button type="button" class="upgrade-firmware-result hidden" disabled></button>
</div>
</label>
<label for="filesystem-file">
Filesystem:
<div class="grid">
<input type="file" name="filesystem" id="filesystem-file" accept=".bin">
<button type="button" class="upgrade-filesystem-result hidden" disabled></button>
</div>
</label>
</fieldset>
<ul>
<li><mark>After a successful upgrade the filesystem, ALL settings will be reset to default values! Save backup before upgrading.</mark></li>
<li><mark>After a successful upgrade, the device will automatically reboot after 10 seconds.</mark></li>
</ul>
<button type="submit">Upgrade</button>
</form>
</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">License</a>
<a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary">Source code</a>
<a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary">Help</a>
<a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary">Issue & questions</a>
<a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary">Releases</a>
</small>
</footer>
<script src="/static/app.js"></script>
<script>
window.onload = async function () {
setupRestoreBackupForm('#restore');
setupUpgradeForm('#upgrade');
};
</script>
</body>
</html>